📄 antlr.g
字号:
;notSet{ int line = LT(1).getLine(); int col = LT(1).getColumn(); GrammarAST subrule=null;} : n:NOT^ ( notTerminal | block ) {#notSet.setLine(line); #notSet.setColumn(col);} ;tree : TREE_BEGIN^ element ( element )+ RPAREN! ;/** matches ENBF blocks (and sets via block rule) */ebnf!{ int line = LT(1).getLine(); int col = LT(1).getColumn();} : b:block ( QUESTION {#ebnf=#([OPTIONAL,"?"],#b);} | STAR {#ebnf=#([CLOSURE,"*"],#b);} | PLUS {#ebnf=#([POSITIVE_CLOSURE,"+"],#b);} | IMPLIES! // syntactic predicate { if ( gtype==COMBINED_GRAMMAR && Character.isUpperCase(currentRuleName.charAt(0)) ) { // ignore for lexer rules in combined #ebnf = #(#[SYNPRED,"=>"],#b); } else { // create manually specified (...)=> predicate; // convert to sempred #ebnf = createSynSemPredFromBlock(#b, SYN_SEMPRED); } } | ROOT {#ebnf = #(#ROOT, #b);} | BANG {#ebnf = #(#BANG, #b);} | {#ebnf = #b;} ) {#ebnf.setLine(line); #ebnf.setColumn(col);} ;range!{GrammarAST subrule=null, root=null;} : c1:CHAR_LITERAL RANGE c2:CHAR_LITERAL { GrammarAST r = #[CHAR_RANGE,".."]; r.setLine(c1.getLine()); r.setColumn(c1.getColumn()); #range = #(r, #c1, #c2); root = #range; }// (subrule=ebnfSuffix[root,false] {#range=subrule;})? ;terminal{GrammarAST ebnfRoot=null, subrule=null;} : cl:CHAR_LITERAL^ (ROOT^|BANG^)? | tr:TOKEN_REF^ ( ARG_ACTION )? // Args are only valid for lexer rules (ROOT^|BANG^)? | sl:STRING_LITERAL (ROOT^|BANG^)? | wi:WILDCARD (ROOT^|BANG^)? ;ebnfSuffix[GrammarAST elemAST, boolean inRewrite] returns [GrammarAST subrule=null]{GrammarAST ebnfRoot=null;} :! ( QUESTION {ebnfRoot = #[OPTIONAL,"?"];} | STAR {ebnfRoot = #[CLOSURE,"*"];} | PLUS {ebnfRoot = #[POSITIVE_CLOSURE,"+"];} ) { GrammarAST save = currentBlockAST; ebnfRoot.setLine(elemAST.getLine()); ebnfRoot.setColumn(elemAST.getColumn()); GrammarAST blkRoot = #[BLOCK,"BLOCK"]; currentBlockAST = blkRoot; GrammarAST eob = #[EOB,"<end-of-block>"]; eob.setLine(elemAST.getLine()); eob.setColumn(elemAST.getColumn()); GrammarAST alt = #(#[ALT,"ALT"],elemAST,#[EOA,"<end-of-alt>"]); if ( !inRewrite ) { prefixWithSynPred(alt); } subrule = #(ebnfRoot, #(blkRoot,alt,eob) ); currentBlockAST = save; } ;notTerminal : cl:CHAR_LITERAL | tr:TOKEN_REF | STRING_LITERAL ;idList : (id)+ ;id : TOKEN_REF {#id.setType(ID);} | RULE_REF {#id.setType(ID);} ;/** Match anything that looks like an ID and return tree as token type ID */idToken : TOKEN_REF {#idToken.setType(ID);} | RULE_REF {#idToken.setType(ID);} ;// R E W R I T E S Y N T A Xrewrite{ GrammarAST root = new GrammarAST();} :! ( options { warnWhenFollowAmbig=false;} : rew:REWRITE pred:SEMPRED alt:rewrite_alternative {root.addChild( #(#rew, #pred, #alt) );} { #pred.setEnclosingRule(currentRuleName); #rew.setEnclosingRule(currentRuleName); } )* rew2:REWRITE alt2:rewrite_alternative { root.addChild( #(#rew2, #alt2) ); #rewrite = (GrammarAST)root.getFirstChild(); } | ;rewrite_block : lp:LPAREN^ {#lp.setType(BLOCK); #lp.setText("BLOCK");} rewrite_alternative RPAREN! { GrammarAST eob = #[EOB,"<end-of-block>"]; eob.setLine(lp.getLine()); eob.setColumn(lp.getColumn()); #rewrite_block.addChild(eob); } ;rewrite_alternative{ GrammarAST eoa = #[EOA, "<end-of-alt>"]; GrammarAST altRoot = #[ALT,"ALT"]; altRoot.setLine(LT(1).getLine()); altRoot.setColumn(LT(1).getColumn());} : {grammar.buildTemplate()}? rewrite_template | {grammar.buildAST()}? ( rewrite_element )+ { if ( #rewrite_alternative==null ) { #rewrite_alternative = #(altRoot,#[EPSILON,"epsilon"],eoa); } else { #rewrite_alternative = #(altRoot, #rewrite_alternative,eoa); } } | {#rewrite_alternative = #(altRoot,#[EPSILON,"epsilon"],eoa);} ;rewrite_element{GrammarAST subrule=null;} : t:rewrite_atom ( subrule=ebnfSuffix[#t,true] {#rewrite_element=subrule;} )? | rewrite_ebnf | tr:rewrite_tree ( subrule=ebnfSuffix[#tr,true] {#rewrite_element=subrule;} )? ;rewrite_atom{GrammarAST subrule=null;} : cl:CHAR_LITERAL | tr:TOKEN_REF^ (ARG_ACTION)? // for imaginary nodes | rr:RULE_REF | sl:STRING_LITERAL |! d:DOLLAR i:id // reference to a label in a rewrite rule { #rewrite_atom = #[LABEL,i_AST.getText()]; #rewrite_atom.setLine(#d.getLine()); #rewrite_atom.setColumn(#d.getColumn()); #rewrite_atom.setEnclosingRule(currentRuleName); } | ACTION ;rewrite_ebnf!{ int line = LT(1).getLine(); int col = LT(1).getColumn();} : b:rewrite_block ( QUESTION {#rewrite_ebnf=#([OPTIONAL,"?"],#b);} | STAR {#rewrite_ebnf=#([CLOSURE,"*"],#b);} | PLUS {#rewrite_ebnf=#([POSITIVE_CLOSURE,"+"],#b);} ) {#rewrite_ebnf.setLine(line); #rewrite_ebnf.setColumn(col);} ;rewrite_tree : TREE_BEGIN^ rewrite_atom ( rewrite_element )* RPAREN! ;/** Build a tree for a template rewrite: ^(TEMPLATE (ID|ACTION) ^(ARGLIST ^(ARG ID ACTION) ...) ) where ARGLIST is always there even if no args exist. ID can be "template" keyword. If first child is ACTION then it's an indirect template ref -> foo(a={...}, b={...}) -> ({string-e})(a={...}, b={...}) // e evaluates to template name -> {%{$ID.text}} // create literal template from string (done in ActionTranslator) -> {st-expr} // st-expr evaluates to ST */rewrite_template{Token st=null;} : // -> template(a={...},...) "..." {LT(1).getText().equals("template")}? // inline rewrite_template_head {st=LT(1);} ( DOUBLE_QUOTE_STRING_LITERAL! | DOUBLE_ANGLE_STRING_LITERAL! ) {#rewrite_template.addChild(#[st]);} | // -> foo(a={...}, ...) rewrite_template_head | // -> ({expr})(a={...}, ...) rewrite_indirect_template_head | // -> {...} ACTION ;/** -> foo(a={...}, ...) */rewrite_template_head : id lp:LPAREN^ {#lp.setType(TEMPLATE); #lp.setText("TEMPLATE");} rewrite_template_args RPAREN! ;/** -> ({expr})(a={...}, ...) */rewrite_indirect_template_head : lp:LPAREN^ {#lp.setType(TEMPLATE); #lp.setText("TEMPLATE");} ACTION RPAREN! LPAREN! rewrite_template_args RPAREN! ;rewrite_template_args : rewrite_template_arg (COMMA! rewrite_template_arg)* {#rewrite_template_args = #(#[ARGLIST,"ARGLIST"], rewrite_template_args);} | {#rewrite_template_args = #[ARGLIST,"ARGLIST"];} ;rewrite_template_arg : id a:ASSIGN^ {#a.setType(ARG); #a.setText("ARG");} ACTION ;class ANTLRLexer extends Lexer;options { k=2; exportVocab=ANTLR; testLiterals=false; interactive=true; charVocabulary='\003'..'\377';}{ /** advance the current column number by one; don't do tabs. * we want char position in line to be sent to AntlrWorks. */ public void tab() { setColumn( getColumn()+1 ); }}WS : ( ' ' | '\t' | ('\r')? '\n' {newline();} ) ;COMMENT : ( SL_COMMENT | t:ML_COMMENT {$setType(t.getType());} ) ;protectedSL_COMMENT : "//" ( (" $ANTLR")=> " $ANTLR " SRC ('\r')? '\n' // src directive | ( options {greedy=false;} : . )* ('\r')? '\n' ) { newline(); } ;protectedML_COMMENT : "/*" ( { LA(2)!='/' }? '*' {$setType(DOC_COMMENT);} | ) ( options { greedy=false; // make it exit upon "*/" } : '\r' '\n' {newline();} | '\n' {newline();} | ~('\n'|'\r') )* "*/" ;OPEN_ELEMENT_OPTION : '<' ;CLOSE_ELEMENT_OPTION : '>' ;AMPERSAND : '@';COMMA : ',';QUESTION : '?' ;TREE_BEGIN : "^(" ;LPAREN: '(' ;RPAREN: ')' ;COLON : ':' ;STAR: '*' ;PLUS: '+' ;ASSIGN : '=' ;PLUS_ASSIGN : "+=" ;IMPLIES : "=>" ;REWRITE : "->" ;SEMI: ';' ;ROOT : '^' ;BANG : '!' ;OR : '|' ;WILDCARD : '.' ;RANGE : ".." ;NOT : '~' ;RCURLY: '}' ;DOLLAR : '$' ;CHAR_LITERAL : '\'' (ESC|'\n'{newline();}|~'\'')* '\'' { StringBuffer s = Grammar.getUnescapedStringFromGrammarStringLiteral($getText); if ( s.length()>1 ) { $setType(STRING_LITERAL); } } ;DOUBLE_QUOTE_STRING_LITERAL : '"' ('\\'! '"'|'\n'{newline();}|~'"')* '"' ;DOUBLE_ANGLE_STRING_LITERAL : "<<" (options {greedy=false;}:'\n'{newline();}|.)* ">>" ;protectedESC : '\\' ( 'n' | 'r' | 't' | 'b' | 'f' | '"' | '\'' | '\\' | '>' | ('0'..'3') ( options { warnWhenFollowAmbig = false; } : ('0'..'9') ( options { warnWhenFollowAmbig = false; } : '0'..'9' )? )? | ('4'..'7') ( options { warnWhenFollowAmbig = false; } : ('0'..'9') )? | 'u' XDIGIT XDIGIT XDIGIT XDIGIT | . // unknown, leave as it is ) ;protectedDIGIT : '0'..'9' ;protectedXDIGIT : '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ;INT : ('0'..'9')+ ;ARG_ACTION : NESTED_ARG_ACTION ;protectedNESTED_ARG_ACTION : '['! ( NESTED_ARG_ACTION | '\r' '\n' {newline();} | '\n' {newline();} | ACTION_STRING_LITERAL | ~']' )* ']'! ;ACTION{int actionLine=getLine(); int actionColumn = getColumn(); } : NESTED_ACTION ( '?'! {_ttype = SEMPRED;} )? { Token t = makeToken(_ttype); String action = $getText; action = action.substring(1,action.length()-1); t.setText(action); t.setLine(actionLine); // set action line to start t.setColumn(actionColumn); $setToken(t); } ;protectedNESTED_ACTION : '{' ( options { greedy = false; // exit upon '}' } : ( '\r' '\n' {newline();} | '\n' {newline();} ) | NESTED_ACTION | ACTION_CHAR_LITERAL | COMMENT | ACTION_STRING_LITERAL | . )* '}' ;protectedACTION_CHAR_LITERAL : '\'' (ACTION_ESC|'\n'{newline();}|~'\'')* '\'' ;protectedACTION_STRING_LITERAL : '"' (ACTION_ESC|'\n'{newline();}|~'"')* '"' ;protectedACTION_ESC : "\\'" | "\\\"" | '\\' ~('\''|'"') ;TOKEN_REFoptions { testLiterals = true; } : 'A'..'Z' ( // scarf as many letters/numbers as you can options { warnWhenFollowAmbig=false; } : 'a'..'z'|'A'..'Z'|'_'|'0'..'9' )* ;// we get a warning here when looking for options '{', but it works rightRULE_REF{ int t=0;} : t=INTERNAL_RULE_REF {_ttype=t;} ( {t==OPTIONS}? WS_LOOP ('{' {_ttype = OPTIONS;})? | {t==TOKENS}? WS_LOOP ('{' {_ttype = TOKENS;})? | ) ;protectedWS_LOOP : ( // grab as much WS as you can options { greedy=true; } : WS | COMMENT )* ;protectedINTERNAL_RULE_REF returns [int t]{ t = RULE_REF;} : 'a'..'z' ( // scarf as many letters/numbers as you can options { warnWhenFollowAmbig=false; } : 'a'..'z'|'A'..'Z'|'_'|'0'..'9' )* {t = testLiteralsTable(t);} ;protectedWS_OPT : (WS)? ;/** Reset the file and line information; useful when the grammar * has been generated so that errors are shown relative to the * original file like the old C preprocessor used to do. */protectedSRC : "src" ' ' file:ACTION_STRING_LITERAL ' ' line:INT { newline(); setFilename(file.getText().substring(1,file.getText().length()-1)); setLine(Integer.parseInt(line.getText())-1); // -1 because SL_COMMENT will increment the line no. KR $setType(Token.SKIP); // don't let this go to the parser } ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -