📄 antlr.g
字号:
{Token startingToken = LT(1);} : setElement (OR! setElement)+ { GrammarAST ast = new GrammarAST(); ast.initialize(new TokenWithIndex(SET, "SET")); ((TokenWithIndex)ast.token) .setIndex(((TokenWithIndex)startingToken).getIndex()); #setNoParens = #(ast, #setNoParens); } ;setElement : CHAR_LITERAL | {gtype!=LEXER_GRAMMAR}? TOKEN_REF | {gtype!=LEXER_GRAMMAR}? STRING_LITERAL | range ;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 {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #ebnf=#([OPTIONAL,"?"],#b);} | STAR {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #ebnf=#([CLOSURE,"*"],#b);} | PLUS {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #ebnf=#([POSITIVE_CLOSURE,"+"],#b);} ) ( BANG )? | IMPLIES! // syntactic predicate { if (#b.getType()==SET) #b=setToBlockWithSet(#b); if ( gtype==COMBINED_GRAMMAR && Character.isUpperCase(currentRuleName.charAt(0)) ) { #ebnf = #(#[SYNPRED,"=>"],#b); // ignore for lexer rules in combined } else { #ebnf = createSynSemPredFromBlock(#b); /* // add grammar fragment to a list so we can make fake rules for them // later. String predName = grammar.defineSyntacticPredicate(#b,currentRuleName); // convert (alpha)=> into {synpredN}? where N is some pred count // during code gen we convert to function call with templates String synpredinvoke = predName; #ebnf = #[SYN_SEMPRED,synpredinvoke]; #ebnf.setEnclosingRule(currentRuleName); // track how many decisions have synpreds grammar.blocksWithSynPreds.add(currentBlockAST); */ } } | {#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^ ( subrule=ebnfSuffix[#cl,false] {#terminal=subrule;} | ast_suffix )? | tr:TOKEN_REF^ ( ARG_ACTION )? ( subrule=ebnfSuffix[#tr,false] {#terminal=subrule;} | ast_suffix )? // Args are only valid for lexer rules | rr:RULE_REF^ ( ARG_ACTION )? ( subrule=ebnfSuffix[#rr,false] {#terminal=subrule;} | ast_suffix )? | sl:STRING_LITERAL^ ( subrule=ebnfSuffix[#sl,false] {#terminal=subrule;} | ast_suffix )? | wi:WILDCARD^ ( subrule=ebnfSuffix[#wi,false] {#terminal=subrule;} | ast_suffix )? ;ast_suffix : ROOT | RULEROOT | 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^ ( ast_suffix )? // bang could be "no char" in lexer | tr:TOKEN_REF^ (ast_suffix)? | STRING_LITERAL (ast_suffix)? ;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);} )* rew2:REWRITE alt2:rewrite_alternative { root.addChild( #(#rew2, #alt2) ); #rewrite = (GrammarAST)root.getFirstChild(); } | ;// DOESNT DO SETSrewrite_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());} : ( rewrite_template )=> rewrite_template | ( 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_terminal ( subrule=ebnfSuffix[#t,true] {#rewrite_element=subrule;} )? | rewrite_ebnf | tr:rewrite_tree ( subrule=ebnfSuffix[#tr,true] {#rewrite_element=subrule;} )? ;rewrite_terminal{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_terminal = #[LABEL,i_AST.getText()]; #rewrite_terminal.setLine(#d.getLine()); #rewrite_terminal.setColumn(#d.getColumn()); } | ACTION ;rewrite_ebnf!{ int line = LT(1).getLine(); int col = LT(1).getColumn();} : b:rewrite_block ( QUESTION {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #rewrite_ebnf=#([OPTIONAL,"?"],#b);} | STAR {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #rewrite_ebnf=#([CLOSURE,"*"],#b);} | PLUS {if (#b.getType()==SET) #b=setToBlockWithSet(#b); #rewrite_ebnf=#([POSITIVE_CLOSURE,"+"],#b);} ) {#rewrite_ebnf.setLine(line); #rewrite_ebnf.setColumn(col);} ;rewrite_tree : TREE_BEGIN^ rewrite_terminal ( 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 : '^' ;RULEROOT : "^^" ;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 : '"' (ESC|'\n'{newline();}|~'"')* '"' ;DOUBLE_ANGLE_STRING_LITERAL : "<<" (options {greedy=false;}:ESC|'\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 + -