1 /* 2 [The "BSD license"] 3 Copyright (c) 2010 Terence Parr 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 1. Redistributions of source code must retain the above copyright 10 notice, this list of conditions and the following disclaimer. 11 2. Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 3. The name of the author may not be used to endorse or promote products 15 derived from this software without specific prior written permission. 16 17 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 javaTypeInitMap ::= [ 30 "int":"0", 31 "long":"0", 32 "float":"0.0f", 33 "double":"0.0", 34 "boolean":"false", 35 "byte":"0", 36 "short":"0", 37 "char":"0", 38 default:"null" // anything other than an atomic type 39 ] 40 41 // System.Boolean.ToString() returns "True" and "False", but the proper C# literals are "true" and "false" 42 // The Java version of Boolean returns "true" and "false", so they map to themselves here. 43 booleanLiteral ::= [ 44 "True":"true", 45 "False":"false", 46 "true":"true", 47 "false":"false", 48 default:"false" 49 ] 50 51 /** The overall file structure of a recognizer; stores methods for rules 52 * and cyclic DFAs plus support code. 53 */ 54 outputFile(LEXER,PARSER,TREE_PARSER, actionScope, actions, 55 docComment, recognizer, 56 name, tokens, tokenNames, rules, cyclicDFAs, 57 bitsets, buildTemplate, buildAST, rewriteMode, profile, 58 backtracking, synpreds, memoize, numRules, 59 fileName, ANTLRVersion, generatedTimestamp, trace, 60 scopes, superClass, literals) ::= 61 << 62 // $ANTLR <ANTLRVersion> <fileName> <generatedTimestamp> 63 <actions.(actionScope).header> 64 65 <@imports> 66 import org.antlr.runtime.*; 67 <if(TREE_PARSER)> 68 import org.antlr.runtime.tree.*; 69 <endif> 70 import java.util.Stack; 71 import java.util.List; 72 import java.util.ArrayList; 73 <if(backtracking)> 74 import java.util.Map; 75 import java.util.HashMap; 76 <endif> 77 <@end> 78 79 <docComment> 80 @SuppressWarnings("all") 81 <recognizer> 82 83 >> 84 85 lexer(grammar, name, tokens, scopes, rules, numRules, filterMode, labelType="CommonToken", 86 superClass="Lexer") ::= << 87 public class <grammar.recognizerName> extends <@superClassName><superClass><@end> { 88 <tokens:{it | public static final int <it.name>=<it.type>;}; separator="\n"> 89 <scopes:{it |<if(it.isDynamicGlobalScope)><globalAttributeScope(it)><endif>}> 90 <actions.lexer.members> 91 92 // delegates 93 <grammar.delegates: 94 {g|public <g.recognizerName> <g:delegateName()>;}; separator="\n"> 95 // delegators 96 <grammar.delegators: 97 {g|public <g.recognizerName> <g:delegateName()>;}; separator="\n"> 98 <last(grammar.delegators):{g|public <g.recognizerName> gParent;}> 99 public <superClass>[] getDelegates() { 100 return new <superClass>[] {<grammar.delegates: {g|<g:delegateName()>}; separator = ", ">}; 101 } 102 103 public <grammar.recognizerName>() {} <! needed by subclasses !> 104 public <grammar.recognizerName>(CharStream input<grammar.delegators:{g|, <g.recognizerName> <g:delegateName()>}>) { 105 this(input, new RecognizerSharedState()<grammar.delegators:{g|, <g:delegateName()>}>); 106 } 107 public <grammar.recognizerName>(CharStream input, RecognizerSharedState state<grammar.delegators:{g|, <g.recognizerName> <g:delegateName()>}>) { 108 super(input,state); 109 <if(memoize)> 110 <if(grammar.grammarIsRoot)> 111 state.ruleMemo = new HashMap[<numRules>+1];<\n><! index from 1..n !> 112 <endif> 113 <endif> 114 <grammar.directDelegates: 115 {g|<g:delegateName()> = new <g.recognizerName>(input, state<trunc(g.delegators):{p|, <p:delegateName()>}>, this);}; separator="\n"> 116 <grammar.delegators: 117 {g|this.<g:delegateName()> = <g:delegateName()>;}; separator="\n"> 118 <last(grammar.delegators):{g|gParent = <g:delegateName()>;}> 119 } 120 @Override public String getGrammarFileName() { return "<fileName>"; } 121 122 <if(filterMode)> 123 <filteringNextToken()> 124 <endif> 125 <rules; separator="\n\n"> 126 127 <synpreds:{p | <lexerSynpred(p)>}> 128 129 <cyclicDFAs:{dfa | protected DFA<dfa.decisionNumber> dfa<dfa.decisionNumber> = new DFA<dfa.decisionNumber>(this);}; separator="\n"> 130 <cyclicDFAs:cyclicDFA(); separator="\n\n"><! dump tables for all DFA !> 131 132 } 133 >> 134 135 /** A override of Lexer.nextToken() that backtracks over mTokens() looking 136 * for matches. No error can be generated upon error; just rewind, consume 137 * a token and then try again. backtracking needs to be set as well. 138 * Make rule memoization happen only at levels above 1 as we start mTokens 139 * at backtracking==1. 140 */ 141 filteringNextToken() ::= << 142 @Override 143 public Token nextToken() { 144 while (true) { 145 if ( input.LA(1)==CharStream.EOF ) { 146 Token eof = new CommonToken(input,Token.EOF, 147 Token.DEFAULT_CHANNEL, 148 input.index(),input.index()); 149 eof.setLine(getLine()); 150 eof.setCharPositionInLine(getCharPositionInLine()); 151 return eof; 152 } 153 state.token = null; 154 state.channel = Token.DEFAULT_CHANNEL; 155 state.tokenStartCharIndex = input.index(); 156 state.tokenStartCharPositionInLine = input.getCharPositionInLine(); 157 state.tokenStartLine = input.getLine(); 158 state.text = null; 159 try { 160 int m = input.mark(); 161 state.backtracking=1; <! means we won't throw slow exception !> 162 state.failed=false; 163 mTokens(); 164 state.backtracking=0; 165 <! mTokens backtracks with synpred at backtracking==2 166 and we set the synpredgate to allow actions at level 1. !> 167 if ( state.failed ) { 168 input.rewind(m); 169 input.consume(); <! advance one char and try again !> 170 } 171 else { 172 emit(); 173 return state.token; 174 } 175 } 176 catch (RecognitionException re) { 177 // shouldn't happen in backtracking mode, but... 178 reportError(re); 179 recover(re); 180 } 181 } 182 } 183 184 @Override 185 public void memoize(IntStream input, 186 int ruleIndex, 187 int ruleStartIndex) 188 { 189 if ( state.backtracking>1 ) super.memoize(input, ruleIndex, ruleStartIndex); 190 } 191 192 @Override 193 public boolean alreadyParsedRule(IntStream input, int ruleIndex) { 194 if ( state.backtracking>1 ) return super.alreadyParsedRule(input, ruleIndex); 195 return false; 196 } 197 >> 198 199 actionGate() ::= "state.backtracking==0" 200 201 filteringActionGate() ::= "state.backtracking==1" 202 203 /** How to generate a parser */ 204 genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 205 bitsets, inputStreamType, superClass, 206 labelType, members, rewriteElementType, 207 filterMode, ASTLabelType="Object") ::= << 208 public class <grammar.recognizerName> extends <@superClassName><superClass><@end> { 209 <if(grammar.grammarIsRoot)> 210 public static final String[] tokenNames = new String[] { 211 "\<invalid>", "\<EOR>", "\<DOWN>", "\<UP>", <tokenNames; separator=", ", wrap="\n\t\t"> 212 }; 213 <endif> 214 <tokens:{it |public static final int <it.name>=<it.type>;}; separator="\n"> 215 216 // delegates 217 <grammar.delegates: {g|public <g.recognizerName> <g:delegateName()>;}; separator="\n"> 218 public <superClass>[] getDelegates() { 219 return new <superClass>[] {<grammar.delegates: {g|<g:delegateName()>}; separator = ", ">}; 220 } 221 222 // delegators 223 <grammar.delegators: 224 {g|public <g.recognizerName> <g:delegateName()>;}; separator="\n"> 225 <last(grammar.delegators):{g|public <g.recognizerName> gParent;}> 226 227 <scopes:{it |<if(it.isDynamicGlobalScope)><globalAttributeScope(it)><endif>}> 228 229 <@members> 230 <! WARNING. bug in ST: this is cut-n-paste into Dbg.stg !> 231 public <grammar.recognizerName>(<inputStreamType> input<grammar.delegators:{g|, <g.recognizerName> <g:delegateName()>}>) { 232 this(input, new RecognizerSharedState()<grammar.delegators:{g|, <g:delegateName()>}>); 233 } 234 public <grammar.recognizerName>(<inputStreamType> input, RecognizerSharedState state<grammar.delegators:{g|, <g.recognizerName> <g:delegateName()>}>) { 235 super(input, state); 236 <parserCtorBody()> 237 <grammar.directDelegates: 238 {g|<g:delegateName()> = new <g.recognizerName>(input, state<trunc(g.delegators):{p|, <p:delegateName()>}>, this);}; separator="\n"> 239 <grammar.indirectDelegates:{g | <g:delegateName()> = <g.delegator:delegateName()>.<g:delegateName()>;}; separator="\n"> 240 <last(grammar.delegators):{g|gParent = <g:delegateName()>;}> 241 } 242 <@end> 243 244 @Override public String[] getTokenNames() { return <grammar.composite.rootGrammar.recognizerName>.tokenNames; } 245 @Override public String getGrammarFileName() { return "<fileName>"; } 246 247 <members> 248 249 <rules; separator="\n\n"> 250 251 <! generate rule/method definitions for imported rules so they 252 appear to be defined in this recognizer. !> 253 // Delegated rules 254 <grammar.delegatedRules:{ruleDescriptor| 255 public <returnType(ruleDescriptor)> <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope()>) throws <ruleDescriptor.throwsSpec; separator=", "> { <if(ruleDescriptor.hasReturnValue)>return <endif><ruleDescriptor.grammar:delegateName()>.<ruleDescriptor.name>(<if(ruleDescriptor.parameterScope)><ruleDescriptor.parameterScope.attributes:{a|<a.name>}; separator=", "><endif>); \}}; separator="\n"> 256 257 <synpreds:{p | <synpred(p)>}> 258 259 <cyclicDFAs:{dfa | protected DFA<dfa.decisionNumber> dfa<dfa.decisionNumber> = new DFA<dfa.decisionNumber>(this);}; separator="\n"> 260 <cyclicDFAs:cyclicDFA(); separator="\n\n"><! dump tables for all DFA !> 261 262 <bitsets:{it | <bitset(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>}, 263 words64=it.bits)>}; separator="\n"> 264 } 265 >> 266 267 parserCtorBody() ::= << 268 <if(memoize)> 269 <if(grammar.grammarIsRoot)> 270 this.state.ruleMemo = new HashMap[<length(grammar.allImportedRules)>+1];<\n><! index from 1..n !> 271 <endif> 272 <endif> 273 <grammar.delegators: 274 {g|this.<g:delegateName()> = <g:delegateName()>;}; separator="\n"> 275 >> 276 277 parser(grammar, name, scopes, tokens, tokenNames, rules, numRules, bitsets, 278 ASTLabelType="Object", superClass="Parser", labelType="Token", 279 members={<actions.parser.members>}) ::= << 280 <genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 281 bitsets, "TokenStream", superClass, 282 labelType, members, "Token", 283 false, ASTLabelType)> 284 >> 285 286 /** How to generate a tree parser; same as parser except the input 287 * stream is a different type. 288 */ 289 treeParser(grammar, name, scopes, tokens, tokenNames, globalAction, rules, 290 numRules, bitsets, filterMode, labelType={<ASTLabelType>}, ASTLabelType="Object", 291 superClass={<if(filterMode)><if(buildAST)>TreeRewriter<else>TreeFilter<endif><else>TreeParser<endif>}, 292 members={<actions.treeparser.members>} 293 ) ::= << 294 <genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 295 bitsets, "TreeNodeStream", superClass, 296 labelType, members, "Node", 297 filterMode, ASTLabelType)> 298 >> 299 300 /** A simpler version of a rule template that is specific to the imaginary 301 * rules created for syntactic predicates. As they never have return values 302 * nor parameters etc..., just give simplest possible method. Don't do 303 * any of the normal memoization stuff in here either; it's a waste. 304 * As predicates cannot be inlined into the invoking rule, they need to 305 * be in a rule by themselves. 306 */ 307 synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 308 << 309 // $ANTLR start <ruleName> 310 public final void <ruleName>_fragment(<ruleDescriptor.parameterScope:parameterScope()>) throws <ruleDescriptor.throwsSpec:{x|<x>}; separator=", "> { 311 <ruleLabelDefs()> 312 <if(trace)> 313 traceIn("<ruleName>_fragment", <ruleDescriptor.index>); 314 try { 315 <block> 316 } 317 finally { 318 traceOut("<ruleName>_fragment", <ruleDescriptor.index>); 319 } 320 <else> 321 <block> 322 <endif> 323 } 324 // $ANTLR end <ruleName> 325 >> 326 327 synpred(name) ::= << 328 public final boolean <name>() { 329 state.backtracking++; 330 <@start()> 331 int start = input.mark(); 332 try { 333 <name>_fragment(); // can never throw exception 334 } catch (RecognitionException re) { 335 System.err.println("impossible: "+re); 336 } 337 boolean success = !state.failed; 338 input.rewind(start); 339 <@stop()> 340 state.backtracking--; 341 state.failed=false; 342 return success; 343 }<\n> 344 >> 345 346 lexerSynpred(name) ::= << 347 <synpred(name)> 348 >> 349 350 ruleMemoization(name) ::= << 351 <if(memoize)> 352 if ( state.backtracking>0 && alreadyParsedRule(input, <ruleDescriptor.index>) ) { <returnStatement(({<ruleReturnValue()>}))> } 353 <endif> 354 >> 355 356 /** How to test for failure and return from rule */ 357 checkRuleBacktrackFailure() ::= << 358 <if(backtracking)>if (state.failed) <returnStatement(({<ruleReturnValue()>}))><endif> 359 >> 360 361 /** This rule has failed, exit indicating failure during backtrack */ 362 ruleBacktrackFailure() ::= << 363 <if(backtracking)>if (state.backtracking>0) {state.failed=true; <returnStatement(({<ruleReturnValue()>}))>}<endif> 364 >> 365 366 /** How to generate code for a rule. This includes any return type 367 * data aggregates required for multiple return values. 368 */ 369 rule(ruleName,ruleDescriptor,block,emptyRule,description,exceptions,finally,memoize) ::= << 370 <ruleAttributeScope(scope=ruleDescriptor.ruleScope)> 371 <returnScope(scope=ruleDescriptor.returnScope)> 372 373 // $ANTLR start "<ruleName>" 374 // <fileName>:<description> 375 <if(isPredefinedRewriteRule.(ruleName) && filterMode && buildAST)> 376 @Override 377 <endif> 378 public final <returnType(ruleDescriptor)> <ruleName>(<ruleDescriptor.parameterScope:parameterScope()>) throws <ruleDescriptor.throwsSpec:{x|<x>}; separator=", "> { 379 <if(trace)>traceIn("<ruleName>", <ruleDescriptor.index>);<endif> 380 <ruleScopeSetUp()> 381 <ruleDeclarations()> 382 <ruleLabelDefs()> 383 <ruleDescriptor.actions.init> 384 <@preamble()> 385 try { 386 <ruleMemoization(name=ruleName)> 387 <block> 388 <ruleCleanUp()> 389 <(ruleDescriptor.actions.after):execAction()> 390 } 391 <if(exceptions)> 392 <exceptions:{e|<catch(decl=e.decl,action=e.action)><\n>}> 393 <else> 394 <if(!emptyRule)> 395 <if(actions.(actionScope).rulecatch)> 396 <actions.(actionScope).rulecatch> 397 <else> 398 catch (RecognitionException re) { 399 reportError(re); 400 recover(input,re); 401 <@setErrorReturnValue()> 402 } 403 <endif> 404 <endif> 405 <endif> 406 finally { 407 // do for sure before leaving 408 <if(trace)>traceOut("<ruleName>", <ruleDescriptor.index>);<endif> 409 <memoize()> 410 <ruleScopeCleanUp()> 411 <finally> 412 } 413 <@postamble()> 414 <returnStatement(({<ruleReturnValue()>}), false)> 415 } 416 // $ANTLR end "<ruleName>" 417 >> 418 419 returnStatement(returnValue, force=true) ::= <% 420 <if(!isEmptyString.(returnValue))> 421 return <returnValue>; 422 <elseif(force)> 423 return; 424 <endif> 425 %> 426 427 catch(decl,action) ::= << 428 catch (<e.decl>) { 429 <e.action> 430 } 431 >> 432 433 ruleDeclarations() ::= << 434 <if(ruleDescriptor.hasMultipleReturnValues)> 435 <returnType(ruleDescriptor)> retval = new <returnType(ruleDescriptor)>(); 436 retval.start = input.LT(1); 437 <elseif(ruleDescriptor.returnScope)> 438 <ruleDescriptor.returnScope.attributes:{ a | 439 <a.type> <a.name> = <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>; 440 }> 441 <endif> 442 <if(memoize)> 443 int <ruleDescriptor.name>_StartIndex = input.index(); 444 <endif> 445 >> 446 447 ruleScopeSetUp() ::= << 448 <ruleDescriptor.useScopes:{it |<it>_stack.push(new <it>_scope());}; separator="\n"> 449 <ruleDescriptor.ruleScope:{it |<it.name>_stack.push(new <it.name>_scope());}; separator="\n"> 450 >> 451 452 ruleScopeCleanUp() ::= << 453 <ruleDescriptor.useScopes:{it |<it>_stack.pop();}; separator="\n"> 454 <ruleDescriptor.ruleScope:{it |<it.name>_stack.pop();}; separator="\n"> 455 >> 456 457 458 ruleLabelDefs() ::= << 459 <[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels, 460 ruleDescriptor.wildcardTreeLabels,ruleDescriptor.wildcardTreeListLabels] 461 :{it |<labelType> <it.label.text>=null;}; separator="\n" 462 > 463 <[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels,ruleDescriptor.wildcardTreeListLabels] 464 :{it |List\<Object> list_<it.label.text>=null;}; separator="\n" 465 > 466 <ruleDescriptor.ruleLabels:ruleLabelDef(); separator="\n"> 467 <ruleDescriptor.ruleListLabels:{ll|RuleReturnScope <ll.label.text> = null;}; separator="\n"> 468 >> 469 470 lexerRuleLabelDefs() ::= << 471 <[ruleDescriptor.tokenLabels, 472 ruleDescriptor.tokenListLabels, 473 ruleDescriptor.ruleLabels] 474 :{it |<labelType> <it.label.text>=null;}; separator="\n" 475 > 476 <ruleDescriptor.charLabels:{it |int <it.label.text>;}; separator="\n"> 477 <[ruleDescriptor.tokenListLabels, 478 ruleDescriptor.ruleListLabels] 479 :{it |List\<Object> list_<it.label.text>=null;}; separator="\n" 480 > 481 >> 482 483 ruleReturnValue() ::= <% 484 <if(!ruleDescriptor.isSynPred)> 485 <if(ruleDescriptor.hasReturnValue)> 486 <if(ruleDescriptor.hasSingleReturnValue)> 487 <ruleDescriptor.singleValueReturnName> 488 <else> 489 retval 490 <endif> 491 <endif> 492 <endif> 493 %> 494 495 ruleCleanUp() ::= << 496 <if(ruleDescriptor.hasMultipleReturnValues)> 497 <if(!TREE_PARSER)> 498 retval.stop = input.LT(-1); 499 <endif> 500 <endif> 501 >> 502 503 memoize() ::= << 504 <if(memoize)> 505 <if(backtracking)> 506 if ( state.backtracking>0 ) { memoize(input, <ruleDescriptor.index>, <ruleDescriptor.name>_StartIndex); } 507 <endif> 508 <endif> 509 >> 510 511 /** How to generate a rule in the lexer; naked blocks are used for 512 * fragment rules. 513 */ 514 lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 515 // $ANTLR start "<ruleName>" 516 public final void m<ruleName>(<ruleDescriptor.parameterScope:parameterScope()>) throws RecognitionException { 517 <if(trace)>traceIn("<ruleName>", <ruleDescriptor.index>);<endif> 518 <ruleScopeSetUp()> 519 <ruleDeclarations()> 520 try { 521 <if(nakedBlock)> 522 <ruleMemoization(name=ruleName)> 523 <lexerRuleLabelDefs()> 524 <ruleDescriptor.actions.init> 525 <block> 526 <else> 527 int _type = <ruleName>; 528 int _channel = DEFAULT_TOKEN_CHANNEL; 529 <ruleMemoization(name=ruleName)> 530 <lexerRuleLabelDefs()> 531 <ruleDescriptor.actions.init> 532 <block> 533 <ruleCleanUp()> 534 state.type = _type; 535 state.channel = _channel; 536 <(ruleDescriptor.actions.after):execAction()> 537 <endif> 538 } 539 finally { 540 // do for sure before leaving 541 <if(trace)>traceOut("<ruleName>", <ruleDescriptor.index>);<endif> 542 <ruleScopeCleanUp()> 543 <memoize()> 544 } 545 } 546 // $ANTLR end "<ruleName>" 547 >> 548 549 /** How to generate code for the implicitly-defined lexer grammar rule 550 * that chooses between lexer rules. 551 */ 552 tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 553 @Override 554 public void mTokens() throws RecognitionException { 555 <block> 556 } 557 >> 558 559 // S U B R U L E S 560 561 /** A (...) subrule with multiple alternatives */ 562 block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 563 // <fileName>:<description> 564 int alt<decisionNumber>=<maxAlt>; 565 <decls> 566 <@predecision()> 567 <decision> 568 <@postdecision()> 569 <@prebranch()> 570 switch (alt<decisionNumber>) { 571 <alts:{a | <altSwitchCase(i,a)>}> 572 } 573 <@postbranch()> 574 >> 575 576 /** A rule block with multiple alternatives */ 577 ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 578 // <fileName>:<description> 579 int alt<decisionNumber>=<maxAlt>; 580 <decls> 581 <@predecision()> 582 <decision> 583 <@postdecision()> 584 switch (alt<decisionNumber>) { 585 <alts:{a | <altSwitchCase(i,a)>}> 586 } 587 >> 588 589 ruleBlockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 590 // <fileName>:<description> 591 <decls> 592 <@prealt()> 593 <alts> 594 <@postalt()> 595 >> 596 597 /** A special case of a (...) subrule with a single alternative */ 598 blockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 599 // <fileName>:<description> 600 <decls> 601 <@prealt()> 602 <alts> 603 <@postalt()> 604 >> 605 606 /** A (..)+ block with 1 or more alternatives */ 607 positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 608 // <fileName>:<description> 609 int cnt<decisionNumber>=0; 610 <decls> 611 <@preloop()> 612 loop<decisionNumber>: 613 while (true) { 614 int alt<decisionNumber>=<maxAlt>; 615 <@predecision()> 616 <decision> 617 <@postdecision()> 618 switch (alt<decisionNumber>) { 619 <alts:{a | <altSwitchCase(i,a)>}> 620 default : 621 if ( cnt<decisionNumber> >= 1 ) break loop<decisionNumber>; 622 <ruleBacktrackFailure()> 623 EarlyExitException eee = new EarlyExitException(<decisionNumber>, input); 624 <@earlyExitException()> 625 throw eee; 626 } 627 cnt<decisionNumber>++; 628 } 629 <@postloop()> 630 >> 631 632 positiveClosureBlockSingleAlt ::= positiveClosureBlock 633 634 /** A (..)* block with 1 or more alternatives */ 635 closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 636 // <fileName>:<description> 637 <decls> 638 <@preloop()> 639 loop<decisionNumber>: 640 while (true) { 641 int alt<decisionNumber>=<maxAlt>; 642 <@predecision()> 643 <decision> 644 <@postdecision()> 645 switch (alt<decisionNumber>) { 646 <alts:{a | <altSwitchCase(i,a)>}> 647 default : 648 break loop<decisionNumber>; 649 } 650 } 651 <@postloop()> 652 >> 653 654 closureBlockSingleAlt ::= closureBlock 655 656 /** Optional blocks (x)? are translated to (x|) by before code generation 657 * so we can just use the normal block template 658 */ 659 optionalBlock ::= block 660 661 optionalBlockSingleAlt ::= block 662 663 /** A case in a switch that jumps to an alternative given the alternative 664 * number. A DFA predicts the alternative and then a simple switch 665 * does the jump to the code that actually matches that alternative. 666 */ 667 altSwitchCase(altNum,alt) ::= << 668 case <altNum> : 669 <@prealt()> 670 <alt> 671 break;<\n> 672 >> 673 674 /** An alternative is just a list of elements; at outermost level */ 675 alt(elements,altNum,description,autoAST,outerAlt,treeLevel,rew) ::= << 676 // <fileName>:<description> 677 { 678 <@declarations()> 679 <elements:element()> 680 <rew> 681 <@cleanup()> 682 } 683 >> 684 685 /** What to emit when there is no rewrite. For auto build 686 * mode, does nothing. 687 */ 688 noRewrite(rewriteBlockLevel, treeLevel) ::= "" 689 690 // E L E M E N T S 691 692 /** Dump the elements one per line */ 693 element(e) ::= << 694 <@prematch()> 695 <e.el> 696 >> 697 698 /** match a token optionally with a label in front */ 699 tokenRef(token,label,elementIndex,terminalOptions={}) ::= << 700 <if(label)><label>=(<labelType>)<endif>match(input,<token>,FOLLOW_<token>_in_<ruleName><elementIndex>); <checkRuleBacktrackFailure()> 701 >> 702 703 /** ids+=ID */ 704 tokenRefAndListLabel(token,label,elementIndex,terminalOptions={}) ::= << 705 <tokenRef(token,label,elementIndex,terminalOptions)> 706 <listLabel(label, label)> 707 >> 708 709 listLabel(label,elem) ::= << 710 if (list_<label>==null) list_<label>=new ArrayList\<Object>(); 711 list_<label>.add(<elem>); 712 >> 713 714 /** match a character */ 715 charRef(char,label) ::= << 716 <if(label)> 717 <label> = input.LA(1); 718 <endif> 719 match(<char>); <checkRuleBacktrackFailure()> 720 >> 721 722 /** match a character range */ 723 charRangeRef(a,b,label) ::= << 724 <if(label)> 725 <label> = input.LA(1); 726 <endif> 727 matchRange(<a>,<b>); <checkRuleBacktrackFailure()> 728 >> 729 730 /** For now, sets are interval tests and must be tested inline */ 731 matchSet(s,label,elementIndex,postmatchCode="",terminalOptions={}) ::= << 732 <if(label)> 733 <if(LEXER)> 734 <label>= input.LA(1); 735 <else> 736 <label>=<castToLabelType("input.LT(1)")>; 737 <endif> 738 <endif> 739 if ( <s> ) { 740 input.consume(); 741 <postmatchCode> 742 <if(!LEXER)> 743 state.errorRecovery=false; 744 <endif> 745 <if(backtracking)>state.failed=false;<endif> 746 } 747 else { 748 <ruleBacktrackFailure()> 749 MismatchedSetException mse = new MismatchedSetException(null,input); 750 <@mismatchedSetException()> 751 <if(LEXER)> 752 recover(mse); 753 throw mse; 754 <else> 755 throw mse; 756 <! use following code to make it recover inline; remove throw mse; 757 recoverFromMismatchedSet(input,mse,FOLLOW_set_in_<ruleName><elementIndex>); 758 !> 759 <endif> 760 } 761 >> 762 763 matchRuleBlockSet ::= matchSet 764 765 matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 766 <matchSet(...)> 767 <listLabel(label, label)> 768 >> 769 770 /** Match a string literal */ 771 lexerStringRef(string,label,elementIndex="0") ::= << 772 <if(label)> 773 int <label>Start = getCharIndex(); 774 match(<string>); <checkRuleBacktrackFailure()> 775 int <label>StartLine<elementIndex> = getLine(); 776 int <label>StartCharPos<elementIndex> = getCharPositionInLine(); 777 <label> = new <labelType>(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, <label>Start, getCharIndex()-1); 778 <label>.setLine(<label>StartLine<elementIndex>); 779 <label>.setCharPositionInLine(<label>StartCharPos<elementIndex>); 780 <else> 781 match(<string>); <checkRuleBacktrackFailure()> 782 <endif> 783 >> 784 785 wildcard(token,label,elementIndex,terminalOptions={}) ::= << 786 <if(label)> 787 <label>=<castToLabelType("input.LT(1)")>; 788 <endif> 789 matchAny(input); <checkRuleBacktrackFailure()> 790 >> 791 792 wildcardAndListLabel(token,label,elementIndex,terminalOptions={}) ::= << 793 <wildcard(...)> 794 <listLabel(label, label)> 795 >> 796 797 /** Match . wildcard in lexer */ 798 wildcardChar(label, elementIndex) ::= << 799 <if(label)> 800 <label> = input.LA(1); 801 <endif> 802 matchAny(); <checkRuleBacktrackFailure()> 803 >> 804 805 wildcardCharListLabel(label, elementIndex) ::= << 806 <wildcardChar(label, elementIndex)> 807 <listLabel(label, label)> 808 >> 809 810 /** Match a rule reference by invoking it possibly with arguments 811 * and a return value or values. The 'rule' argument was the 812 * target rule name, but now is type Rule, whose toString is 813 * same: the rule name. Now though you can access full rule 814 * descriptor stuff. 815 */ 816 ruleRef(rule,label,elementIndex,args,scope) ::= << 817 pushFollow(FOLLOW_<rule.name>_in_<ruleName><elementIndex>); 818 <if(label)><label>=<endif><if(scope)><scope:delegateName()>.<endif><rule.name>(<args; separator=", ">); 819 state._fsp--; 820 <checkRuleBacktrackFailure()> 821 >> 822 823 /** ids+=r */ 824 ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 825 <ruleRef(rule,label,elementIndex,args,scope)> 826 <listLabel(label, label)> 827 >> 828 829 /** A lexer rule reference. 830 * 831 * The 'rule' argument was the target rule name, but now 832 * is type Rule, whose toString is same: the rule name. 833 * Now though you can access full rule descriptor stuff. 834 */ 835 lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 836 <if(label)> 837 int <label>Start<elementIndex> = getCharIndex(); 838 int <label>StartLine<elementIndex> = getLine(); 839 int <label>StartCharPos<elementIndex> = getCharPositionInLine(); 840 <if(scope)><scope:delegateName()>.<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()> 841 <label> = new <labelType>(input, Token.INVALID_TOKEN_TYPE, Token.DEFAULT_CHANNEL, <label>Start<elementIndex>, getCharIndex()-1); 842 <label>.setLine(<label>StartLine<elementIndex>); 843 <label>.setCharPositionInLine(<label>StartCharPos<elementIndex>); 844 <else> 845 <if(scope)><scope:delegateName()>.<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()> 846 <endif> 847 >> 848 849 /** i+=INT in lexer */ 850 lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 851 <lexerRuleRef(rule,label,args,elementIndex,scope)> 852 <listLabel(label, label)> 853 >> 854 855 /** EOF in the lexer */ 856 lexerMatchEOF(label,elementIndex) ::= << 857 <if(label)> 858 int <label>Start<elementIndex> = getCharIndex(); 859 int <label>StartLine<elementIndex> = getLine(); 860 int <label>StartCharPos<elementIndex> = getCharPositionInLine(); 861 match(EOF); <checkRuleBacktrackFailure()> 862 <labelType> <label> = new <labelType>(input, EOF, Token.DEFAULT_CHANNEL, <label>Start<elementIndex>, getCharIndex()-1); 863 <label>.setLine(<label>StartLine<elementIndex>); 864 <label>.setCharPositionInLine(<label>StartCharPos<elementIndex>); 865 <else> 866 match(EOF); <checkRuleBacktrackFailure()> 867 <endif> 868 >> 869 870 // used for left-recursive rules 871 recRuleDefArg() ::= "int <recRuleArg()>" 872 recRuleArg() ::= "_p" 873 recRuleAltPredicate(ruleName,opPrec) ::= "<recRuleArg()> \<= <opPrec>" 874 recRuleSetResultAction() ::= "root_0=$<ruleName>_primary.tree;" 875 recRuleSetReturnAction(src,name) ::= "$<name>=$<src>.<name>;" 876 877 /** match ^(root children) in tree parser */ 878 tree(root, actionsAfterRoot, children, nullableChildList, 879 enclosingTreeLevel, treeLevel) ::= << 880 <root:element()> 881 <actionsAfterRoot:element()> 882 <if(nullableChildList)> 883 if ( input.LA(1)==Token.DOWN ) { 884 match(input, Token.DOWN, null); <checkRuleBacktrackFailure()> 885 <children:element()> 886 match(input, Token.UP, null); <checkRuleBacktrackFailure()> 887 } 888 <else> 889 match(input, Token.DOWN, null); <checkRuleBacktrackFailure()> 890 <children:element()> 891 match(input, Token.UP, null); <checkRuleBacktrackFailure()> 892 <endif> 893 >> 894 895 /** Every predicate is used as a validating predicate (even when it is 896 * also hoisted into a prediction expression). 897 */ 898 validateSemanticPredicate(pred,description) ::= << 899 if ( !(<evalPredicate(pred,description)>) ) { 900 <ruleBacktrackFailure()> 901 throw new FailedPredicateException(input, "<ruleName>", "<description>"); 902 } 903 >> 904 905 // F i x e d D F A (if-then-else) 906 907 dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 908 int LA<decisionNumber>_<stateNumber> = input.LA(<k>); 909 <edges; separator="\nelse "> 910 <if((!isTrue.(last(edges).labelExpr)) && (!last(edges).predicates))> 911 else { 912 <if(eotPredictsAlt)> 913 alt<decisionNumber>=<eotPredictsAlt>; 914 <else> 915 <ruleBacktrackFailure()> 916 <(nvaExceptionWrapperMap.(k))({NoViableAltException nvae = 917 new NoViableAltException("<description>", <decisionNumber>, <stateNumber>, input); 918 <@noViableAltException()> 919 throw nvae;})> 920 <endif> 921 } 922 <endif> 923 >> 924 925 nvaExceptionWrapperMap ::= [ 926 "1":"wrapNvaExceptionForK1", 927 "2":"wrapNvaExceptionForK2", 928 default:"wrapNvaExceptionForKN" 929 ] 930 931 wrapNvaExceptionForK1(exceptionCode) ::= << 932 <exceptionCode> 933 >> 934 935 wrapNvaExceptionForK2(exceptionCode) ::= << 936 int nvaeMark = input.mark(); 937 try { 938 input.consume(); 939 <exceptionCode> 940 } finally { 941 input.rewind(nvaeMark); 942 } 943 >> 944 945 wrapNvaExceptionForKN(exceptionCode) ::= << 946 int nvaeMark = input.mark(); 947 try { 948 for (int nvaeConsume = 0; nvaeConsume \< <k> - 1; nvaeConsume++) { 949 input.consume(); 950 } 951 <exceptionCode> 952 } finally { 953 input.rewind(nvaeMark); 954 } 955 >> 956 957 /** Same as a normal DFA state except that we don't examine lookahead 958 * for the bypass alternative. It delays error detection but this 959 * is faster, smaller, and more what people expect. For (X)? people 960 * expect "if ( LA(1)==X ) match(X);" and that's it. 961 */ 962 dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 963 int LA<decisionNumber>_<stateNumber> = input.LA(<k>); 964 <edges; separator="\nelse "> 965 >> 966 967 /** A DFA state that is actually the loopback decision of a closure 968 * loop. If end-of-token (EOT) predicts any of the targets then it 969 * should act like a default clause (i.e., no error can be generated). 970 * This is used only in the lexer so that for ('a')* on the end of a rule 971 * anything other than 'a' predicts exiting. 972 */ 973 dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 974 int LA<decisionNumber>_<stateNumber> = input.LA(<k>); 975 <edges; separator="\nelse "> 976 <if(eotPredictsAlt)> 977 <if(!edges)> 978 alt<decisionNumber>=<eotPredictsAlt>; <! if no edges, don't gen ELSE !> 979 <else> 980 else { 981 alt<decisionNumber>=<eotPredictsAlt>; 982 } 983 <endif> 984 <endif> 985 >> 986 987 /** An accept state indicates a unique alternative has been predicted */ 988 dfaAcceptState(alt) ::= "alt<decisionNumber>=<alt>;" 989 990 /** A simple edge with an expression. If the expression is satisfied, 991 * enter to the target state. To handle gated productions, we may 992 * have to evaluate some predicates for this edge. 993 */ 994 dfaEdge(labelExpr, targetState, predicates) ::= << 995 if ( (<labelExpr>) <if(predicates)>&& (<predicates>)<endif>) { 996 <targetState> 997 } 998 >> 999 1000 // F i x e d D F A (switch case) 1001 1002 /** A DFA state where a SWITCH may be generated. The code generator 1003 * decides if this is possible: CodeGenerator.canGenerateSwitch(). 1004 */ 1005 dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1006 switch ( input.LA(<k>) ) { 1007 <edges; separator="\n"> 1008 default: 1009 <if(eotPredictsAlt)> 1010 alt<decisionNumber>=<eotPredictsAlt>; 1011 <else> 1012 <ruleBacktrackFailure()> 1013 <(nvaExceptionWrapperMap.(k))({NoViableAltException nvae = 1014 new NoViableAltException("<description>", <decisionNumber>, <stateNumber>, input); 1015 <@noViableAltException()> 1016 throw nvae;})> 1017 <endif> 1018 } 1019 >> 1020 1021 dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1022 switch ( input.LA(<k>) ) { 1023 <edges; separator="\n"> 1024 } 1025 >> 1026 1027 dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1028 switch ( input.LA(<k>) ) { 1029 <edges; separator="\n"> 1030 <if(eotPredictsAlt)> 1031 default: 1032 alt<decisionNumber>=<eotPredictsAlt>; 1033 break; 1034 <endif> 1035 } 1036 >> 1037 1038 dfaEdgeSwitch(labels, targetState) ::= << 1039 <labels:{it |case <it>:}; separator="\n"> 1040 { 1041 <targetState> 1042 } 1043 break; 1044 >> 1045 1046 // C y c l i c D F A 1047 1048 /** The code to initiate execution of a cyclic DFA; this is used 1049 * in the rule to predict an alt just like the fixed DFA case. 1050 * The <name> attribute is inherited via the parser, lexer, ... 1051 */ 1052 dfaDecision(decisionNumber,description) ::= << 1053 alt<decisionNumber> = dfa<decisionNumber>.predict(input); 1054 >> 1055 1056 /* Dump DFA tables as run-length-encoded Strings of octal values. 1057 * Can't use hex as compiler translates them before compilation. 1058 * These strings are split into multiple, concatenated strings. 1059 * Java puts them back together at compile time thankfully. 1060 * Java cannot handle large static arrays, so we're stuck with this 1061 * encode/decode approach. See analysis and runtime DFA for 1062 * the encoding methods. 1063 */ 1064 cyclicDFA(dfa) ::= << 1065 static final String DFA<dfa.decisionNumber>_eotS = 1066 "<dfa.javaCompressedEOT; wrap="\"+\n\t\"">"; 1067 static final String DFA<dfa.decisionNumber>_eofS = 1068 "<dfa.javaCompressedEOF; wrap="\"+\n\t\"">"; 1069 static final String DFA<dfa.decisionNumber>_minS = 1070 "<dfa.javaCompressedMin; wrap="\"+\n\t\"">"; 1071 static final String DFA<dfa.decisionNumber>_maxS = 1072 "<dfa.javaCompressedMax; wrap="\"+\n\t\"">"; 1073 static final String DFA<dfa.decisionNumber>_acceptS = 1074 "<dfa.javaCompressedAccept; wrap="\"+\n\t\"">"; 1075 static final String DFA<dfa.decisionNumber>_specialS = 1076 "<dfa.javaCompressedSpecial; wrap="\"+\n\t\"">}>"; 1077 static final String[] DFA<dfa.decisionNumber>_transitionS = { 1078 <dfa.javaCompressedTransition:{s|"<s; wrap="\"+\n\"">"}; separator=",\n"> 1079 }; 1080 1081 static final short[] DFA<dfa.decisionNumber>_eot = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_eotS); 1082 static final short[] DFA<dfa.decisionNumber>_eof = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_eofS); 1083 static final char[] DFA<dfa.decisionNumber>_min = DFA.unpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_minS); 1084 static final char[] DFA<dfa.decisionNumber>_max = DFA.unpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_maxS); 1085 static final short[] DFA<dfa.decisionNumber>_accept = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_acceptS); 1086 static final short[] DFA<dfa.decisionNumber>_special = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_specialS); 1087 static final short[][] DFA<dfa.decisionNumber>_transition; 1088 1089 static { 1090 int numStates = DFA<dfa.decisionNumber>_transitionS.length; 1091 DFA<dfa.decisionNumber>_transition = new short[numStates][]; 1092 for (int i=0; i\<numStates; i++) { 1093 DFA<dfa.decisionNumber>_transition[i] = DFA.unpackEncodedString(DFA<dfa.decisionNumber>_transitionS[i]); 1094 } 1095 } 1096 1097 protected class DFA<dfa.decisionNumber> extends DFA { 1098 1099 public DFA<dfa.decisionNumber>(BaseRecognizer recognizer) { 1100 this.recognizer = recognizer; 1101 this.decisionNumber = <dfa.decisionNumber>; 1102 this.eot = DFA<dfa.decisionNumber>_eot; 1103 this.eof = DFA<dfa.decisionNumber>_eof; 1104 this.min = DFA<dfa.decisionNumber>_min; 1105 this.max = DFA<dfa.decisionNumber>_max; 1106 this.accept = DFA<dfa.decisionNumber>_accept; 1107 this.special = DFA<dfa.decisionNumber>_special; 1108 this.transition = DFA<dfa.decisionNumber>_transition; 1109 } 1110 @Override 1111 public String getDescription() { 1112 return "<dfa.description>"; 1113 } 1114 <@errorMethod()> 1115 <if(dfa.specialStateSTs)> 1116 @Override 1117 public int specialStateTransition(int s, IntStream _input) throws NoViableAltException { 1118 <if(LEXER)> 1119 IntStream input = _input; 1120 <endif> 1121 <if(PARSER)> 1122 TokenStream input = (TokenStream)_input; 1123 <endif> 1124 <if(TREE_PARSER)> 1125 TreeNodeStream input = (TreeNodeStream)_input; 1126 <endif> 1127 int _s = s; 1128 switch ( s ) { 1129 <dfa.specialStateSTs:{state | 1130 case <i0> : <! compressed special state numbers 0..n-1 !> 1131 <state>}; separator="\n"> 1132 } 1133 <if(backtracking)> 1134 if (state.backtracking>0) {state.failed=true; return -1;} 1135 <endif> 1136 NoViableAltException nvae = 1137 new NoViableAltException(getDescription(), <dfa.decisionNumber>, _s, input); 1138 error(nvae); 1139 throw nvae; 1140 } 1141 <endif> 1142 } 1143 >> 1144 1145 /** A state in a cyclic DFA; it's a special state and part of a big switch on 1146 * state. 1147 */ 1148 cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 1149 int LA<decisionNumber>_<stateNumber> = input.LA(1); 1150 <if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 1151 int index<decisionNumber>_<stateNumber> = input.index(); 1152 input.rewind(); 1153 <endif> 1154 s = -1; 1155 <edges; separator="\nelse "> 1156 <if(semPredState)> <! return input cursor to state before we rewound !> 1157 input.seek(index<decisionNumber>_<stateNumber>); 1158 <endif> 1159 if ( s>=0 ) return s; 1160 break; 1161 >> 1162 1163 /** Just like a fixed DFA edge, test the lookahead and indicate what 1164 * state to jump to next if successful. 1165 */ 1166 cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1167 if ( (<labelExpr>) <if(predicates)>&& (<predicates>)<endif>) {s = <targetStateNumber>;} 1168 >> 1169 1170 /** An edge pointing at end-of-token; essentially matches any char; 1171 * always jump to the target. 1172 */ 1173 eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1174 s = <targetStateNumber>; 1175 >> 1176 1177 1178 // D F A E X P R E S S I O N S 1179 1180 andPredicates(left,right) ::= "(<left>&&<right>)" 1181 1182 orPredicates(operands) ::= "(<operands; separator=\"||\">)" 1183 1184 notPredicate(pred) ::= "!(<evalPredicate(pred,{})>)" 1185 1186 evalPredicate(pred,description) ::= "(<pred>)" 1187 1188 evalSynPredicate(pred,description) ::= "<pred>()" 1189 1190 lookaheadTest(atom,k,atomAsInt) ::= "LA<decisionNumber>_<stateNumber>==<atom>" 1191 1192 /** Sometimes a lookahead test cannot assume that LA(k) is in a temp variable 1193 * somewhere. Must ask for the lookahead directly. 1194 */ 1195 isolatedLookaheadTest(atom,k,atomAsInt) ::= "input.LA(<k>)==<atom>" 1196 1197 lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= <% 1198 (LA<decisionNumber>_<stateNumber> >= <lower> && LA<decisionNumber>_<stateNumber> \<= <upper>) 1199 %> 1200 1201 isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(input.LA(<k>) >= <lower> && input.LA(<k>) \<= <upper>)" 1202 1203 setTest(ranges) ::= << 1204 <ranges; separator="||"> 1205 >> 1206 1207 // A T T R I B U T E S 1208 1209 globalAttributeScope(scope) ::= << 1210 <if(scope.attributes)> 1211 protected static class <scope.name>_scope { 1212 <scope.attributes:{it |<it.decl>;}; separator="\n"> 1213 } 1214 protected Stack\<<scope.name>_scope> <scope.name>_stack = new Stack\<<scope.name>_scope>(); 1215 <endif> 1216 >> 1217 1218 ruleAttributeScope(scope) ::= << 1219 <if(scope)> 1220 <if(scope.attributes)> 1221 protected static class <scope.name>_scope { 1222 <scope.attributes:{it |<it.decl>;}; separator="\n"> 1223 } 1224 protected Stack\<<scope.name>_scope> <scope.name>_stack = new Stack\<<scope.name>_scope>(); 1225 <endif> 1226 <endif> 1227 >> 1228 1229 returnStructName(r) ::= "<r.name>_return" 1230 1231 returnType(ruleDescriptor) ::= <% 1232 <if(ruleDescriptor.hasMultipleReturnValues)> 1233 <ruleDescriptor.grammar.recognizerName>.<ruleDescriptor:returnStructName()> 1234 <elseif(ruleDescriptor.hasSingleReturnValue)> 1235 <ruleDescriptor.singleValueReturnType> 1236 <else> 1237 void 1238 <endif> 1239 %> 1240 1241 /** Generate the Java type associated with a single or multiple return 1242 * values. 1243 */ 1244 ruleLabelType(referencedRule) ::= <% 1245 <if(referencedRule.hasMultipleReturnValues)> 1246 <returnScopeBaseType()> 1247 <elseif(referencedRule.hasSingleReturnValue)> 1248 <referencedRule.singleValueReturnType> 1249 <else> 1250 void 1251 <endif> 1252 %> 1253 1254 delegateName(d) ::= << 1255 <if(d.label)><d.label><else>g<d.name><endif> 1256 >> 1257 1258 /** Using a type to init value map, try to init a type; if not in table 1259 * must be an object, default value is "null". 1260 */ 1261 initValue(typeName) ::= << 1262 <javaTypeInitMap.(typeName)> 1263 >> 1264 1265 /** Define a rule label including default value */ 1266 ruleLabelDef(label) ::= <% 1267 <ruleLabelType(referencedRule=label.referencedRule)> <label.label.text> = 1268 <initValue(typeName=ruleLabelType(referencedRule=label.referencedRule))>; 1269 %> 1270 1271 /** Define a return struct for a rule if the code needs to access its 1272 * start/stop tokens, tree stuff, attributes, ... Leave a hole for 1273 * subgroups to stick in members. 1274 */ 1275 returnScope(scope) ::= << 1276 <if(ruleDescriptor.hasMultipleReturnValues)> 1277 public static class <ruleDescriptor:returnStructName()> extends <returnScopeBaseType()> { 1278 <if(scope)><scope.attributes:{it |public <it.decl>;}; separator="\n"><endif> 1279 <@ruleReturnMembers()> 1280 }; 1281 <endif> 1282 >> 1283 1284 returnScopeBaseType() ::= <% 1285 <if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope 1286 %> 1287 1288 parameterScope(scope) ::= << 1289 <scope.attributes:{it |<it.decl>}; separator=", "> 1290 >> 1291 1292 parameterAttributeRef(attr) ::= "<attr.name>" 1293 parameterSetAttributeRef(attr,expr) ::= "<attr.name> =<expr>;" 1294 1295 scopeAttributeRef(scope,attr,index,negIndex) ::= <% 1296 <if(negIndex)> 1297 <scope>_stack.elementAt(<scope>_stack.size()-<negIndex>-1).<attr.name> 1298 <else> 1299 <if(index)> 1300 <scope>_stack.elementAt(<index>).<attr.name> 1301 <else> 1302 <scope>_stack.peek().<attr.name> 1303 <endif> 1304 <endif> 1305 %> 1306 1307 scopeSetAttributeRef(scope,attr,expr,index,negIndex) ::= <% 1308 <if(negIndex)> 1309 <scope>_stack.elementAt(<scope>_stack.size()-<negIndex>-1).<attr.name> =<expr>; 1310 <else> 1311 <if(index)> 1312 <scope>_stack.elementAt(<index>).<attr.name> =<expr>; 1313 <else> 1314 <scope>_stack.peek().<attr.name> =<expr>; 1315 <endif> 1316 <endif> 1317 %> 1318 1319 /** $x is either global scope or x is rule with dynamic scope; refers 1320 * to stack itself not top of stack. This is useful for predicates 1321 * like {$function.size()>0 && $function::name.equals("foo")}? 1322 */ 1323 isolatedDynamicScopeRef(scope) ::= "<scope>_stack" 1324 1325 /** reference an attribute of rule; might only have single return value */ 1326 ruleLabelRef(referencedRule,scope,attr) ::= <% 1327 <if(referencedRule.hasMultipleReturnValues)> 1328 (<scope>!=null?((<returnType(referencedRule)>)<scope>).<attr.name>:<initValue(attr.type)>) 1329 <else> 1330 <scope> 1331 <endif> 1332 %> 1333 1334 returnAttributeRef(ruleDescriptor,attr) ::= <% 1335 <if(ruleDescriptor.hasMultipleReturnValues)> 1336 retval.<attr.name> 1337 <else> 1338 <attr.name> 1339 <endif> 1340 %> 1341 1342 returnSetAttributeRef(ruleDescriptor,attr,expr) ::= <% 1343 <if(ruleDescriptor.hasMultipleReturnValues)> 1344 retval.<attr.name> =<expr>; 1345 <else> 1346 <attr.name> =<expr>; 1347 <endif> 1348 %> 1349 1350 /** How to translate $tokenLabel */ 1351 tokenLabelRef(label) ::= "<label>" 1352 1353 /** ids+=ID {$ids} or e+=expr {$e} */ 1354 listLabelRef(label) ::= "list_<label>" 1355 1356 1357 // not sure the next are the right approach 1358 1359 tokenLabelPropertyRef_text(scope,attr) ::= "(<scope>!=null?<scope>.getText():null)" 1360 tokenLabelPropertyRef_type(scope,attr) ::= "(<scope>!=null?<scope>.getType():0)" 1361 tokenLabelPropertyRef_line(scope,attr) ::= "(<scope>!=null?<scope>.getLine():0)" 1362 tokenLabelPropertyRef_pos(scope,attr) ::= "(<scope>!=null?<scope>.getCharPositionInLine():0)" 1363 tokenLabelPropertyRef_channel(scope,attr) ::= "(<scope>!=null?<scope>.getChannel():0)" 1364 tokenLabelPropertyRef_index(scope,attr) ::= "(<scope>!=null?<scope>.getTokenIndex():0)" 1365 tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1366 tokenLabelPropertyRef_int(scope,attr) ::= "(<scope>!=null?Integer.valueOf(<scope>.getText()):0)" 1367 1368 ruleLabelPropertyRef_start(scope,attr) ::= "(<scope>!=null?(<castToLabelType({<scope>.start})>):null)" 1369 ruleLabelPropertyRef_stop(scope,attr) ::= "(<scope>!=null?(<castToLabelType({<scope>.stop})>):null)" 1370 ruleLabelPropertyRef_tree(scope,attr) ::= "(<scope>!=null?((<ASTLabelType>)<scope>.getTree()):null)" 1371 ruleLabelPropertyRef_text(scope,attr) ::= <% 1372 <if(TREE_PARSER)> 1373 (<scope>!=null?(input.getTokenStream().toString( 1374 input.getTreeAdaptor().getTokenStartIndex(<scope>.start), 1375 input.getTreeAdaptor().getTokenStopIndex(<scope>.start))):null) 1376 <else> 1377 (<scope>!=null?input.toString(<scope>.start,<scope>.stop):null) 1378 <endif> 1379 %> 1380 1381 ruleLabelPropertyRef_st(scope,attr) ::= "(<scope>!=null?((StringTemplate)<scope>.getTemplate()):null)" 1382 1383 /** Isolated $RULE ref ok in lexer as it's a Token */ 1384 lexerRuleLabel(label) ::= "<label>" 1385 1386 lexerRuleLabelPropertyRef_type(scope,attr) ::= 1387 "(<scope>!=null?<scope>.getType():0)" 1388 lexerRuleLabelPropertyRef_line(scope,attr) ::= 1389 "(<scope>!=null?<scope>.getLine():0)" 1390 lexerRuleLabelPropertyRef_pos(scope,attr) ::= 1391 "(<scope>!=null?<scope>.getCharPositionInLine():-1)" 1392 lexerRuleLabelPropertyRef_channel(scope,attr) ::= 1393 "(<scope>!=null?<scope>.getChannel():0)" 1394 lexerRuleLabelPropertyRef_index(scope,attr) ::= 1395 "(<scope>!=null?<scope>.getTokenIndex():0)" 1396 lexerRuleLabelPropertyRef_text(scope,attr) ::= 1397 "(<scope>!=null?<scope>.getText():null)" 1398 lexerRuleLabelPropertyRef_int(scope,attr) ::= 1399 "(<scope>!=null?Integer.valueOf(<scope>.getText()):0)" 1400 1401 // Somebody may ref $template or $tree or $stop within a rule: 1402 rulePropertyRef_start(scope,attr) ::= "(<castToLabelType(\"retval.start\")>)" 1403 rulePropertyRef_stop(scope,attr) ::= "(<castToLabelType(\"retval.stop\")>)" 1404 rulePropertyRef_tree(scope,attr) ::= "retval.tree" 1405 rulePropertyRef_text(scope,attr) ::= <% 1406 <if(TREE_PARSER)> 1407 input.getTokenStream().toString( 1408 input.getTreeAdaptor().getTokenStartIndex(retval.start), 1409 input.getTreeAdaptor().getTokenStopIndex(retval.start)) 1410 <else> 1411 input.toString(retval.start,input.LT(-1)) 1412 <endif> 1413 %> 1414 rulePropertyRef_st(scope,attr) ::= "retval.st" 1415 1416 lexerRulePropertyRef_text(scope,attr) ::= "getText()" 1417 lexerRulePropertyRef_type(scope,attr) ::= "_type" 1418 lexerRulePropertyRef_line(scope,attr) ::= "state.tokenStartLine" 1419 lexerRulePropertyRef_pos(scope,attr) ::= "state.tokenStartCharPositionInLine" 1420 lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1421 lexerRulePropertyRef_channel(scope,attr) ::= "_channel" 1422 lexerRulePropertyRef_start(scope,attr) ::= "state.tokenStartCharIndex" 1423 lexerRulePropertyRef_stop(scope,attr) ::= "(getCharIndex()-1)" 1424 lexerRulePropertyRef_int(scope,attr) ::= "Integer.valueOf(<scope>.getText())" 1425 1426 // setting $st and $tree is allowed in local rule. everything else 1427 // is flagged as error 1428 ruleSetPropertyRef_tree(scope,attr,expr) ::= "retval.tree =<expr>;" 1429 ruleSetPropertyRef_st(scope,attr,expr) ::= "retval.st =<expr>;" 1430 1431 /** How to execute an action (only when not backtracking) */ 1432 execAction(action) ::= <% 1433 <if(backtracking)> 1434 if ( <actions.(actionScope).synpredgate> ) { 1435 <action> 1436 } 1437 <else> 1438 <action> 1439 <endif> 1440 %> 1441 1442 /** How to always execute an action even when backtracking */ 1443 execForcedAction(action) ::= "<action>" 1444 1445 // M I S C (properties, etc...) 1446 1447 bitset(name, words64) ::= << 1448 public static final BitSet <name> = new BitSet(new long[]{<words64:{it |<it>L};separator=",">}); 1449 >> 1450 1451 codeFileExtension() ::= ".java" 1452 1453 true_value() ::= "true" 1454 false_value() ::= "false" 1455 1456 isEmptyString ::= [ 1457 "" : true, 1458 default : false 1459 ] 1460 1461 isTrue ::= [ 1462 "true" : true, 1463 default : false 1464 ] 1465 1466 isDefaultLabelType ::= [ 1467 "Token" : true, 1468 default : false 1469 ] 1470 1471 isPredefinedRewriteRule ::= [ 1472 "topdown" : true, 1473 "bottomup" : true, 1474 default : false 1475 ] 1476 1477 castToLabelType(value) ::= <% 1478 <if(!isDefaultLabelType.(labelType))> 1479 (<labelType>) 1480 <endif> 1481 <value> 1482 %> 1483