📄 parser.jj
字号:
{ /* * in REFMOD2, we don't want to bind the whitespace and \n like we * do when closing a directive. */ <REFMOD2_RPAREN: ")"> { /* * need to simply switch back to REFERENCE, not drop down the stack * because we can (infinitely) chain, ala * $foo.bar().blargh().woogie().doogie() */ SwitchTo( REFERENCE ); }}/*---------------------------------------------- * * escape "\\" handling for the built-in directives * *--------------------------------------------- */TOKEN:{ /* * We have to do this, because we want these to be a Text node, and * whatever follows to be peer to this text in the tree. * * We need to touch the ASTs for these, because we want an even # of \'s * to render properly in front of the block * * This is really simplistic. I actually would prefer to find them in * grammatical context, but I am neither smart nor rested, a receipe * for disaster, another long night with Mr. Parser, or both. */ <ESCAPE_DIRECTIVE : (<DOUBLE_ESCAPE>)* "\\#" <WORD> >}/* * needed because #set is so wacky in it's desired behavior. We want set * to eat any preceeding whitespace so it is invisible in formatting. * (As it should be.) If this works well, I am going to chuck the whole MORE: * token abomination. */TOKEN:{ <SET_DIRECTIVE: (" "|"\t")* "#set" > { if (! inComment) { inDirective = true; if ( debugPrint ) System.out.print("#set : going to " + DIRECTIVE ); stateStackPush(); inSet = true; SwitchTo(DIRECTIVE); } }}<*>MORE :{ /* * Note : DOLLARBANG is a duplicate of DOLLAR. They must be identical. */ <DOLLAR: ("\\")* "$"> { if (! inComment) { /* * if we find ourselves in REFERENCE, we need to pop down * to end the previous ref */ if (curLexState == REFERENCE) { inReference = false; stateStackPop(); } inReference = true; if ( debugPrint ) System.out.print( "$ : going to " + REFERENCE ); stateStackPush(); SwitchTo(REFERENCE); } }| <DOLLARBANG: ("\\")* "$" ("\\")* "!"> { if (! inComment) { /* * if we find ourselves in REFERENCE, we need to pop down * to end the previous ref */ if (curLexState == REFERENCE) { inReference = false; stateStackPop(); } inReference = true; if ( debugPrint ) System.out.print( "$! : going to " + REFERENCE ); stateStackPush(); SwitchTo(REFERENCE); } }| "##" { if (!inComment) { if (curLexState == REFERENCE) { inReference = false; stateStackPop(); } inComment = true; stateStackPush(); SwitchTo(IN_SINGLE_LINE_COMMENT); } }| <"#**" ~["#"]> { input_stream.backup(1); inComment = true; stateStackPush(); SwitchTo( IN_FORMAL_COMMENT); }| "#*" { inComment=true; stateStackPush(); SwitchTo( IN_MULTI_LINE_COMMENT ); }| <HASH : "#" > { if (! inComment) { /* * We can have the situation where #if($foo)$foo#end. * We need to transition out of REFERENCE before going to DIRECTIVE. * I don't really like this, but I can't think of a legal way * you are going into DIRECTIVE while in REFERENCE. -gmj */ if (curLexState == REFERENCE || curLexState == REFMODIFIER ) { inReference = false; stateStackPop(); } inDirective = true; if ( debugPrint ) System.out.print("# : going to " + DIRECTIVE ); stateStackPush(); SwitchTo(PRE_DIRECTIVE); } }}TOKEN :{ <DOUBLE_ESCAPE : "\\\\">| <ESCAPE: "\\" >| <TEXT: (~["$", "#", "\\"])+ >}/* ----------------------------------------------------------------------- * * *_COMMENT Lexical tokens * *-----------------------------------------------------------------------*/<IN_SINGLE_LINE_COMMENT>TOKEN :{ <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > { inComment = false; stateStackPop(); }}<IN_FORMAL_COMMENT>TOKEN :{ <FORMAL_COMMENT: "*#" > { inComment = false; stateStackPop(); }}<IN_MULTI_LINE_COMMENT>TOKEN :{ <MULTI_LINE_COMMENT: "*#" > { inComment = false; stateStackPop(); }}<IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>MORE :{ < ~[] >}/* ----------------------------------------------------------------------- * * DIRECTIVE Lexical State (some of it, anyway) * * ---------------------------------------------------------------------- */<DIRECTIVE,REFMOD2>TOKEN:{ <WHITESPACE : ([" ","\t"])+ >}<DIRECTIVE,REFMOD2>TOKEN :{// <STRING_LITERAL: ( "\"" ( ~["\"","\n","\r"] )* "\"" ) | ( "'" ( ~["'","\n","\r"] )* "'" ) > < STRING_LITERAL: ("\"" ( (~["\"","\\","\n","\r"]) | ("\\" ( ["n","t","b","r","f","\\","'","\""] | ["0"-"7"] ( ["0"-"7"] )? | ["0"-"3"] ["0"-"7"] ["0"-"7"] ) ) | ( "\\" (" ")* "\n") )* "\"" ) | ("\'" ( (~["\'","\n","\r"]) | ( "\\" (" ")* "\n") )* "\'" ) > { /* * - if we are in DIRECTIVE and haven't seen ( yet, then also drop out. * don't forget to account for the beloved yet wierd #set * - finally, if we are in REFMOD2 (remember : $foo.bar( ) then " is ok! */ if( curLexState == DIRECTIVE && !inSet && lparen == 0) stateStackPop(); }}<REFERENCE,DIRECTIVE,REFMODIFIER,REFMOD2>TOKEN:{ <TRUE: "true">| <FALSE: "false">}<DIRECTIVE>TOKEN :{ <NEWLINE: "\n" | "\r" | "\r\n" > { if ( debugPrint ) System.out.println(" NEWLINE :"); stateStackPop(); if (inSet) inSet = false; if (inDirective) inDirective = false; }}<DIRECTIVE>TOKEN :{ <MINUS: "-">| <PLUS: "+">| <MULTIPLY: "*">| <DIVIDE: "/">| <MODULUS: "%">| <LOGICAL_AND: "&&">| <LOGICAL_OR: "||">| <LOGICAL_LT: "<">| <LOGICAL_LE: "<=">| <LOGICAL_GT: ">">| <LOGICAL_GE: ">=">| <LOGICAL_EQUALS: "==">| <LOGICAL_NOT_EQUALS: "!=">| <LOGICAL_NOT: "!">| <EQUALS: "=" >}<PRE_DIRECTIVE>TOKEN :{ <END: "end" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? > { inDirective = false; stateStackPop(); }| <IF_DIRECTIVE: "if"> { SwitchTo(DIRECTIVE); }| <ELSEIF_DIRECTIVE: "elseif"> { SwitchTo(DIRECTIVE); }| <ELSE_DIRECTIVE: "else" ( ( " " | "\t" )* ( "\n" | "\r" | "\r\n" ) )? > { inDirective = false; stateStackPop(); }| <STOP_DIRECTIVE: "stop"> { matchedToken.kind = EOF; fileDepth = 0; }}<PRE_DIRECTIVE,DIRECTIVE,REFMOD2>TOKEN:{ <#DIGIT: [ "0"-"9" ] >| <NUMBER_LITERAL: ("-")? (<DIGIT>)+ > { /* * check to see if we are in set * ex. #set $foo = $foo + 3 * because we want to handle the \n after */ if ( lparen == 0 && !inSet && curLexState != REFMOD2) { stateStackPop(); } }}<PRE_DIRECTIVE,DIRECTIVE>TOKEN:{ <#LETTER: [ "a"-"z", "A" - "Z" ] >| <#DIRECTIVE_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "_" ] >| <WORD: ( <LETTER> | ["_"]) (<DIRECTIVE_CHAR>)* >}/* ----------------------------------------------------------------------- * * REFERENCE Lexical States * * This is more than a single state, because of the structure of * the VTL references. We use three states because the set of tokens * for each state can be different. * * $foo.bar( "arg" ) * ^ ^ ^ * | | | * ----------- > REFERENCE : state initiated by the '$' character. Continues * | | until end of the reference, or the . character. * |------ > REFMODIFIER : state switched to when the <DOT> is encountered. * | note that this is a switch, not a push. See notes at bottom * | re stateStack. * |-- > REFMOD2 : state switch to when the LPAREN is encountered. * again, this is a switch, not a push. * * ---------------------------------------------------------------------------- */<REFERENCE,REFMODIFIER,REFMOD2>TOKEN :{ <#ALPHA_CHAR: ["a"-"z", "A"-"Z"] >| <#ALPHANUM_CHAR: [ "a"-"z", "A"-"Z", "0"-"9" ] >| <#IDENTIFIER_CHAR: [ "a"-"z", "A"-"Z", "0"-"9", "-", "_" ] >| <IDENTIFIER: ( <ALPHA_CHAR> | ["_"]) (<IDENTIFIER_CHAR>)* >| <DOT: "." <ALPHA_CHAR>> { /* * push the alpha char back into the stream so the following identifier * is complete */ input_stream.backup(1); /* * and munge the <DOT> so we just get a . when we have normal text that * looks like a ref.ident */ matchedToken.image = "."; if ( debugPrint ) System.out.print("DOT : switching to " + REFMODIFIER); SwitchTo(REFMODIFIER); }| <LCURLY: "{">| <RCURLY: "}"> { stateStackPop(); }}<REFERENCE,REFMODIFIER,REFMOD2>SPECIAL_TOKEN :{ <REFERENCE_TERMINATOR: ~[] > { /* * push every terminator character back into the stream */ input_stream.backup(1); inReference = false; if ( debugPrint ) System.out.print("REF_TERM :"); stateStackPop(); }}<PRE_DIRECTIVE>SPECIAL_TOKEN :{ <DIRECTIVE_TERMINATOR: ~[] > { if ( debugPrint ) System.out.print("DIRECTIVE_TERM :"); input_stream.backup(1); inDirective = false; stateStackPop(); }}/** * This method is what starts the whole parsing * process. After the parsing is complete and * the template has been turned into an AST, * this method returns the root of AST which * can subsequently be traversed by a visitor * which implements the ParserVisitor interface * which is generated automatically by JavaCC
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -