JSP compilation into Servlet (1) syntax tree generation-Syntax Parsing
Generally, a syntax tree is formed after a statement is deduced according to certain rules. This tree structure facilitates the description of the statement structure hierarchy. Similarly, Jaspe generates a tree after parsing JSP syntax. Each node of this tree contains different information. However, for JSP, the parsed syntax tree is relatively simple, there is only one parent node and n subnodes. For example, node1 is a comment node that represents an image. The node contains an attribute that represents a comment string; node2 may be an expression node that represents an expression like <% = a + B %>. The node contains an attribute that represents the expression, and other nodes may also represent other syntaxes of JSP, with this tree, we can easily generate the corresponding Servlet.
Now let's look at how to parse and generate this tree,
① First define the tree data structure, where parent points to the parent node, nodes is the child node of this node, and nodes should be an ordered list, so that it can be consistent with the resolution order. In addition, because each Node has different attributes, the Node class only provides some common attributes, and other attributes of different nodes need to inherit the Node for additional implementation.
Public class Node {
Private Node parent;
Private List Nodes;
Private String text;
Private Attributes attrs;
}
Public class RootNode {}
Public class CommentNode {}
Public class PageNode {}
Public class extends denode {}
Public class TaglibNode {}
② A tool class for reading JSP files is required. This tool class mainly provides character operations on JSP files, where a cursor variable is used to indicate the current parsing location, the main method is to determine whether the hasMoreInput method reaches the end of the file, obtain the nextChar method of the next character, and obtain the getText method of a string consisting of characters within a certain range, match the matches method that contains a string, skip the skipSpaces method of the space character, and jump to the skipUntil method of a string. With these auxiliary operations, you can start to read the parsing syntax.
Public class JspReader {
Private int cursor;
Public int getCursor () {return cursor ;}
Boolean hasMoreInput (){...}
Public int nextChar (){...}
Public String getText (int start, int end ){...}
Boolean matches (String string ){...}
Int skipSpaces (){...}
Int skipUntil (String limit ){...}
}
③ A JSP syntax parser is required to parse the JSP. Annotation syntax, <@ page... /%> page command, <[email protected] .. /%> contains commands, <[email protected] .. /%> label command. Assume that the index. jsp parses the syntax and matches <% -- to indicate the annotation syntax. Obtain the annotation text and create a commentNode node as the child node of the root node, if <% @ is matched, there are three possibilities, so further Parsing is required, that is, parsing of corresponding page commands, including instructions and tag commands. The last Parsing is a syntax tree.
Public class Parser {
Public RootNode parse (){
JspReader reader = new JspReader ("index. jsp ");
RootNode root = new RootNode ();
While (reader. hasMoreInput ()){
If (reader. matches ("<% --")){
Int start = reader. getCursor ();
Reader. skipUntil ("-- %> ");
Int end = reader. getCursor ();
CommentNode commentNode = new CommentNode ();
CommentNode. setText (reader. getText (start, stop ));
CommentNode. setParent (parent );
Parent. getList (). add (commentNode );
} Else if (reader. matches ("<% @")){
If (reader. matches ("page ")){
Parse the attributes in <[email protected] ../%> to generate attrs
PageNode pageNode = new PageNode ();
PageNode. setAttributes (attrs );
PageNode. setParent (parent );
Parent. getList (). add (pageNode );
} Else if (reader. matches ("include ")){
Parse the attributes in <[email protected] ../%> to generate attrs
IncludeNode includeNode = new IncludeNode ();
IncludeNode. setAttributes (attrs );
IncludeNode. setParent (parent );
Parent. getList (). add (includeNode );
} Else if (reader. matches ("taglib ")){
Parse the attributes in <[email protected] ../%> to generate attrs
TaglibNode taglibNode = new TaglibNode ();
TaglibNode. setAttributes (attrs );
TaglibNode. setParent (parent );
Parent. getList (). add (taglibNode );
}
}
}
Return root;
}
}