1/* [The "BSD license"] 2 Copyright (c) 2008 Erik van Bilsen 3 Copyright (c) 2007-2008 Johannes Luber 4 Copyright (c) 2005-2007 Kunle Odutola 5 Copyright (c) 2005-2006 Terence Parr 6 All rights reserved. 7 8 Redistribution and use in source and binary forms, with or without 9 modification, are permitted provided that the following conditions 10 are met: 11 1. Redistributions of source code must retain the above copyright 12 notice, this list of conditions and the following disclaimer. 13 2. Redistributions in binary form must reproduce the above copyright 14 notice, this list of conditions and the following disclaimer in the 15 documentation and/or other materials provided with the distribution. 16 3. The name of the author may not be used to endorse or promote products 17 derived from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 20 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 21 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 22 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 24 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29*/ 30group Delphi; 31 32csharpTypeInitMap ::= [ 33 "int":"0", 34 "uint":"0", 35 "long":"0", 36 "ulong":"0", 37 "float":"0.0", 38 "double":"0.0", 39 "bool":"False", 40 "byte":"0", 41 "sbyte":"0", 42 "short":"0", 43 "ushort":"0", 44 "char":"#0", 45 "string":"''", 46 "String":"''", 47 default:"nil" // anything other than an atomic type 48] 49 50/** The overall file structure of a recognizer; stores methods for rules 51 * and cyclic DFAs plus support code. 52 * LEXER (Boolean): should we generate lexer code? 53 * PARSER (Boolean): should we generate parser code? 54 * TREE_PARSER (Boolean): should we generate tree parser code? 55 * actionScope (String): 'lexer', 'parser', 'tree_parser' or custom scope 56 * actions (HashMap): 57 * docComment (String): document comment 58 * recognizer (Object): recognizer class generator 59 * name (String): name of grammar 60 * tokens (HashMap<name: String, type: Integer>): 61 * tokenNames: 62 * rules: 63 * cyclicDFAs: 64 * bitsets: 65 * buildTemplate (Boolean): should we generate a string template? 66 * buildAST (Boolean): should we generate an AST? 67 * rewriteMode (Boolean): are we rewriteing nodes? 68 * profile (Boolean): 69 * backtracking (Boolean): backtracking mode? 70 * synpreds (): syntactic predicates 71 * memoize (Boolean): should we memoize? 72 * numRules (Integer): number of rules 73 * fileName (String): fully qualified name of original .g file 74 * ANTLRVersion (String): ANTLR version in Major.Minor.Build format 75 * generatedTimestamp (String): date/time when the file is generated 76 * trace (Boolean): should we trace input/output? 77 * scopes: 78 * superClass (String): name of base class, or empty string 79 * literals: 80 */ 81outputFile(LEXER,PARSER,TREE_PARSER, actionScope, actions, 82 docComment, recognizer, 83 name, tokens, tokenNames, rules, cyclicDFAs, 84 bitsets, buildTemplate, buildAST, rewriteMode, profile, 85 backtracking, synpreds, memoize, numRules, 86 fileName, ANTLRVersion, generatedTimestamp, trace, 87 scopes, superClass, literals) ::= 88<< 89unit <name>; 90 91{$HINTS OFF} 92 93// $ANTLR <ANTLRVersion> <fileName> <generatedTimestamp> 94 95<actions.(actionScope).header> 96 97interface 98 99<@imports> 100uses<\n> 101<@end> 102 <actions.(actionScope).usesInterface> 103<if(TREE_PARSER)> 104 Antlr.Runtime.Tree,<\n> 105<endif> 106 Antlr.Runtime, 107 Antlr.Runtime.Collections, 108 Antlr.Runtime.Tools; 109 110<docComment> 111<recognizer> 112>> 113 114/** Generates source code for the lexer class 115 * grammar (Grammar object) 116 */ 117lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token", 118 filterMode, superClass="Lexer") ::= << 119type 120 I<grammar.recognizerName> = interface(I<@superClassName><superClass><@end>) 121 end; 122 123 T<grammar.recognizerName> = class(T<@superClassName><superClass><@end>, I<grammar.recognizerName>) 124 strict private 125 FCnt: array [0..<grammar.numberOfDecisions>] of Byte; 126 FLA: array [0..<grammar.numberOfDecisions>, 0..255] of Integer; 127 FException: ERecognitionException; 128 procedure InitializeCyclicDFAs; 129 <cyclicDFAs:cyclicDFADeclaration()> 130 public 131 const 132 <tokens:{<it.name> = <it.type>;}; separator="\n"> 133 <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}> 134 strict private 135 <actions.(actionScope).memberDeclarations> 136 public 137 // delegates 138 <grammar.delegates: {g|<g:delegateName()>: I<superClass>; {<g.recognizerName>}}; separator="\n"> 139 public 140 // delegators 141 <grammar.delegators: {g|<g:delegateName()>: Pointer; {<g.recognizerName>}}; separator="\n"> 142 <last(grammar.delegators):{g|gParent: Pointer; {<g.recognizerName>}}> 143 protected 144 { IBaseRecognizer } 145 function GetGrammarFileName: String; override; 146<if(filterMode)> 147 function AlreadyParsedRule(const Input: IIntStream; 148 const RuleIndex: Integer): Boolean; override; 149 procedure Memoize(const Input: IIntStream; const RuleIndex, 150 RuleStartIndex: Integer); override; 151 protected 152 { ILexer } 153 function NextToken: IToken; override;<\n> 154<endif> 155 protected 156 { ILexer } 157 procedure DoTokens; override; 158 public 159 constructor Create; overload; 160 constructor Create(const AInput: ICharStream<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload; 161 constructor Create(const AInput: ICharStream; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload; 162 163 <rules: {r | <if(!r.ruleDescriptor.isSynPred)><lexerRuleDeclaration(r)><endif>}> 164 <synpreds:{p | <lexerSynpredDeclaration(p)>}; separator="\n"> 165 end; 166 167implementation 168 169uses 170 <grammar.delegates: {g|<g.recognizerName>,}; separator="\n"> 171 <grammar.delegators: {g|<g.recognizerName>,}; separator="\n"> 172 <actions.(actionScope).usesImplementation> 173 SysUtils, 174 StrUtils, 175 Math; 176 177{ T<grammar.recognizerName> } 178 179constructor T<grammar.recognizerName>.Create; 180begin 181 InitializeCyclicDFAs; 182end; 183 184constructor T<grammar.recognizerName>.Create(const AInput: ICharStream<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 185begin 186 Create(AInput, nil<grammar.delegators:{g|, A<g:delegateName()>}>); 187end; 188 189constructor T<grammar.recognizerName>.Create(const AInput: ICharStream; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 190begin 191 inherited Create(AInput, AState); 192 InitializeCyclicDFAs; { TODO: Necessary in Delphi??? Not removed yet. } 193 <if(memoize)> 194 <if(grammar.grammarIsRoot)> 195 State.RuleMemoCount := <numRules>+1;<\n> <! index from 1..n !> 196 <endif> 197 <endif> 198 <grammar.directDelegates: 199 {g|<g:delegateName()> := T<g.recognizerName>.Create(AInput, State<trunc(g.delegators):{p|, <p:delegateName()>}>, Self);}; separator="\n"> 200 <grammar.delegators: 201 {g|<g:delegateName()> := Pointer(A<g:delegateName()>);}; separator="\n"> 202 <last(grammar.delegators):{g|gParent := Pointer(A<g:delegateName()>);}> 203 <actions.(actionScope).memberInitializations> 204end; 205<actions.(actionScope).memberImplementations> 206function T<grammar.recognizerName>.GetGrammarFileName: String; 207begin 208 Result := '<fileName>'; 209end; 210 211<if(filterMode)> 212<filteringNextToken()> 213<endif> 214 215<rules; separator="\n\n"> 216<synpreds:{p | <lexerSynpred(p)>}> 217 218procedure T<grammar.recognizerName>.InitializeCyclicDFAs; 219begin 220 <cyclicDFAs:{dfa | FDFA<dfa.decisionNumber> := TDFA<dfa.decisionNumber>.Create(Self<@debugAddition()>);}; separator="\n"> 221 <cyclicDFAs:{dfa | <if(dfa.specialStateSTs)>FDFA<dfa.decisionNumber>.SpecialStateTransitionHandler := DFA<dfa.decisionNumber>_SpecialStateTransition;<endif>}; separator="\n"> 222end; 223 224<cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 225end.>> 226 227lexerRuleDeclaration(rule) ::= << 228procedure m<rule.ruleName>(<rule.ruleDescriptor.parameterScope:parameterScope(scope=rule)>);<\n> 229>> 230 231/** A override of Lexer.nextToken() that backtracks over mTokens() looking 232 * for matches. No error can be generated upon error; just rewind, consume 233 * a token and then try again. backtracking needs to be set as well. 234 * 235 * Make rule memoization happen only at levels above 1 as we start mTokens 236 * at backtracking==1. 237 */ 238filteringNextToken() ::= << 239function T<grammar.recognizerName>.NextToken: IToken; 240var 241 M: Integer; 242begin 243 while (True) do 244 begin 245 if (Input.LA(1) = Integer(cscEOF)) then 246 Exit(TToken.EOF_TOKEN); 247 248 State.Token := nil; 249 State.Channel := TToken.DEFAULT_CHANNEL; 250 State.TokenStartCharIndex := Input.Index; 251 State.TokenStartCharPositionInLine := Input.CharPositionInLine; 252 State.TokenStartLine := Input.Line; 253 State.Text := ''; 254 try 255 M := Input.Mark(); 256 State.Backtracking := 1; <! means we won't throw slow exception !> 257 State.Failed := False; 258 mTokens(); 259 State.Backtracking := 0; 260<! 261 mTokens backtracks with synpred at backtracking==2 262 and we set the synpredgate to allow actions at level 1. 263!> 264 if (State.Failed) then 265 begin 266 Input.Rewind(M); 267 Input.Consume; <! // advance one char and try again !> 268 end 269 else 270 begin 271 Emit; 272 Exit(State.Token); 273 end; 274 except 275 on RE: ERecognitionException do 276 begin 277 // shouldn't happen in backtracking mode, but... 278 ReportError(RE); 279 Recover(RE); 280 end; 281 end; 282 end; 283end; 284 285function T<grammar.recognizerName>.AlreadyParsedRule(const Input: IIntStream; 286 const RuleIndex: Integer): Boolean; 287begin 288 if (State.Backtracking > 1) then 289 Result := inherited AlreadyParsedRule(Input, RuleIndex) 290 else 291 Result := False; 292end; 293 294procedure T<grammar.recognizerName>.Memoize(const Input: IIntStream; const RuleIndex, 295 RuleStartIndex: Integer); 296begin 297 if (State.Backtracking > 1) then 298 inherited Memoize(Input, RuleIndex, RuleStartIndex); 299end; 300 301>> 302 303filteringActionGate() ::= "(State.Backtracking = 1)" 304 305/** How to generate a parser */ 306genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 307 bitsets, inputStreamType, superClass, filterMode, 308 ASTLabelType="ANTLRInterface", labelType, members, rewriteElementType) ::= << 309type 310 <rules: {r | <genericParserRuleReturnType(rule=r, ruleDescriptor=r.ruleDescriptor)>}> 311 I<grammar.recognizerName> = interface(I<@superClassName><superClass><@end>) 312 <rules: {r | <genericParserRuleInterface(rule=r, ruleDescriptor=r.ruleDescriptor)>}> 313 end; 314 315 T<grammar.recognizerName> = class(T<@superClassName><superClass><@end>, I<grammar.recognizerName>) 316<if(grammar.grammarIsRoot)> 317 public 318 const 319 TOKEN_NAMES: array [0..<length(tokenNames)>+3] of String = ( 320 '\<invalid>', 321 '\<EOR>', 322 '\<DOWN>', 323 '\<UP>', 324 <tokenNames; separator=",\n">);<\n> 325<endif> 326 public 327 const 328 <tokens:{<it.name> = <it.type>;}; separator="\n"> 329 public 330 // delegates 331 <grammar.delegates: {g|<g:delegateName()>: I<superClass>; {<g.recognizerName>}}; separator="\n"> 332 public 333 // delegators 334 <grammar.delegators: {g|<g:delegateName()>: Pointer; {<g.recognizerName>}}; separator="\n"> 335 <last(grammar.delegators):{g|gParent: Pointer; {<g.recognizerName>}}> 336 337 <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScopeDeclaration(scope=it)><endif>}> 338<@members> 339 <! WARNING. bug in ST: this is cut-n-paste into Dbg.stg !> 340 public 341 constructor Create(const AInput: <inputStreamType><grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload; 342 constructor Create(const AInput: <inputStreamType>; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); overload; 343<@end> 344 protected 345 { IBaseRecognizer } 346 function GetTokenNames: TStringArray; override; 347 function GetGrammarFileName: String; override; 348 strict private 349 <actions.(actionScope).memberDeclarations> 350 <rules: {r | <genericParserRuleDeclaration(rule=r, ruleDescriptor=r.ruleDescriptor)>}> 351 352<! generate rule/method definitions for imported rules so they 353 appear to be defined in this recognizer. !> 354 // Delegated rules 355 <grammar.delegatedRules:{ruleDescriptor| <delegatedRuleDeclaration(ruleDescriptor)>}> 356 357 <synpreds:{p | <synpredDeclaration(p)>}; separator="\n"> 358 <cyclicDFAs:cyclicDFADeclaration()> 359 strict private 360 FException: ERecognitionException; 361 FLA: array [0..<grammar.numberOfDecisions>, 0..255] of Integer; 362 FCnt: array [0..<grammar.numberOfDecisions>] of Byte; 363 procedure InitializeCyclicDFAs; 364<if(bitsets)> 365 public 366 class var 367 <bitsets:bitsetDecl(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>})> 368 public 369 class procedure InitializeBitsets; static;<\n> 370<endif> 371 end; 372 373implementation 374 375uses 376 <grammar.delegates: {g|<g.recognizerName>,}; separator="\n"> 377 <grammar.delegators: {g|<g.recognizerName>,}; separator="\n"> 378 <actions.(actionScope).usesImplementation> 379 SysUtils, 380 StrUtils, 381 Math; 382 383{ T<grammar.recognizerName> } 384 385constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType><grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 386begin 387 Create(AInput, TRecognizerSharedState.Create<grammar.delegators:{g|, A<g:delegateName()>}>); 388end; 389 390constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType>; 391 const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 392begin 393 inherited Create(AInput, AState); 394 <@membersConstructor> 395 <@end> 396 <parserCtorBody()> 397 <grammar.directDelegates:{g|<g:delegateName()> := T<g.recognizerName>.Create(Input, State<trunc(g.delegators):{p|, <p:delegateName()>}>, Self);}; separator="\n"> 398 <grammar.indirectDelegates:{g | <g:delegateName()> := <g.delegator:delegateName()>.<g:delegateName()>;}; separator="\n"> 399 <last(grammar.delegators):{g|gParent := Pointer(A<g:delegateName()>);}> 400 <rules: {r | <ruleAttributeScopeInit(scope=r.ruleDescriptor.ruleScope)>}> 401 <scopes:{<if(it.isDynamicGlobalScope)><globalAttributeScope(scope=it)><endif>}> 402 <actions.(actionScope).memberInitializations> 403end; 404<actions.(actionScope).memberImplementations> 405 406<grammar.delegatedRules:{ruleDescriptor| <delegatedRuleImplementation(ruleDescriptor)>}; separator="\n"> 407procedure T<grammar.recognizerName>.InitializeCyclicDFAs; 408begin 409 <cyclicDFAs:{dfa | FDFA<dfa.decisionNumber> := TDFA<dfa.decisionNumber>.Create(Self);}; separator="\n"> 410 <cyclicDFAs:{dfa | <if(dfa.specialStateSTs)>FDFA<dfa.decisionNumber>.SpecialStateTransitionHandler := DFA<dfa.decisionNumber>_SpecialStateTransition;<endif>}; separator="\n"> 411end; 412 413<if(bitsets)> 414class procedure T<grammar.recognizerName>.InitializeBitsets; 415begin 416 <bitsets:bitset(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>}, words64=it.bits)> 417end; 418<endif> 419 420<@membersImplementation> 421 <@end> 422 423function T<grammar.recognizerName>.GetTokenNames: TStringArray; 424var 425 I: Integer; 426begin 427 SetLength(Result,Length(T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES)); 428 for I := 0 to Length(T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES) - 1 do 429 Result[I] := T<grammar.composite.rootGrammar.recognizerName>.TOKEN_NAMES[I]; 430end; 431 432function T<grammar.recognizerName>.GetGrammarFileName: String; 433begin 434 Result := '<fileName>'; 435end; 436 437<rules; separator="\n\n"> 438<synpreds:{p | <synpred(p)>}> 439 440<cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 441<if(bitsets)> 442initialization 443 T<grammar.recognizerName>.InitializeBitsets;<\n> 444<endif> 445end.>> 446 447delegatedRuleDeclaration(ruleDescriptor) ::= << 448<if(ruleDescriptor.hasMultipleReturnValues)> 449function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n> 450<else> 451<if(ruleDescriptor.hasSingleReturnValue)> 452function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n> 453<else> 454procedure <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n> 455<endif> 456<endif> 457>> 458 459delegatedRuleImplementation(ruleDescriptor) ::= << 460<if(ruleDescriptor.hasMultipleReturnValues)> 461function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n> 462<else> 463<if(ruleDescriptor.hasSingleReturnValue)> 464function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n> 465<else> 466procedure T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n> 467<endif> 468<endif> 469begin 470 <if(ruleDescriptor.hasReturnValue)>Result :=<endif> T<ruleDescriptor.grammar.recognizerName>(<ruleDescriptor.grammar:delegateName()>.Implementor).<ruleDescriptor.name>(<ruleDescriptor.parameterScope.attributes:{a|<a.name>}; separator=", ">); 471end; 472 473>> 474 475parserCtorBody() ::= << 476InitializeCyclicDFAs; 477<if(memoize)> 478<if(grammar.grammarIsRoot)> 479State.RuleMemoCount := <length(grammar.allImportedRules)>+1;<\n> <! index from 1..n !> 480<endif> 481<endif> 482<grammar.delegators: {g|<g:delegateName()> := Pointer(A<g:delegateName()>);}; separator="\n"> 483>> 484 485parser(grammar, name, scopes, tokens, tokenNames, rules, numRules, bitsets, ASTLabelType, superClass="Parser", labelType="Token", members={<actions.parser.members>}) ::= << 486<genericParser(inputStreamType="ITokenStream", rewriteElementType="Token", ...)> 487>> 488 489/** How to generate a tree parser; same as parser except the input 490 * stream is a different type. 491 */ 492treeParser(grammar, name, scopes, tokens, tokenNames, globalAction, rules, numRules, bitsets, labelType={<ASTLabelType>}, ASTLabelType="object", superClass="TreeParser", members={<actions.treeparser.members>}, filterMode) ::= << 493<genericParser(inputStreamType="ITreeNodeStream", rewriteElementType="Node", ...)> 494>> 495 496/** A simpler version of a rule template that is specific to the imaginary 497 * rules created for syntactic predicates. As they never have return values 498 * nor parameters etc..., just give simplest possible method. Don't do 499 * any of the normal memoization stuff in here either; it's a waste. 500 * As predicates cannot be inlined into the invoking rule, they need to 501 * be in a rule by themselves. 502 */ 503synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 504<< 505// $ANTLR start "<ruleName>" 506procedure T<grammar.recognizerName>.<ruleName>_fragment(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 507var 508 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 509 <ruleLabelDefVars()> 510begin 511 <ruleLabelDefs()> 512<if(trace)> 513 TraceIn('<ruleName>_fragment', <ruleDescriptor.index>); 514 try 515 <block> 516 finally 517 TraceOut('<ruleName>_fragment', <ruleDescriptor.index>); 518 end; 519<else> 520 <block> 521<endif> 522end; 523// $ANTLR end "<ruleName>" 524>> 525 526synpredDecls(name) ::= << 527SynPredPointer <name>;<\n> 528>> 529 530synpred(name) ::= << 531 532function T<grammar.recognizerName>.<name>: Boolean; 533var 534 Start: Integer; 535 Success: Boolean; 536begin 537 State.Backtracking := State.Backtracking + 1; 538 <@start()> 539 Start := Input.Mark; 540 try 541 <name>_fragment(); // can never throw exception 542 except 543 on RE: ERecognitionException do 544 WriteLn('Impossible: ' + RE.ToString); 545 end; 546 Success := not State.Failed; 547 Input.Rewind(Start); 548 <@stop()> 549 State.Backtracking := State.Backtracking - 1; 550 State.Failed := False; 551 Result := Success; 552end;<\n> 553>> 554 555lexerSynpred(name) ::= << 556<synpred(name)> 557>> 558 559lexerSynpredDeclaration(name) ::= << 560function <name>: Boolean; 561procedure <name>_fragment; 562>> 563 564synpredDeclaration(name) ::= << 565function <name>: Boolean; 566procedure <name>_fragment; 567>> 568 569ruleMemoization(name) ::= << 570<if(memoize)> 571if ((State.Backtracking > 0) and AlreadyParsedRule(Input, <ruleDescriptor.index>)) then 572 Exit(<ruleReturnValue()>); 573<endif> 574>> 575 576/** How to test for failure and return from rule */ 577checkRuleBacktrackFailure() ::= << 578<if(backtracking)><\n>if (State.Failed) then Exit(<ruleReturnValue()>);<\n><endif> 579>> 580 581/** This rule has failed, exit indicating failure during backtrack */ 582ruleBacktrackFailure() ::= << 583<if(backtracking)>if (State.Backtracking > 0) then 584begin 585 State.Failed := True; 586 Exit(<ruleReturnValue()>); 587end;<endif> 588>> 589 590genericParserRuleDeclaration(rule, ruleDescriptor) ::= << 591<if(ruleDescriptor.isSynPred)> 592<else> 593<ruleAttributeScopeDeclaration(scope=ruleDescriptor.ruleScope)> 594<returnScopeDeclaration(scope=ruleDescriptor.returnScope)> 595public 596<if(ruleDescriptor.hasMultipleReturnValues)> 597 function <rule.ruleName>: I<returnType()>;<\n> 598<else> 599<if(ruleDescriptor.hasSingleReturnValue)> 600 function <rule.ruleName>: <returnType()>;<\n> 601<else> 602 procedure <rule.ruleName>;<\n> 603<endif> 604<endif> 605<endif> 606>> 607 608genericParserRuleInterface(rule, ruleDescriptor) ::= << 609<if(ruleDescriptor.isSynPred)> 610<else> 611<if(ruleDescriptor.hasMultipleReturnValues)> 612function <rule.ruleName>: I<returnType()>;<\n> 613<else> 614<if(ruleDescriptor.hasSingleReturnValue)> 615function <rule.ruleName>: <returnType()>;<\n> 616<else> 617procedure <rule.ruleName>;<\n> 618<endif> 619<endif> 620<endif> 621>> 622 623genericParserRuleReturnType(rule, ruleDescriptor) ::= << 624<if(ruleDescriptor.hasMultipleReturnValues)> 625<if(ruleDescriptor.isSynPred)> 626<else> 627I<returnType()> = interface(I<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope) 628end;<\n> 629<endif> 630<endif> 631>> 632 633/** How to generate code for a rule. This includes any return type 634 * data aggregates required for multiple return values. 635 */ 636rule(ruleName,ruleDescriptor,block,emptyRule,description,exceptions,finally,memoize) ::= << 637<ruleAttributeScope(scope=ruleDescriptor.ruleScope)> 638<returnScope(scope=ruleDescriptor.returnScope)> 639 640// $ANTLR start "<ruleName>" 641(* <fileName>:<description> *) 642<if(ruleDescriptor.hasMultipleReturnValues)> 643function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>; 644<else> 645<if(ruleDescriptor.hasSingleReturnValue)> 646function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>; 647<else> 648procedure T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 649<endif> 650<endif> 651 652var 653<ruleDescriptor.actions.vars> 654 Locals: TLocalStorage; 655<if(ruleDescriptor.hasMultipleReturnValues)> 656 RetVal: I<returnType()>;<\n> 657<else> 658<if(ruleDescriptor.hasSingleReturnValue)> 659 RetVal: <returnType()>;<\n> 660<else> 661<endif> 662<endif> 663 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 664 <ruleDeclarationVars()> 665 <ruleLabelDefVars()> 666begin 667 Locals.Initialize; 668 try 669 <if(trace)>TraceIn('<ruleName>', <ruleDescriptor.index>);<endif> 670 <ruleScopeSetUp()> 671 <ruleDeclarations()> 672 <ruleLabelDefs()> 673 <ruleDescriptor.actions.init> 674 <@preamble()> 675 try 676 try 677 <ruleMemoization(name=ruleName)> 678 <block> 679 <ruleCleanUp()> 680 <(ruleDescriptor.actions.after):execAction()> 681<if(exceptions)> 682 <exceptions:{e|<catch(decl=e.decl,action=e.action)><\n>}> 683<else> 684<if(!emptyRule)> 685<if(actions.(actionScope).rulecatch)> 686 <actions.(actionScope).rulecatch> 687<else> 688 except 689 on RE: ERecognitionException do 690 begin 691 ReportError(RE); 692 Recover(Input,RE); 693 <@setErrorReturnValue()> 694 end;<\n> 695<endif> 696<endif> 697<endif> 698 end; 699 finally 700 <if(trace)>TraceOut("<ruleName>", <ruleDescriptor.index>);<endif> 701 <memoize()> 702 <ruleScopeCleanUp()> 703 <finally> 704 end; 705 <@postamble()> 706 finally 707 Locals.Finalize; 708 end; 709 Exit(<ruleReturnValue()>); 710end; 711// $ANTLR end "<ruleName>" 712>> 713 714catch(decl,action) ::= << 715catch (<e.decl>) 716{ 717 <e.action> 718} 719>> 720 721ruleDeclarations() ::= << 722<if(ruleDescriptor.hasMultipleReturnValues)> 723RetVal := T<returnType()>.Create; 724RetVal.Start := Input.LT(1);<\n> 725<else> 726<ruleDescriptor.returnScope.attributes:{ a | 727<a.name> := <if(a.initValue)><a.initValue><else><initValue(a.type)><endif>; 728}> 729<endif> 730<if(memoize)> 731<ruleDescriptor.name>_StartIndex := Input.Index(); 732<endif> 733>> 734 735ruleDeclarationVars() ::= << 736<if(ruleDescriptor.hasMultipleReturnValues)> 737<else> 738<ruleDescriptor.returnScope.attributes:{ a | 739<a.name>: <a.type>; 740}> 741<endif> 742<if(memoize)> 743<ruleDescriptor.name>_StartIndex: Integer; 744<endif> 745>> 746 747ruleScopeSetUp() ::= << 748<ruleDescriptor.useScopes:{<it>Stack.Push(T<it>Scope.Create);}; separator="\n"> 749<ruleDescriptor.ruleScope:{<it.name>Stack.Push(T<it.name>Scope.Create);}; separator="\n"> 750>> 751 752ruleScopeCleanUp() ::= << 753<ruleDescriptor.useScopes:{<it>Stack.Pop();}; separator="\n"> 754<ruleDescriptor.ruleScope:{<it.name>Stack.Pop;}; separator="\n"> 755>> 756 757ruleLabelDefs() ::= << 758<[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels]:{<it.label.text> := nil;}; separator="\n"> 759<[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels]:{list_<it.label.text> := nil;}; separator="\n"> 760<ruleDescriptor.ruleLabels:ruleLabelDef(label=it); separator="\n"> 761<ruleDescriptor.ruleListLabels:{ll|<ll.label.text> := nil;}; separator="\n"> 762>> 763 764ruleLabelDefVars() ::= << 765<[ruleDescriptor.tokenLabels,ruleDescriptor.tokenListLabels]:{<it.label.text>: I<labelType>;}; separator="\n"> 766<[ruleDescriptor.tokenListLabels,ruleDescriptor.ruleListLabels]:{list_<it.label.text>: IList\<IANTLRInterface\>;}; separator="\n"> 767<ruleDescriptor.ruleLabels:ruleLabelDefVar(label=it); separator="\n"> 768<ruleDescriptor.ruleListLabels:{ll|<ll.label.text>: <ruleLabelType(referencedRule=ll.referencedRule)>;}; separator="\n"> 769>> 770 771lexerRuleLabelDefs() ::= << 772<[ruleDescriptor.tokenLabels, 773 ruleDescriptor.tokenListLabels, 774 ruleDescriptor.ruleLabels] 775 :{<it.label.text> := nil;}; separator="\n" 776> 777<ruleDescriptor.charLabels:{int <it.label.text>;}; separator="\n"> 778<[ruleDescriptor.tokenListLabels, 779 ruleDescriptor.ruleListLabels, 780 ruleDescriptor.ruleListLabels] 781 :{List_<it.label.text> := nil;}; separator="\n" 782> 783>> 784 785lexerRuleLabelDefDeclarations() ::= << 786<[ruleDescriptor.tokenLabels, 787 ruleDescriptor.tokenListLabels, 788 ruleDescriptor.ruleLabels] 789 :{<it.label.text>: I<labelType>;}; separator="\n" 790> 791<ruleDescriptor.charLabels:{int <it.label.text>;}; separator="\n"> 792<[ruleDescriptor.tokenListLabels, 793 ruleDescriptor.ruleListLabels, 794 ruleDescriptor.ruleListLabels] 795 :{List_<it.label.text>: IList;}; separator="\n" 796> 797>> 798 799ruleReturnValue() ::= << 800<if(!ruleDescriptor.isSynPred)> 801<if(ruleDescriptor.hasReturnValue)> 802<if(ruleDescriptor.hasSingleReturnValue)> 803<ruleDescriptor.singleValueReturnName> 804<else> 805RetVal 806<endif> 807<else> 808<! nil !> 809<endif> 810<endif> 811>> 812 813ruleCleanUp() ::= << 814<if(ruleDescriptor.hasMultipleReturnValues)> 815<if(!TREE_PARSER)> 816RetVal.Stop := Input.LT(-1); 817<endif> 818<endif> 819>> 820 821memoize() ::= << 822<if(memoize)> 823<if(backtracking)> 824if (State.Backtracking > 0) then 825 Memoize(Input, <ruleDescriptor.index>, <ruleDescriptor.name>_StartIndex); 826<endif> 827<endif> 828>> 829 830/** How to generate a rule in the lexer; naked blocks are used for 831 * fragment rules. 832 */ 833lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 834// $ANTLR start "<ruleName>" 835<ruleDescriptor.parameterScope> 836procedure T<grammar.recognizerName>.m<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 837var 838 <ruleDescriptor.actions.vars> 839 Locals: TLocalStorage; 840 TokenType, Channel: Integer; 841 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 842 <lexerRuleLabelDefDeclarations()> 843begin 844 Locals.Initialize; 845 try 846 <ruleAttributeScope(scope=ruleDescriptor.ruleScope)> 847 <if(trace)>TraceIn("<ruleName>", <ruleDescriptor.index>);<endif> 848 <ruleScopeSetUp()> 849 <ruleDeclarations()> 850 try 851<if(nakedBlock)> 852 <ruleMemoization(name=ruleName)> 853 <lexerRuleLabelDefs()> 854 <ruleDescriptor.actions.init> 855 <block><\n> 856<else> 857 TokenType := <ruleName>; 858 Channel := DEFAULT_TOKEN_CHANNEL; 859 <ruleMemoization(name=ruleName)> 860 <lexerRuleLabelDefs()> 861 <ruleDescriptor.actions.init> 862 <block> 863 <ruleCleanUp()> 864 State.TokenType := TokenType; 865 State.Channel := Channel; 866 <(ruleDescriptor.actions.after):execAction()> 867<endif> 868 finally 869 <if(trace)>TraceOut("<ruleName>", <ruleDescriptor.index>);<endif> 870 <ruleScopeCleanUp()> 871 <memoize()> 872 end; 873 finally 874 Locals.Finalize; 875 end; 876end; 877// $ANTLR end "<ruleName>" 878>> 879 880/** How to generate code for the implicitly-defined lexer grammar rule 881 * that chooses between lexer rules. 882 */ 883tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 884procedure T<grammar.recognizerName>.mTokens; 885var 886 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 887begin 888 <block> 889end; 890 891procedure T<grammar.recognizerName>.DoTokens; 892begin 893 mTokens; 894end; 895>> 896 897// S U B R U L E S 898 899/** A (...) subrule with multiple alternatives */ 900block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 901(* <fileName>:<description> *) 902Alt[<decisionNumber>] := <maxAlt>; 903<decls> 904<@predecision()> 905<decision> 906<@postdecision()> 907<@prebranch()> 908case Alt[<decisionNumber>] of 909 <alts:altSwitchCase()> 910end; 911<@postbranch()> 912>> 913 914/** A rule block with multiple alternatives */ 915ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 916(* <fileName>:<description> *) 917Alt[<decisionNumber>] := <maxAlt>; 918<decls> 919<@predecision()> 920<decision> 921<@postdecision()> 922case Alt[<decisionNumber>] of 923 <alts:altSwitchCase()> 924end; 925>> 926 927ruleBlockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 928(* <fileName>:<description> *) 929<decls> 930<@prealt()> 931<alts> 932<@postalt()> 933>> 934 935/** A special case of a (...) subrule with a single alternative */ 936blockSingleAlt(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,description) ::= << 937(* <fileName>:<description> *) 938<decls> 939<@prealt()> 940<alts> 941<@postalt()> 942>> 943 944/** A (..)+ block with 1 or more alternatives */ 945positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 946(* <fileName>:<description> *) 947FCnt[<decisionNumber>] := 0; 948<decls> 949<@preloop()> 950while (True) do 951begin 952 Alt[<decisionNumber>] := <maxAlt>; 953 <@predecision()> 954 <decision> 955 <@postdecision()> 956 case Alt[<decisionNumber>] of 957 <alts:altSwitchCase()> 958 else 959 begin 960 if (FCnt[<decisionNumber>] >= 1) then 961 Break; 962 <ruleBacktrackFailure()> 963 raise EEarlyExitException.Create(<decisionNumber>, Input); 964 <@earlyExitException()> 965 end; 966 end; 967 Inc(FCnt[<decisionNumber>]); 968end; 969<@postloop()> 970>> 971 972positiveClosureBlockSingleAlt ::= positiveClosureBlock 973 974/** A (..)* block with 1 or more alternatives */ 975closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 976(* <fileName>:<description> *) 977<decls> 978<@preloop()> 979while (True) do 980begin 981 Alt[<decisionNumber>] := <maxAlt>; 982 <@predecision()> 983 <decision> 984 <@postdecision()> 985 case Alt[<decisionNumber>] of 986 <alts:altSwitchCase()> 987 else 988 Break; 989 end; 990end; 991<@postloop()> 992>> 993 994closureBlockSingleAlt ::= closureBlock 995 996/** Optional blocks (x)? are translated to (x|) by before code generation 997 * so we can just use the normal block template 998 */ 999optionalBlock ::= block 1000 1001optionalBlockSingleAlt ::= block 1002 1003/** A case in a switch that jumps to an alternative given the alternative 1004 * number. A DFA predicts the alternative and then a simple switch 1005 * does the jump to the code that actually matches that alternative. 1006 */ 1007altSwitchCase() ::= << 1008<i>: 1009 <@prealt()> 1010 <it><\n> 1011>> 1012 1013/** An alternative is just a list of elements; at outermost level */ 1014alt(elements,altNum,description,autoAST,outerAlt,treeLevel,rew) ::= << 1015(* <fileName>:<description> *) 1016begin 1017 <@declarations()> 1018 <elements:element()> 1019 <rew> 1020 <@cleanup()> 1021end; 1022>> 1023 1024/** What to emit when there is no rewrite. For auto build 1025 * mode, does nothing. 1026 */ 1027noRewrite(rewriteBlockLevel, treeLevel) ::= "" 1028 1029// E L E M E N T S 1030 1031/** Dump the elements one per line */ 1032element() ::= << 1033<@prematch()> 1034<it.el> 1035>> 1036 1037/** match a token optionally with a label in front */ 1038tokenRef(token,label,elementIndex,terminalOptions) ::= << 1039<if(label)><label> := <endif>Match(Input, <token>, FOLLOW_<token>_in_<ruleName><elementIndex>)<if(label)> as I<labelType><endif>;<\n><checkRuleBacktrackFailure()> 1040>> 1041 1042/** ids+=ID */ 1043tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 1044<tokenRef(...)> 1045<listLabel(elem=label,...)> 1046>> 1047 1048listLabel(label,elem) ::= << 1049if (list_<label> = nil) then list_<label> := TList\<IANTLRInterface\>.Create; 1050list_<label>.Add(<elem>);<\n> 1051>> 1052 1053/** match a character */ 1054charRef(char,label) ::= << 1055<if(label)> 1056<label> := Input.LA(1);<\n> 1057<endif> 1058Match(<char>); <checkRuleBacktrackFailure()> 1059>> 1060 1061/** match a character range */ 1062charRangeRef(a,b,label) ::= << 1063<if(label)> 1064<label> := Input.LA(1);<\n> 1065<endif> 1066MatchRange(<a>, <b>); <checkRuleBacktrackFailure()> 1067>> 1068 1069/** For now, sets are interval tests and must be tested inline */ 1070matchSet(s,label,elementIndex,postmatchCode="") ::= << 1071<if(label)> 1072<if(LEXER)> 1073<label> := Input.LA(1);<\n> 1074<else> 1075<label> := Input.LT(1) as I<labelType>;<\n> 1076<endif> 1077<endif> 1078if (<s>) then 1079begin 1080 Input.Consume; 1081 <postmatchCode> 1082 <if(!LEXER)> 1083 State.ErrorRecovery := False;<endif> 1084 <if(backtracking)>State.Failed := False;<endif> 1085end 1086else 1087begin 1088 <ruleBacktrackFailure()> 1089 FException := EMismatchedSetException.Create(nil, Input); 1090 <@mismatchedSetException()> 1091<if(LEXER)> 1092 Recover(FException); 1093 raise FException;<\n> 1094<else> 1095 raise FException; 1096 <! use following code to make it recover inline; remove throw mse; 1097 RecoverFromMismatchedSet(input,mse,FOLLOW_set_in_<ruleName><elementIndex>); 1098 !> 1099<endif> 1100end;<\n> 1101>> 1102 1103matchRuleBlockSet ::= matchSet 1104 1105matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 1106<matchSet(...)> 1107<listLabel(elem=label,...)> 1108>> 1109 1110/** Match a string literal */ 1111lexerStringRef(string,label,elementIndex) ::= << 1112<if(label)> 1113Locals.AsInteger['<label>Start'] := CharIndex; 1114Match(<string>); <checkRuleBacktrackFailure()> 1115<label> := TCommonToken.Create(Input, TToken.INVALID_TOKEN_TYPE, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start'], CharIndex-1); 1116<else> 1117Match(<string>); <checkRuleBacktrackFailure()> 1118<endif> 1119>> 1120 1121wildcard(label,elementIndex) ::= << 1122<if(label)> 1123<label> := Input.LT(1) as I<labelType>;<\n> 1124<endif> 1125MatchAny(input); <checkRuleBacktrackFailure()> 1126>> 1127 1128wildcardAndListLabel(label,elementIndex) ::= << 1129<wildcard(...)> 1130<listLabel(elem=label,...)> 1131>> 1132 1133/** Match . wildcard in lexer */ 1134wildcardChar(label, elementIndex) ::= << 1135<if(label)> 1136<label> := Input.LA(1);<\n> 1137<endif> 1138MatchAny(); <checkRuleBacktrackFailure()> 1139>> 1140 1141wildcardCharListLabel(label, elementIndex) ::= << 1142<wildcardChar(...)> 1143<listLabel(elem=label,...)> 1144>> 1145 1146/** Match a rule reference by invoking it possibly with arguments 1147 * and a return value or values. The 'rule' argument was the 1148 * target rule name, but now is type Rule, whose toString is 1149 * same: the rule name. Now though you can access full rule 1150 * descriptor stuff. 1151 */ 1152ruleRef(rule,label,elementIndex,args,scope) ::= << 1153PushFollow(FOLLOW_<rule.name>_in_<ruleName><elementIndex>); 1154<if(label)> 1155<label> := <if(scope)><scope:delegateName()>.<endif><rule.name>(<args; separator=", ">);<\n> 1156<else> 1157<if(scope)>T<scope.recognizerName>(IANTLRObject(<scope:delegateName()>).Implementor).<endif><rule.name>(<args; separator=", ">);<\n> 1158<endif> 1159State.FollowingStackPointer := State.FollowingStackPointer - 1; 1160<checkRuleBacktrackFailure()> 1161>> 1162 1163/** ids+=r */ 1164ruleRefAndListLabel(rule,label,elementIndex,args,scope) ::= << 1165<ruleRef(...)> 1166<listLabel(elem=label,...)> 1167>> 1168 1169/** A lexer rule reference. 1170 * 1171 * The 'rule' argument was the target rule name, but now 1172 * is type Rule, whose toString is same: the rule name. 1173 * Now though you can access full rule descriptor stuff. 1174 */ 1175lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 1176<if(label)> 1177Locals.AsInteger['<label>Start<elementIndex>'] := CharIndex; 1178<if(scope)><scope:delegateName()>.<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()> 1179<label> := TCommonToken.Create(Input, TToken.INVALID_TOKEN_TYPE, TToken.DEFAULT_CHANNEL, 1180 Locals.AsInteger['<label>Start<elementIndex>'], CharIndex - 1); 1181<else> 1182<if(scope)>(<scope:delegateName()>.Implementor as T<scope.recognizerName>).<endif>m<rule.name>(<args; separator=", ">); <checkRuleBacktrackFailure()> 1183<endif> 1184>> 1185 1186/** i+=INT in lexer */ 1187lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 1188<lexerRuleRef(...)> 1189<listLabel(elem=label,...)> 1190>> 1191 1192/** EOF in the lexer */ 1193lexerMatchEOF(label,elementIndex) ::= << 1194<if(label)> 1195Locals.AsInteger['<label>Start<elementIndex>'] := CharIndex; 1196Match(EOF); <checkRuleBacktrackFailure()> 1197Locals['<label>'] := TCommonToken.Create(Input, EOF, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start<elementIndex>'], CharIndex-1); 1198<else> 1199Match(EOF); <checkRuleBacktrackFailure()> 1200<endif> 1201>> 1202 1203/** match ^(root children) in tree parser */ 1204tree(root, actionsAfterRoot, children, nullableChildList, 1205 enclosingTreeLevel, treeLevel) ::= << 1206<root:element()> 1207<actionsAfterRoot:element()> 1208<if(nullableChildList)> 1209if (Input.LA(1) = TToken.DOWN) then 1210begin 1211 Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()> 1212 <children:element()> 1213 Match(Input, TToken.UP, nil); <checkRuleBacktrackFailure()> 1214end; 1215<else> 1216Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()> 1217<children:element()> 1218Match(Input, TToken.UP, nil);<\n><checkRuleBacktrackFailure()> 1219<endif> 1220>> 1221 1222/** Every predicate is used as a validating predicate (even when it is 1223 * also hoisted into a prediction expression). 1224 */ 1225validateSemanticPredicate(pred,description) ::= << 1226if (not (<evalPredicate(...)>)) then 1227begin 1228 <ruleBacktrackFailure()> 1229 raise EFailedPredicateException.Create(Input, '<ruleName>', '<description>'); 1230end;<\n> 1231>> 1232 1233// F i x e d D F A (if-then-else) 1234 1235dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1236FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);<\n> 1237<edges; separator="\nelse "> 1238else 1239begin 1240<if(eotPredictsAlt)> 1241 Alt[<decisionNumber>] := <eotPredictsAlt>;<\n> 1242<else> 1243 <ruleBacktrackFailure()> 1244 raise ENoViableAltException.Create('<description>', <decisionNumber>, <stateNumber>, Input);<\n> 1245<endif> 1246end; 1247>> 1248 1249/** Same as a normal DFA state except that we don't examine lookahead 1250 * for the bypass alternative. It delays error detection but this 1251 * is faster, smaller, and more what people expect. For (X)? people 1252 * expect "if ( LA(1)==X ) match(X);" and that's it. 1253 */ 1254dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1255FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);<\n> 1256<edges; separator="\nelse ">; 1257>> 1258 1259/** A DFA state that is actually the loopback decision of a closure 1260 * loop. If end-of-token (EOT) predicts any of the targets then it 1261 * should act like a default clause (i.e., no error can be generated). 1262 * This is used only in the lexer so that for ('a')* on the end of a rule 1263 * anything other than 'a' predicts exiting. 1264 */ 1265dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1266FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>); 1267<edges; separator="\nelse ">;<\n> 1268<if(eotPredictsAlt)> 1269<if(!edges)> 1270Alt[<decisionNumber>] := <eotPredictsAlt>; <! if no edges, don't gen ELSE !> 1271<else> 1272else 1273begin 1274 Alt[<decisionNumber>] := <eotPredictsAlt>; 1275end;<\n> 1276<endif> 1277<endif> 1278>> 1279 1280/** An accept state indicates a unique alternative has been predicted */ 1281dfaAcceptState(alt) ::= "Alt[<decisionNumber>] := <alt>;" 1282 1283/** A simple edge with an expression. If the expression is satisfied, 1284 * enter to the target state. To handle gated productions, we may 1285 * have to evaluate some predicates for this edge. 1286 */ 1287dfaEdge(labelExpr, targetState, predicates) ::= << 1288if ((<labelExpr>)<if(predicates)> and (<predicates>)<endif>) then 1289begin 1290 <targetState> 1291end <! no ; here !> 1292>> 1293 1294// F i x e d D F A (switch case) 1295 1296/** A DFA state where a SWITCH may be generated. The code generator 1297 * decides if this is possible: CodeGenerator.canGenerateSwitch(). 1298 */ 1299dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1300case Input.LA(<k>) of 1301 <edges; separator="\n"> 1302else 1303 begin 1304<if(eotPredictsAlt)> 1305 Alt[<decisionNumber>] := <eotPredictsAlt>; 1306<else> 1307 <ruleBacktrackFailure()> 1308 <@noViableAltException()> 1309 raise ENoViableAltException.Create('<description>', <decisionNumber>, <stateNumber>, Input);<\n> 1310<endif> 1311 end; 1312end;<\n> 1313>> 1314 1315dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1316case Input.LA(<k>) of 1317 <edges; separator="\n"> 1318end;<\n> 1319>> 1320 1321dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1322case Input.LA(<k>) of 1323 <edges; separator="\n"><\n> 1324<if(eotPredictsAlt)> 1325else 1326 Alt[<decisionNumber>] := <eotPredictsAlt>;<\n> 1327<endif> 1328end;<\n> 1329>> 1330 1331dfaEdgeSwitch(labels, targetState) ::= << 1332<labels:{<it>}; separator=",\n">: 1333 begin 1334 <targetState> 1335 end; 1336>> 1337 1338// C y c l i c D F A 1339 1340/** The code to initiate execution of a cyclic DFA; this is used 1341 * in the rule to predict an alt just like the fixed DFA case. 1342 * The <name> attribute is inherited via the parser, lexer, ... 1343 */ 1344dfaDecision(decisionNumber,description) ::= << 1345Alt[<decisionNumber>] := FDFA<decisionNumber>.Predict(Input); 1346>> 1347 1348/* Dump DFA tables. 1349 */ 1350cyclicDFADeclaration(dfa) ::= << 1351strict protected 1352 type 1353 TDFA<dfa.decisionNumber> = class(TDFA) 1354 protected 1355 { IDFA } 1356 function Description: String; override; 1357 public 1358 constructor Create(const ARecognizer: IBaseRecognizer); 1359 end; 1360 var 1361 FDFA<dfa.decisionNumber>: IDFA; 1362<if(dfa.specialStateSTs)> 1363strict protected 1364 function DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer; 1365 const AInput: IIntStream): Integer;<endif> 1366>> 1367 1368cyclicDFA(dfa) ::= << 1369{ T<grammar.recognizerName>.TDFA<dfa.decisionNumber> } 1370 1371constructor T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Create(const ARecognizer: IBaseRecognizer); 1372const 1373 DFA<dfa.decisionNumber>_EOT = '<dfa.javaCompressedEOT; wrap="'+\n '">'; 1374 DFA<dfa.decisionNumber>_EOF = '<dfa.javaCompressedEOF; wrap="'+\n '">'; 1375 DFA<dfa.decisionNumber>_MIN = '<dfa.javaCompressedMin; wrap="'+\n '">'; 1376 DFA<dfa.decisionNumber>_MAX = '<dfa.javaCompressedMax; wrap="'+\n '">'; 1377 DFA<dfa.decisionNumber>_ACCEPT = '<dfa.javaCompressedAccept; wrap="'+\n '">'; 1378 DFA<dfa.decisionNumber>_SPECIAL = '<dfa.javaCompressedSpecial; wrap="'+\n '">'; 1379 DFA<dfa.decisionNumber>_TRANSITION: array [0..<length(dfa.javaCompressedTransition)>-1] of String = ( 1380 <dfa.javaCompressedTransition:{s|'<s; wrap="'+\n'">'}; separator=",\n">); 1381begin 1382 inherited Create; 1383 Recognizer := ARecognizer; 1384 DecisionNumber := <dfa.decisionNumber>; 1385 EOT := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_EOT); 1386 EOF := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_EOF); 1387 Min := TDFA.UnpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_MIN); 1388 Max := TDFA.UnpackEncodedStringToUnsignedChars(DFA<dfa.decisionNumber>_MAX); 1389 Accept := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_ACCEPT); 1390 Special := TDFA.UnpackEncodedString(DFA<dfa.decisionNumber>_SPECIAL); 1391 Transition := TDFA.UnpackEncodedStringArray(DFA<dfa.decisionNumber>_TRANSITION); 1392end; 1393 1394function T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Description: String; 1395begin 1396 Result := '<dfa.description>'; 1397end;<\n> 1398<if(dfa.specialStateSTs)> 1399function T<grammar.recognizerName>.DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer; 1400 const AInput: IIntStream): Integer; 1401var 1402 Locals: TLocalStorage; 1403 <if(LEXER)> 1404 Input: IIntStream; 1405 <endif> 1406 <if(PARSER)> 1407 Input: ITokenStream; 1408 <endif> 1409 <if(TREE_PARSER)> 1410 Input: ITreeNodeStream; 1411 <endif> 1412 _S: Integer; 1413 NVAE: ENoViableAltException; 1414begin 1415 Result := -1; 1416 Locals.Initialize; 1417 try 1418 <if(LEXER)> 1419 Input := AInput; 1420 <endif> 1421 <if(PARSER)> 1422 Input := AInput as ITokenStream; 1423 <endif> 1424 <if(TREE_PARSER)> 1425 Input := AInput as ITreeNodeStream; 1426 <endif> 1427 _S := S; 1428 case S of 1429 <dfa.specialStateSTs:{state | <i0>: begin<! compressed special state numbers 0..n-1 !> 1430 <state> <\n> end;}; separator="\n"> 1431 end; 1432<if(backtracking)> 1433 if (State.Backtracking > 0) then 1434 begin 1435 State.Failed := True; 1436 Exit(-1); 1437 end;<\n> 1438<endif> 1439 NVAE := ENoViableAltException.Create(DFA.Description, <dfa.decisionNumber>, _S, Input); 1440 DFA.Error(NVAE); 1441 raise NVAE; 1442 finally 1443 Locals.Finalize; 1444 end; 1445end;<\n> 1446<endif> 1447>> 1448 1449/** A state in a cyclic DFA; it's a special state and part of a big switch on 1450 * state. 1451 */ 1452cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 1453FLA[<decisionNumber>,<stateNumber>] := Input.LA(1);<\n> 1454<if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 1455Locals.AsInteger['index<decisionNumber>_<stateNumber>'] := Input.Index; 1456Input.Rewind;<\n> 1457<endif> 1458S := -1; 1459<edges; separator="\nelse ">; 1460<if(semPredState)> <! return input cursor to state before we rewound !> 1461Input.Seek(Locals.AsInteger['index<decisionNumber>_<stateNumber>']);<\n> 1462<endif> 1463if (S >= 0) then 1464 Exit(S); 1465>> 1466 1467/** Just like a fixed DFA edge, test the lookahead and indicate what 1468 * state to jump to next if successful. 1469 */ 1470cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1471if ((<labelExpr>)<if(predicates)> and (<predicates>)<endif>) then 1472 S := <targetStateNumber> 1473>> 1474 1475/** An edge pointing at end-of-token; essentially matches any char; 1476 * always jump to the target. 1477 */ 1478eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1479S := <targetStateNumber>;<\n> 1480>> 1481 1482 1483// D F A E X P R E S S I O N S 1484 1485andPredicates(left,right) ::= "((<left>) and (<right>))" 1486 1487orPredicates(operands) ::= "((<first(operands)>)<rest(operands):{o | or (<o>)}>)" 1488 1489notPredicate(pred) ::= "!(<evalPredicate(...)>)" 1490 1491evalPredicate(pred,description) ::= "(<pred>)" 1492 1493evalSynPredicate(pred,description) ::= "<pred>()" 1494 1495lookaheadTest(atom,k,atomAsInt) ::= "FLA[<decisionNumber>,<stateNumber>] = <atomAsInt>" 1496 1497/** Sometimes a lookahead test cannot assume that LA(k) is in a temp variable 1498 * somewhere. Must ask for the lookahead directly. 1499 */ 1500isolatedLookaheadTest(atom,k,atomAsInt) ::= "Input.LA(<k>) = <atomAsInt>" 1501 1502lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= << 1503((FLA[<decisionNumber>,<stateNumber>] \>= <lowerAsInt>) and (FLA[<decisionNumber>,<stateNumber>] \<= <upperAsInt>)) 1504>> 1505 1506isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(Input.LA(<k>) \>= <lowerAsInt>) and (Input.LA(<k>) \<= <upperAsInt>)" 1507 1508setTest(ranges) ::= "<ranges; separator=\") or (\">" 1509 1510// A T T R I B U T E S 1511 1512globalAttributeScope(scope) ::= << 1513<scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n> 1514<endif> 1515>> 1516 1517globalAttributeScopeDeclaration(scope) ::= << 1518<if(scope.attributes)> 1519strict protected 1520 type 1521 I<scope.name>Scope = interface(IANTLRObject) 1522 end; 1523 T<scope.name>Scope = class(TANTLRObject, I<scope.name>Scope) 1524 protected 1525 <scope.attributes:{<it.name>: <it.type>;}; separator="\n"> 1526 end; 1527strict protected 1528 <scope.name>Stack: IStackList\<I<scope.name>Scope\>; 1529<endif> 1530>> 1531 1532ruleAttributeScopeDeclaration(scope) ::= << 1533<if(scope.attributes)> 1534strict protected 1535 type 1536 I<scope.name>Scope = interface(IANTLRObject) 1537 end; 1538 T<scope.name>Scope = class(TANTLRObject, I<scope.name>Scope) 1539 protected 1540 <scope.attributes:{<it.name>: <it.type>;}; separator="\n"> 1541 end; 1542strict protected 1543 <scope.name>Stack: IStackList\<I<scope.name>Scope\>; 1544<endif> 1545>> 1546 1547ruleAttributeScope(scope) ::= << 1548<! protected Stack <scope.name>Stack = new Stack();<\n> !> 1549>> 1550 1551ruleAttributeScopeInit(scope) ::= << 1552<if(scope)> 1553<scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n> 1554<endif> 1555>> 1556 1557returnStructName() ::= "<it.name>_return" 1558 1559returnType() ::= << 1560<if(ruleDescriptor.hasMultipleReturnValues)> 1561<ruleDescriptor:returnStructName()> 1562<! I<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope !> 1563<else> 1564<if(ruleDescriptor.hasSingleReturnValue)> 1565<ruleDescriptor.singleValueReturnType> 1566<else> 1567<! Pointer/void !> 1568<endif> 1569<endif> 1570>> 1571 1572/** Generate the C# type associated with a single or multiple return 1573 * values. 1574 */ 1575ruleLabelType(referencedRule) ::= << 1576<if(referencedRule.hasMultipleReturnValues)> 1577I<referencedRule.name>_return 1578<else> 1579<if(referencedRule.hasSingleReturnValue)> 1580<referencedRule.singleValueReturnType> 1581<else> 1582void 1583<endif> 1584<endif> 1585>> 1586 1587delegateName() ::= << 1588<if(it.label)><it.label><else>g<it.name><endif> 1589>> 1590 1591/** Using a type to init value map, try to init a type; if not in table 1592 * must be an object, default value is "null". 1593 */ 1594initValue(typeName) ::= << 1595<csharpTypeInitMap.(typeName)> 1596>> 1597 1598/** Define a rule label including default value */ 1599ruleLabelDef(label) ::= << 1600<label.label.text> := <initValue(typeName=ruleLabelType(referencedRule=label.referencedRule))>;<\n> 1601>> 1602 1603ruleLabelDefVar(label) ::= << 1604<label.label.text>: <ruleLabelType(referencedRule=label.referencedRule)>; 1605>> 1606 1607/** Define a return struct for a rule if the code needs to access its 1608 * start/stop tokens, tree stuff, attributes, ... Leave a hole for 1609 * subgroups to stick in members. 1610 */ 1611returnScope(scope) ::= << 1612<if(ruleDescriptor.hasMultipleReturnValues)> 1613{ T<ruleDescriptor:returnStructName()> } 1614 1615<scope.attributes:{public <it.decl>;}; separator="\n"> 1616<@ruleReturnMembers()> 1617<endif> 1618>> 1619 1620returnScopeDeclaration(scope) ::= << 1621<if(ruleDescriptor.hasMultipleReturnValues)> 1622public 1623 type 1624 T<ruleDescriptor:returnStructName()> = class(T<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope, I<ruleDescriptor:returnStructName()>) 1625 <scope.attributes:{public <it.decl>;}; separator="\n"> 1626 <@ruleReturnMembers()> 1627 end; 1628<endif> 1629>> 1630 1631parameterScope(scope) ::= << 1632<scope.attributes:{<it.decl>}; separator=", "> 1633>> 1634 1635parameterAttributeRef(attr) ::= "<attr.name>" 1636parameterSetAttributeRef(attr,expr) ::= "<attr.name> := <expr>;" 1637 1638scopeAttributeRef(scope,attr,index,negIndex) ::= << 1639<if(negIndex)> 1640(<scope>Stack[<scope>Stack.Count-<negIndex>-1] as T<scope>Scope).<attr.name> 1641<else> 1642<if(index)> 1643(<scope>Stack[<index>] as T<scope>Scope).<attr.name> 1644((<scope>_scope)<scope>_stack[<index>]).<attr.name> 1645<else> 1646(<scope>Stack.Peek.Implementor as T<scope>Scope).<attr.name> 1647<endif> 1648<endif> 1649>> 1650 1651scopeSetAttributeRef(scope,attr,expr,index,negIndex) ::= << 1652<if(negIndex)> 1653(<scope>Stack[<scope>Stack.Count-<negIndex>-1] as T<scope>Scope).<attr.name> := <expr>;<\n> 1654<else> 1655<if(index)> 1656(<scope>Stack[<index>] as T<scope>Scope).<attr.name> := <expr>;<\n> 1657<else> 1658(<scope>Stack.Peek.Implementor as T<scope>Scope).<attr.name> := <expr>;<\n> 1659<endif> 1660<endif> 1661>> 1662 1663/** $x is either global scope or x is rule with dynamic scope; refers 1664 * to stack itself not top of stack. This is useful for predicates 1665 * like {$function.size()>0 && $function::name.equals("foo")}? 1666 */ 1667isolatedDynamicScopeRef(scope) ::= "<scope>Stack" 1668 1669/** reference an attribute of rule; might only have single return value */ 1670ruleLabelRef(referencedRule,scope,attr) ::= << 1671<if(referencedRule.hasMultipleReturnValues)> 1672(IfThen(Assigned(<scope>),Def(<scope>).<attr.name>,<initValue(attr.type)>)) 1673<else> 1674<scope> 1675<endif> 1676>> 1677 1678returnAttributeRef(ruleDescriptor,attr) ::= << 1679<if(ruleDescriptor.hasMultipleReturnValues)> 1680RetVal.<attr.name> 1681<else> 1682<attr.name> 1683<endif> 1684>> 1685 1686returnSetAttributeRef(ruleDescriptor,attr,expr) ::= << 1687<if(ruleDescriptor.hasMultipleReturnValues)> 1688RetVal.<attr.name> := <expr>; 1689<else> 1690<attr.name> := <expr>; 1691<endif> 1692>> 1693 1694/** How to translate $tokenLabel */ 1695tokenLabelRef(label) ::= "<label>" 1696 1697/** ids+=ID {$ids} or e+=expr {$e} */ 1698listLabelRef(label) ::= "list_<label>" 1699 1700 1701// not sure the next are the right approach 1702 1703tokenLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)" 1704tokenLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)" 1705tokenLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)" 1706tokenLabelPropertyRef_pos(scope,attr) ::= "(Def(<scope>).CharPositionInLine)" 1707tokenLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)" 1708tokenLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)" 1709tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1710tokenLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))" 1711 1712ruleLabelPropertyRef_start(scope,attr) ::= "(IfThen(Assigned(<scope>), Def(<scope>).Start, nil) as I<labelType>)" 1713ruleLabelPropertyRef_stop(scope,attr) ::= "(Def(<scope>).Stop as I<labelType>)" 1714ruleLabelPropertyRef_tree(scope,attr) ::= "(Def(Def(<scope>).Tree as I<ASTLabelType>))" 1715ruleLabelPropertyRef_text(scope,attr) ::= << 1716<if(TREE_PARSER)> 1717IfThen(Assigned(<scope>), Input.TokenStream.ToString( 1718 Input.TreeAdaptor.GetTokenStartIndex(Def(<scope>).Start), 1719 Input.TreeAdaptor.GetTokenStopIndex(Def(<scope>).Start)), '') 1720<else> 1721IfThen(Assigned(<scope>), Input.ToString( 1722 (Def(<scope>).Start) as IToken,(Def(<scope>).Stop) as IToken), '') 1723<endif> 1724>> 1725ruleLabelPropertyRef_st(scope,attr) ::= "((<scope> != null) ? <scope>.ST : null)" 1726 1727/** Isolated $RULE ref ok in lexer as it's a Token */ 1728lexerRuleLabel(label) ::= "<label>" 1729 1730lexerRuleLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)" 1731lexerRuleLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)" 1732lexerRuleLabelPropertyRef_pos(scope,attr) ::= "(IfThen(Assigned(<scope>),Def(<scope>).CharPositionInLine,-1))" 1733lexerRuleLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)" 1734lexerRuleLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)" 1735lexerRuleLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)" 1736lexerRuleLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))" 1737 1738// Somebody may ref $template or $tree or $stop within a rule: 1739rulePropertyRef_start(scope,attr) ::= "(RetVal.Start as I<labelType>)" 1740rulePropertyRef_stop(scope,attr) ::= "(RetVal.Stop as I<labelType>)" 1741rulePropertyRef_tree(scope,attr) ::= "(RetVal.Tree as I<ASTLabelType>)" 1742rulePropertyRef_text(scope,attr) ::= << 1743<if(TREE_PARSER)> 1744Input.TokenStream.ToString( 1745 Input.TreeAdaptor.GetTokenStartIndex(RetVal.Start), 1746 Input.TreeAdaptor.GetTokenStopIndex(RetVal.Start)) 1747<else> 1748Input.ToString(RetVal.Start as IToken,Input.LT(-1)) 1749<endif> 1750>> 1751rulePropertyRef_st(scope,attr) ::= "RetVal.ST" 1752 1753lexerRulePropertyRef_text(scope,attr) ::= "Text" 1754lexerRulePropertyRef_type(scope,attr) ::= "TokenType" 1755lexerRulePropertyRef_line(scope,attr) ::= "State.TokenStartLine" 1756lexerRulePropertyRef_pos(scope,attr) ::= "State.TokenStartCharPositionInLine" 1757lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1758lexerRulePropertyRef_channel(scope,attr) ::= "Channel" 1759lexerRulePropertyRef_start(scope,attr) ::= "State.TokenStartCharIndex" 1760lexerRulePropertyRef_stop(scope,attr) ::= "(CharIndex-1)" 1761lexerRulePropertyRef_int(scope,attr) ::= "StrToInt(<scope>.Text)" 1762 1763// setting $st and $tree is allowed in local rule. everything else 1764// is flagged as error 1765ruleSetPropertyRef_tree(scope,attr,expr) ::= "RetVal.Tree := <expr>;" 1766ruleSetPropertyRef_st(scope,attr,expr) ::= "RetVal.ST := <expr>;" 1767 1768 1769/** How to execute an action (only when not backtracking) */ 1770execAction(action) ::= << 1771<if(backtracking)> 1772<if(actions.(actionScope).synpredgate)> 1773if (<actions.(actionScope).synpredgate>) then 1774begin 1775 <action> 1776end; 1777<else> 1778if (State.Backtracking = 0) then 1779begin 1780 <action> 1781end;<\n> 1782<endif> 1783<else> 1784<action> 1785<endif> 1786>> 1787 1788 1789/** How to always execute an action even when backtracking */ 1790execForcedAction(action) ::= "<action>" 1791 1792// M I S C (properties, etc...) 1793 1794bitset(name, words64) ::= << 1795<name> := TBitSet.Create([<words64:{<it>};separator=",">]);<\n> 1796>> 1797 1798bitsetDecl(name) ::= << 1799<name>: IBitSet;<\n> 1800>> 1801 1802codeFileExtension() ::= ".pas" 1803 1804true() ::= "True" 1805false() ::= "False" 1806