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 */ 30 group Delphi; 31 32 csharpTypeInitMap ::= [ 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 */ 81 outputFile(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 << 89 unit <name>; 90 91 {$HINTS OFF} 92 93 // $ANTLR <ANTLRVersion> <fileName> <generatedTimestamp> 94 95 <actions.(actionScope).header> 96 97 interface 98 99 <@imports> 100 uses<\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 */ 117 lexer(grammar, name, tokens, scopes, rules, numRules, labelType="Token", 118 filterMode, superClass="Lexer") ::= << 119 type 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 167 implementation 168 169 uses 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 179 constructor T<grammar.recognizerName>.Create; 180 begin 181 InitializeCyclicDFAs; 182 end; 183 184 constructor T<grammar.recognizerName>.Create(const AInput: ICharStream<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 185 begin 186 Create(AInput, nil<grammar.delegators:{g|, A<g:delegateName()>}>); 187 end; 188 189 constructor T<grammar.recognizerName>.Create(const AInput: ICharStream; const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 190 begin 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> 204 end; 205 <actions.(actionScope).memberImplementations> 206 function T<grammar.recognizerName>.GetGrammarFileName: String; 207 begin 208 Result := '<fileName>'; 209 end; 210 211 <if(filterMode)> 212 <filteringNextToken()> 213 <endif> 214 215 <rules; separator="\n\n"> 216 <synpreds:{p | <lexerSynpred(p)>}> 217 218 procedure T<grammar.recognizerName>.InitializeCyclicDFAs; 219 begin 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"> 222 end; 223 224 <cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 225 end.>> 226 227 lexerRuleDeclaration(rule) ::= << 228 procedure 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 */ 238 filteringNextToken() ::= << 239 function T<grammar.recognizerName>.NextToken: IToken; 240 var 241 M: Integer; 242 begin 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; 283 end; 284 285 function T<grammar.recognizerName>.AlreadyParsedRule(const Input: IIntStream; 286 const RuleIndex: Integer): Boolean; 287 begin 288 if (State.Backtracking > 1) then 289 Result := inherited AlreadyParsedRule(Input, RuleIndex) 290 else 291 Result := False; 292 end; 293 294 procedure T<grammar.recognizerName>.Memoize(const Input: IIntStream; const RuleIndex, 295 RuleStartIndex: Integer); 296 begin 297 if (State.Backtracking > 1) then 298 inherited Memoize(Input, RuleIndex, RuleStartIndex); 299 end; 300 301 >> 302 303 filteringActionGate() ::= "(State.Backtracking = 1)" 304 305 /** How to generate a parser */ 306 genericParser(grammar, name, scopes, tokens, tokenNames, rules, numRules, 307 bitsets, inputStreamType, superClass, filterMode, 308 ASTLabelType="ANTLRInterface", labelType, members, rewriteElementType) ::= << 309 type 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 373 implementation 374 375 uses 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 385 constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType><grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 386 begin 387 Create(AInput, TRecognizerSharedState.Create<grammar.delegators:{g|, A<g:delegateName()>}>); 388 end; 389 390 constructor T<grammar.recognizerName>.Create(const AInput: <inputStreamType>; 391 const AState: IRecognizerSharedState<grammar.delegators:{g|; const A<g:delegateName()>: IBaseRecognizer{<g.recognizerName>}}>); 392 begin 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> 403 end; 404 <actions.(actionScope).memberImplementations> 405 406 <grammar.delegatedRules:{ruleDescriptor| <delegatedRuleImplementation(ruleDescriptor)>}; separator="\n"> 407 procedure T<grammar.recognizerName>.InitializeCyclicDFAs; 408 begin 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"> 411 end; 412 413 <if(bitsets)> 414 class procedure T<grammar.recognizerName>.InitializeBitsets; 415 begin 416 <bitsets:bitset(name={FOLLOW_<it.name>_in_<it.inName><it.tokenIndex>}, words64=it.bits)> 417 end; 418 <endif> 419 420 <@membersImplementation> 421 <@end> 422 423 function T<grammar.recognizerName>.GetTokenNames: TStringArray; 424 var 425 I: Integer; 426 begin 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]; 430 end; 431 432 function T<grammar.recognizerName>.GetGrammarFileName: String; 433 begin 434 Result := '<fileName>'; 435 end; 436 437 <rules; separator="\n\n"> 438 <synpreds:{p | <synpred(p)>}> 439 440 <cyclicDFAs:cyclicDFA()> <! dump tables for all DFA !> 441 <if(bitsets)> 442 initialization 443 T<grammar.recognizerName>.InitializeBitsets;<\n> 444 <endif> 445 end.>> 446 447 delegatedRuleDeclaration(ruleDescriptor) ::= << 448 <if(ruleDescriptor.hasMultipleReturnValues)> 449 function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n> 450 <else> 451 <if(ruleDescriptor.hasSingleReturnValue)> 452 function <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n> 453 <else> 454 procedure <ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n> 455 <endif> 456 <endif> 457 >> 458 459 delegatedRuleImplementation(ruleDescriptor) ::= << 460 <if(ruleDescriptor.hasMultipleReturnValues)> 461 function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>;<\n> 462 <else> 463 <if(ruleDescriptor.hasSingleReturnValue)> 464 function T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>;<\n> 465 <else> 466 procedure T<grammar.recognizerName>.<ruleDescriptor.name>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>);<\n> 467 <endif> 468 <endif> 469 begin 470 <if(ruleDescriptor.hasReturnValue)>Result :=<endif> T<ruleDescriptor.grammar.recognizerName>(<ruleDescriptor.grammar:delegateName()>.Implementor).<ruleDescriptor.name>(<ruleDescriptor.parameterScope.attributes:{a|<a.name>}; separator=", ">); 471 end; 472 473 >> 474 475 parserCtorBody() ::= << 476 InitializeCyclicDFAs; 477 <if(memoize)> 478 <if(grammar.grammarIsRoot)> 479 State.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 485 parser(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 */ 492 treeParser(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 */ 503 synpredRule(ruleName, ruleDescriptor, block, description, nakedBlock) ::= 504 << 505 // $ANTLR start "<ruleName>" 506 procedure T<grammar.recognizerName>.<ruleName>_fragment(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 507 var 508 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 509 <ruleLabelDefVars()> 510 begin 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> 522 end; 523 // $ANTLR end "<ruleName>" 524 >> 525 526 synpredDecls(name) ::= << 527 SynPredPointer <name>;<\n> 528 >> 529 530 synpred(name) ::= << 531 532 function T<grammar.recognizerName>.<name>: Boolean; 533 var 534 Start: Integer; 535 Success: Boolean; 536 begin 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; 552 end;<\n> 553 >> 554 555 lexerSynpred(name) ::= << 556 <synpred(name)> 557 >> 558 559 lexerSynpredDeclaration(name) ::= << 560 function <name>: Boolean; 561 procedure <name>_fragment; 562 >> 563 564 synpredDeclaration(name) ::= << 565 function <name>: Boolean; 566 procedure <name>_fragment; 567 >> 568 569 ruleMemoization(name) ::= << 570 <if(memoize)> 571 if ((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 */ 577 checkRuleBacktrackFailure() ::= << 578 <if(backtracking)><\n>if (State.Failed) then Exit(<ruleReturnValue()>);<\n><endif> 579 >> 580 581 /** This rule has failed, exit indicating failure during backtrack */ 582 ruleBacktrackFailure() ::= << 583 <if(backtracking)>if (State.Backtracking > 0) then 584 begin 585 State.Failed := True; 586 Exit(<ruleReturnValue()>); 587 end;<endif> 588 >> 589 590 genericParserRuleDeclaration(rule, ruleDescriptor) ::= << 591 <if(ruleDescriptor.isSynPred)> 592 <else> 593 <ruleAttributeScopeDeclaration(scope=ruleDescriptor.ruleScope)> 594 <returnScopeDeclaration(scope=ruleDescriptor.returnScope)> 595 public 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 608 genericParserRuleInterface(rule, ruleDescriptor) ::= << 609 <if(ruleDescriptor.isSynPred)> 610 <else> 611 <if(ruleDescriptor.hasMultipleReturnValues)> 612 function <rule.ruleName>: I<returnType()>;<\n> 613 <else> 614 <if(ruleDescriptor.hasSingleReturnValue)> 615 function <rule.ruleName>: <returnType()>;<\n> 616 <else> 617 procedure <rule.ruleName>;<\n> 618 <endif> 619 <endif> 620 <endif> 621 >> 622 623 genericParserRuleReturnType(rule, ruleDescriptor) ::= << 624 <if(ruleDescriptor.hasMultipleReturnValues)> 625 <if(ruleDescriptor.isSynPred)> 626 <else> 627 I<returnType()> = interface(I<if(TREE_PARSER)>Tree<else>Parser<endif>RuleReturnScope) 628 end;<\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 */ 636 rule(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)> 643 function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): I<returnType()>; 644 <else> 645 <if(ruleDescriptor.hasSingleReturnValue)> 646 function T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>): <returnType()>; 647 <else> 648 procedure T<grammar.recognizerName>.<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 649 <endif> 650 <endif> 651 652 var 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()> 666 begin 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()>); 710 end; 711 // $ANTLR end "<ruleName>" 712 >> 713 714 catch(decl,action) ::= << 715 catch (<e.decl>) 716 { 717 <e.action> 718 } 719 >> 720 721 ruleDeclarations() ::= << 722 <if(ruleDescriptor.hasMultipleReturnValues)> 723 RetVal := T<returnType()>.Create; 724 RetVal.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 735 ruleDeclarationVars() ::= << 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 747 ruleScopeSetUp() ::= << 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 752 ruleScopeCleanUp() ::= << 753 <ruleDescriptor.useScopes:{<it>Stack.Pop();}; separator="\n"> 754 <ruleDescriptor.ruleScope:{<it.name>Stack.Pop;}; separator="\n"> 755 >> 756 757 ruleLabelDefs() ::= << 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 764 ruleLabelDefVars() ::= << 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 771 lexerRuleLabelDefs() ::= << 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 785 lexerRuleLabelDefDeclarations() ::= << 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 799 ruleReturnValue() ::= << 800 <if(!ruleDescriptor.isSynPred)> 801 <if(ruleDescriptor.hasReturnValue)> 802 <if(ruleDescriptor.hasSingleReturnValue)> 803 <ruleDescriptor.singleValueReturnName> 804 <else> 805 RetVal 806 <endif> 807 <else> 808 <! nil !> 809 <endif> 810 <endif> 811 >> 812 813 ruleCleanUp() ::= << 814 <if(ruleDescriptor.hasMultipleReturnValues)> 815 <if(!TREE_PARSER)> 816 RetVal.Stop := Input.LT(-1); 817 <endif> 818 <endif> 819 >> 820 821 memoize() ::= << 822 <if(memoize)> 823 <if(backtracking)> 824 if (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 */ 833 lexerRule(ruleName,nakedBlock,ruleDescriptor,block,memoize) ::= << 834 // $ANTLR start "<ruleName>" 835 <ruleDescriptor.parameterScope> 836 procedure T<grammar.recognizerName>.m<ruleName>(<ruleDescriptor.parameterScope:parameterScope(scope=it)>); 837 var 838 <ruleDescriptor.actions.vars> 839 Locals: TLocalStorage; 840 TokenType, Channel: Integer; 841 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 842 <lexerRuleLabelDefDeclarations()> 843 begin 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; 876 end; 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 */ 883 tokensRule(ruleName,nakedBlock,args,block,ruleDescriptor) ::= << 884 procedure T<grammar.recognizerName>.mTokens; 885 var 886 Alt: array [0..<grammar.numberOfDecisions>] of Integer; 887 begin 888 <block> 889 end; 890 891 procedure T<grammar.recognizerName>.DoTokens; 892 begin 893 mTokens; 894 end; 895 >> 896 897 // S U B R U L E S 898 899 /** A (...) subrule with multiple alternatives */ 900 block(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 901 (* <fileName>:<description> *) 902 Alt[<decisionNumber>] := <maxAlt>; 903 <decls> 904 <@predecision()> 905 <decision> 906 <@postdecision()> 907 <@prebranch()> 908 case Alt[<decisionNumber>] of 909 <alts:altSwitchCase()> 910 end; 911 <@postbranch()> 912 >> 913 914 /** A rule block with multiple alternatives */ 915 ruleBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 916 (* <fileName>:<description> *) 917 Alt[<decisionNumber>] := <maxAlt>; 918 <decls> 919 <@predecision()> 920 <decision> 921 <@postdecision()> 922 case Alt[<decisionNumber>] of 923 <alts:altSwitchCase()> 924 end; 925 >> 926 927 ruleBlockSingleAlt(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 */ 936 blockSingleAlt(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 */ 945 positiveClosureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 946 (* <fileName>:<description> *) 947 FCnt[<decisionNumber>] := 0; 948 <decls> 949 <@preloop()> 950 while (True) do 951 begin 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>]); 968 end; 969 <@postloop()> 970 >> 971 972 positiveClosureBlockSingleAlt ::= positiveClosureBlock 973 974 /** A (..)* block with 1 or more alternatives */ 975 closureBlock(alts,decls,decision,enclosingBlockLevel,blockLevel,decisionNumber,maxK,maxAlt,description) ::= << 976 (* <fileName>:<description> *) 977 <decls> 978 <@preloop()> 979 while (True) do 980 begin 981 Alt[<decisionNumber>] := <maxAlt>; 982 <@predecision()> 983 <decision> 984 <@postdecision()> 985 case Alt[<decisionNumber>] of 986 <alts:altSwitchCase()> 987 else 988 Break; 989 end; 990 end; 991 <@postloop()> 992 >> 993 994 closureBlockSingleAlt ::= 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 */ 999 optionalBlock ::= block 1000 1001 optionalBlockSingleAlt ::= 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 */ 1007 altSwitchCase() ::= << 1008 <i>: 1009 <@prealt()> 1010 <it><\n> 1011 >> 1012 1013 /** An alternative is just a list of elements; at outermost level */ 1014 alt(elements,altNum,description,autoAST,outerAlt,treeLevel,rew) ::= << 1015 (* <fileName>:<description> *) 1016 begin 1017 <@declarations()> 1018 <elements:element()> 1019 <rew> 1020 <@cleanup()> 1021 end; 1022 >> 1023 1024 /** What to emit when there is no rewrite. For auto build 1025 * mode, does nothing. 1026 */ 1027 noRewrite(rewriteBlockLevel, treeLevel) ::= "" 1028 1029 // E L E M E N T S 1030 1031 /** Dump the elements one per line */ 1032 element() ::= << 1033 <@prematch()> 1034 <it.el> 1035 >> 1036 1037 /** match a token optionally with a label in front */ 1038 tokenRef(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 */ 1043 tokenRefAndListLabel(token,label,elementIndex,terminalOptions) ::= << 1044 <tokenRef(...)> 1045 <listLabel(elem=label,...)> 1046 >> 1047 1048 listLabel(label,elem) ::= << 1049 if (list_<label> = nil) then list_<label> := TList\<IANTLRInterface\>.Create; 1050 list_<label>.Add(<elem>);<\n> 1051 >> 1052 1053 /** match a character */ 1054 charRef(char,label) ::= << 1055 <if(label)> 1056 <label> := Input.LA(1);<\n> 1057 <endif> 1058 Match(<char>); <checkRuleBacktrackFailure()> 1059 >> 1060 1061 /** match a character range */ 1062 charRangeRef(a,b,label) ::= << 1063 <if(label)> 1064 <label> := Input.LA(1);<\n> 1065 <endif> 1066 MatchRange(<a>, <b>); <checkRuleBacktrackFailure()> 1067 >> 1068 1069 /** For now, sets are interval tests and must be tested inline */ 1070 matchSet(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> 1078 if (<s>) then 1079 begin 1080 Input.Consume; 1081 <postmatchCode> 1082 <if(!LEXER)> 1083 State.ErrorRecovery := False;<endif> 1084 <if(backtracking)>State.Failed := False;<endif> 1085 end 1086 else 1087 begin 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> 1100 end;<\n> 1101 >> 1102 1103 matchRuleBlockSet ::= matchSet 1104 1105 matchSetAndListLabel(s,label,elementIndex,postmatchCode) ::= << 1106 <matchSet(...)> 1107 <listLabel(elem=label,...)> 1108 >> 1109 1110 /** Match a string literal */ 1111 lexerStringRef(string,label,elementIndex) ::= << 1112 <if(label)> 1113 Locals.AsInteger['<label>Start'] := CharIndex; 1114 Match(<string>); <checkRuleBacktrackFailure()> 1115 <label> := TCommonToken.Create(Input, TToken.INVALID_TOKEN_TYPE, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start'], CharIndex-1); 1116 <else> 1117 Match(<string>); <checkRuleBacktrackFailure()> 1118 <endif> 1119 >> 1120 1121 wildcard(label,elementIndex) ::= << 1122 <if(label)> 1123 <label> := Input.LT(1) as I<labelType>;<\n> 1124 <endif> 1125 MatchAny(input); <checkRuleBacktrackFailure()> 1126 >> 1127 1128 wildcardAndListLabel(label,elementIndex) ::= << 1129 <wildcard(...)> 1130 <listLabel(elem=label,...)> 1131 >> 1132 1133 /** Match . wildcard in lexer */ 1134 wildcardChar(label, elementIndex) ::= << 1135 <if(label)> 1136 <label> := Input.LA(1);<\n> 1137 <endif> 1138 MatchAny(); <checkRuleBacktrackFailure()> 1139 >> 1140 1141 wildcardCharListLabel(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 */ 1152 ruleRef(rule,label,elementIndex,args,scope) ::= << 1153 PushFollow(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> 1159 State.FollowingStackPointer := State.FollowingStackPointer - 1; 1160 <checkRuleBacktrackFailure()> 1161 >> 1162 1163 /** ids+=r */ 1164 ruleRefAndListLabel(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 */ 1175 lexerRuleRef(rule,label,args,elementIndex,scope) ::= << 1176 <if(label)> 1177 Locals.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 */ 1187 lexerRuleRefAndListLabel(rule,label,args,elementIndex,scope) ::= << 1188 <lexerRuleRef(...)> 1189 <listLabel(elem=label,...)> 1190 >> 1191 1192 /** EOF in the lexer */ 1193 lexerMatchEOF(label,elementIndex) ::= << 1194 <if(label)> 1195 Locals.AsInteger['<label>Start<elementIndex>'] := CharIndex; 1196 Match(EOF); <checkRuleBacktrackFailure()> 1197 Locals['<label>'] := TCommonToken.Create(Input, EOF, TToken.DEFAULT_CHANNEL, Locals.AsInteger['<label>Start<elementIndex>'], CharIndex-1); 1198 <else> 1199 Match(EOF); <checkRuleBacktrackFailure()> 1200 <endif> 1201 >> 1202 1203 /** match ^(root children) in tree parser */ 1204 tree(root, actionsAfterRoot, children, nullableChildList, 1205 enclosingTreeLevel, treeLevel) ::= << 1206 <root:element()> 1207 <actionsAfterRoot:element()> 1208 <if(nullableChildList)> 1209 if (Input.LA(1) = TToken.DOWN) then 1210 begin 1211 Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()> 1212 <children:element()> 1213 Match(Input, TToken.UP, nil); <checkRuleBacktrackFailure()> 1214 end; 1215 <else> 1216 Match(Input, TToken.DOWN, nil); <checkRuleBacktrackFailure()> 1217 <children:element()> 1218 Match(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 */ 1225 validateSemanticPredicate(pred,description) ::= << 1226 if (not (<evalPredicate(...)>)) then 1227 begin 1228 <ruleBacktrackFailure()> 1229 raise EFailedPredicateException.Create(Input, '<ruleName>', '<description>'); 1230 end;<\n> 1231 >> 1232 1233 // F i x e d D F A (if-then-else) 1234 1235 dfaState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1236 FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>);<\n> 1237 <edges; separator="\nelse "> 1238 else 1239 begin 1240 <if(eotPredictsAlt)> 1241 Alt[<decisionNumber>] := <eotPredictsAlt>;<\n> 1242 <else> 1243 <ruleBacktrackFailure()> 1244 raise ENoViableAltException.Create('<description>', <decisionNumber>, <stateNumber>, Input);<\n> 1245 <endif> 1246 end; 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 */ 1254 dfaOptionalBlockState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1255 FLA[<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 */ 1265 dfaLoopbackState(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1266 FLA[<decisionNumber>,<stateNumber>] := Input.LA(<k>); 1267 <edges; separator="\nelse ">;<\n> 1268 <if(eotPredictsAlt)> 1269 <if(!edges)> 1270 Alt[<decisionNumber>] := <eotPredictsAlt>; <! if no edges, don't gen ELSE !> 1271 <else> 1272 else 1273 begin 1274 Alt[<decisionNumber>] := <eotPredictsAlt>; 1275 end;<\n> 1276 <endif> 1277 <endif> 1278 >> 1279 1280 /** An accept state indicates a unique alternative has been predicted */ 1281 dfaAcceptState(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 */ 1287 dfaEdge(labelExpr, targetState, predicates) ::= << 1288 if ((<labelExpr>)<if(predicates)> and (<predicates>)<endif>) then 1289 begin 1290 <targetState> 1291 end <! 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 */ 1299 dfaStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1300 case Input.LA(<k>) of 1301 <edges; separator="\n"> 1302 else 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; 1312 end;<\n> 1313 >> 1314 1315 dfaOptionalBlockStateSwitch(k,edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1316 case Input.LA(<k>) of 1317 <edges; separator="\n"> 1318 end;<\n> 1319 >> 1320 1321 dfaLoopbackStateSwitch(k, edges,eotPredictsAlt,description,stateNumber,semPredState) ::= << 1322 case Input.LA(<k>) of 1323 <edges; separator="\n"><\n> 1324 <if(eotPredictsAlt)> 1325 else 1326 Alt[<decisionNumber>] := <eotPredictsAlt>;<\n> 1327 <endif> 1328 end;<\n> 1329 >> 1330 1331 dfaEdgeSwitch(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 */ 1344 dfaDecision(decisionNumber,description) ::= << 1345 Alt[<decisionNumber>] := FDFA<decisionNumber>.Predict(Input); 1346 >> 1347 1348 /* Dump DFA tables. 1349 */ 1350 cyclicDFADeclaration(dfa) ::= << 1351 strict 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)> 1363 strict protected 1364 function DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer; 1365 const AInput: IIntStream): Integer;<endif> 1366 >> 1367 1368 cyclicDFA(dfa) ::= << 1369 { T<grammar.recognizerName>.TDFA<dfa.decisionNumber> } 1370 1371 constructor T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Create(const ARecognizer: IBaseRecognizer); 1372 const 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">); 1381 begin 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); 1392 end; 1393 1394 function T<grammar.recognizerName>.TDFA<dfa.decisionNumber>.Description: String; 1395 begin 1396 Result := '<dfa.description>'; 1397 end;<\n> 1398 <if(dfa.specialStateSTs)> 1399 function T<grammar.recognizerName>.DFA<dfa.decisionNumber>_SpecialStateTransition(const DFA: IDFA; S: Integer; 1400 const AInput: IIntStream): Integer; 1401 var 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; 1414 begin 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; 1445 end;<\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 */ 1452 cyclicDFAState(decisionNumber,stateNumber,edges,needErrorClause,semPredState) ::= << 1453 FLA[<decisionNumber>,<stateNumber>] := Input.LA(1);<\n> 1454 <if(semPredState)> <! get next lookahead symbol to test edges, then rewind !> 1455 Locals.AsInteger['index<decisionNumber>_<stateNumber>'] := Input.Index; 1456 Input.Rewind;<\n> 1457 <endif> 1458 S := -1; 1459 <edges; separator="\nelse ">; 1460 <if(semPredState)> <! return input cursor to state before we rewound !> 1461 Input.Seek(Locals.AsInteger['index<decisionNumber>_<stateNumber>']);<\n> 1462 <endif> 1463 if (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 */ 1470 cyclicDFAEdge(labelExpr, targetStateNumber, edgeNumber, predicates) ::= << 1471 if ((<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 */ 1478 eotDFAEdge(targetStateNumber,edgeNumber, predicates) ::= << 1479 S := <targetStateNumber>;<\n> 1480 >> 1481 1482 1483 // D F A E X P R E S S I O N S 1484 1485 andPredicates(left,right) ::= "((<left>) and (<right>))" 1486 1487 orPredicates(operands) ::= "((<first(operands)>)<rest(operands):{o | or (<o>)}>)" 1488 1489 notPredicate(pred) ::= "!(<evalPredicate(...)>)" 1490 1491 evalPredicate(pred,description) ::= "(<pred>)" 1492 1493 evalSynPredicate(pred,description) ::= "<pred>()" 1494 1495 lookaheadTest(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 */ 1500 isolatedLookaheadTest(atom,k,atomAsInt) ::= "Input.LA(<k>) = <atomAsInt>" 1501 1502 lookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= << 1503 ((FLA[<decisionNumber>,<stateNumber>] \>= <lowerAsInt>) and (FLA[<decisionNumber>,<stateNumber>] \<= <upperAsInt>)) 1504 >> 1505 1506 isolatedLookaheadRangeTest(lower,upper,k,rangeNumber,lowerAsInt,upperAsInt) ::= "(Input.LA(<k>) \>= <lowerAsInt>) and (Input.LA(<k>) \<= <upperAsInt>)" 1507 1508 setTest(ranges) ::= "<ranges; separator=\") or (\">" 1509 1510 // A T T R I B U T E S 1511 1512 globalAttributeScope(scope) ::= << 1513 <scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n> 1514 <endif> 1515 >> 1516 1517 globalAttributeScopeDeclaration(scope) ::= << 1518 <if(scope.attributes)> 1519 strict 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; 1527 strict protected 1528 <scope.name>Stack: IStackList\<I<scope.name>Scope\>; 1529 <endif> 1530 >> 1531 1532 ruleAttributeScopeDeclaration(scope) ::= << 1533 <if(scope.attributes)> 1534 strict 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; 1542 strict protected 1543 <scope.name>Stack: IStackList\<I<scope.name>Scope\>; 1544 <endif> 1545 >> 1546 1547 ruleAttributeScope(scope) ::= << 1548 <! protected Stack <scope.name>Stack = new Stack();<\n> !> 1549 >> 1550 1551 ruleAttributeScopeInit(scope) ::= << 1552 <if(scope)> 1553 <scope.name>Stack := TStackList\<I<scope.name>Scope\>.Create;<\n> 1554 <endif> 1555 >> 1556 1557 returnStructName() ::= "<it.name>_return" 1558 1559 returnType() ::= << 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 */ 1575 ruleLabelType(referencedRule) ::= << 1576 <if(referencedRule.hasMultipleReturnValues)> 1577 I<referencedRule.name>_return 1578 <else> 1579 <if(referencedRule.hasSingleReturnValue)> 1580 <referencedRule.singleValueReturnType> 1581 <else> 1582 void 1583 <endif> 1584 <endif> 1585 >> 1586 1587 delegateName() ::= << 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 */ 1594 initValue(typeName) ::= << 1595 <csharpTypeInitMap.(typeName)> 1596 >> 1597 1598 /** Define a rule label including default value */ 1599 ruleLabelDef(label) ::= << 1600 <label.label.text> := <initValue(typeName=ruleLabelType(referencedRule=label.referencedRule))>;<\n> 1601 >> 1602 1603 ruleLabelDefVar(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 */ 1611 returnScope(scope) ::= << 1612 <if(ruleDescriptor.hasMultipleReturnValues)> 1613 { T<ruleDescriptor:returnStructName()> } 1614 1615 <scope.attributes:{public <it.decl>;}; separator="\n"> 1616 <@ruleReturnMembers()> 1617 <endif> 1618 >> 1619 1620 returnScopeDeclaration(scope) ::= << 1621 <if(ruleDescriptor.hasMultipleReturnValues)> 1622 public 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 1631 parameterScope(scope) ::= << 1632 <scope.attributes:{<it.decl>}; separator=", "> 1633 >> 1634 1635 parameterAttributeRef(attr) ::= "<attr.name>" 1636 parameterSetAttributeRef(attr,expr) ::= "<attr.name> := <expr>;" 1637 1638 scopeAttributeRef(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 1651 scopeSetAttributeRef(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 */ 1667 isolatedDynamicScopeRef(scope) ::= "<scope>Stack" 1668 1669 /** reference an attribute of rule; might only have single return value */ 1670 ruleLabelRef(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 1678 returnAttributeRef(ruleDescriptor,attr) ::= << 1679 <if(ruleDescriptor.hasMultipleReturnValues)> 1680 RetVal.<attr.name> 1681 <else> 1682 <attr.name> 1683 <endif> 1684 >> 1685 1686 returnSetAttributeRef(ruleDescriptor,attr,expr) ::= << 1687 <if(ruleDescriptor.hasMultipleReturnValues)> 1688 RetVal.<attr.name> := <expr>; 1689 <else> 1690 <attr.name> := <expr>; 1691 <endif> 1692 >> 1693 1694 /** How to translate $tokenLabel */ 1695 tokenLabelRef(label) ::= "<label>" 1696 1697 /** ids+=ID {$ids} or e+=expr {$e} */ 1698 listLabelRef(label) ::= "list_<label>" 1699 1700 1701 // not sure the next are the right approach 1702 1703 tokenLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)" 1704 tokenLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)" 1705 tokenLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)" 1706 tokenLabelPropertyRef_pos(scope,attr) ::= "(Def(<scope>).CharPositionInLine)" 1707 tokenLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)" 1708 tokenLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)" 1709 tokenLabelPropertyRef_tree(scope,attr) ::= "<scope>_tree" 1710 tokenLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))" 1711 1712 ruleLabelPropertyRef_start(scope,attr) ::= "(IfThen(Assigned(<scope>), Def(<scope>).Start, nil) as I<labelType>)" 1713 ruleLabelPropertyRef_stop(scope,attr) ::= "(Def(<scope>).Stop as I<labelType>)" 1714 ruleLabelPropertyRef_tree(scope,attr) ::= "(Def(Def(<scope>).Tree as I<ASTLabelType>))" 1715 ruleLabelPropertyRef_text(scope,attr) ::= << 1716 <if(TREE_PARSER)> 1717 IfThen(Assigned(<scope>), Input.TokenStream.ToString( 1718 Input.TreeAdaptor.GetTokenStartIndex(Def(<scope>).Start), 1719 Input.TreeAdaptor.GetTokenStopIndex(Def(<scope>).Start)), '') 1720 <else> 1721 IfThen(Assigned(<scope>), Input.ToString( 1722 (Def(<scope>).Start) as IToken,(Def(<scope>).Stop) as IToken), '') 1723 <endif> 1724 >> 1725 ruleLabelPropertyRef_st(scope,attr) ::= "((<scope> != null) ? <scope>.ST : null)" 1726 1727 /** Isolated $RULE ref ok in lexer as it's a Token */ 1728 lexerRuleLabel(label) ::= "<label>" 1729 1730 lexerRuleLabelPropertyRef_type(scope,attr) ::= "(Def(<scope>).TokenType)" 1731 lexerRuleLabelPropertyRef_line(scope,attr) ::= "(Def(<scope>).Line)" 1732 lexerRuleLabelPropertyRef_pos(scope,attr) ::= "(IfThen(Assigned(<scope>),Def(<scope>).CharPositionInLine,-1))" 1733 lexerRuleLabelPropertyRef_channel(scope,attr) ::= "(Def(<scope>).Channel)" 1734 lexerRuleLabelPropertyRef_index(scope,attr) ::= "(Def(<scope>).TokenIndex)" 1735 lexerRuleLabelPropertyRef_text(scope,attr) ::= "(Def(<scope>).Text)" 1736 lexerRuleLabelPropertyRef_int(scope,attr) ::= "(StrToIntDef(Def(<scope>).Text,0))" 1737 1738 // Somebody may ref $template or $tree or $stop within a rule: 1739 rulePropertyRef_start(scope,attr) ::= "(RetVal.Start as I<labelType>)" 1740 rulePropertyRef_stop(scope,attr) ::= "(RetVal.Stop as I<labelType>)" 1741 rulePropertyRef_tree(scope,attr) ::= "(RetVal.Tree as I<ASTLabelType>)" 1742 rulePropertyRef_text(scope,attr) ::= << 1743 <if(TREE_PARSER)> 1744 Input.TokenStream.ToString( 1745 Input.TreeAdaptor.GetTokenStartIndex(RetVal.Start), 1746 Input.TreeAdaptor.GetTokenStopIndex(RetVal.Start)) 1747 <else> 1748 Input.ToString(RetVal.Start as IToken,Input.LT(-1)) 1749 <endif> 1750 >> 1751 rulePropertyRef_st(scope,attr) ::= "RetVal.ST" 1752 1753 lexerRulePropertyRef_text(scope,attr) ::= "Text" 1754 lexerRulePropertyRef_type(scope,attr) ::= "TokenType" 1755 lexerRulePropertyRef_line(scope,attr) ::= "State.TokenStartLine" 1756 lexerRulePropertyRef_pos(scope,attr) ::= "State.TokenStartCharPositionInLine" 1757 lexerRulePropertyRef_index(scope,attr) ::= "-1" // undefined token index in lexer 1758 lexerRulePropertyRef_channel(scope,attr) ::= "Channel" 1759 lexerRulePropertyRef_start(scope,attr) ::= "State.TokenStartCharIndex" 1760 lexerRulePropertyRef_stop(scope,attr) ::= "(CharIndex-1)" 1761 lexerRulePropertyRef_int(scope,attr) ::= "StrToInt(<scope>.Text)" 1762 1763 // setting $st and $tree is allowed in local rule. everything else 1764 // is flagged as error 1765 ruleSetPropertyRef_tree(scope,attr,expr) ::= "RetVal.Tree := <expr>;" 1766 ruleSetPropertyRef_st(scope,attr,expr) ::= "RetVal.ST := <expr>;" 1767 1768 1769 /** How to execute an action (only when not backtracking) */ 1770 execAction(action) ::= << 1771 <if(backtracking)> 1772 <if(actions.(actionScope).synpredgate)> 1773 if (<actions.(actionScope).synpredgate>) then 1774 begin 1775 <action> 1776 end; 1777 <else> 1778 if (State.Backtracking = 0) then 1779 begin 1780 <action> 1781 end;<\n> 1782 <endif> 1783 <else> 1784 <action> 1785 <endif> 1786 >> 1787 1788 1789 /** How to always execute an action even when backtracking */ 1790 execForcedAction(action) ::= "<action>" 1791 1792 // M I S C (properties, etc...) 1793 1794 bitset(name, words64) ::= << 1795 <name> := TBitSet.Create([<words64:{<it>};separator=",">]);<\n> 1796 >> 1797 1798 bitsetDecl(name) ::= << 1799 <name>: IBitSet;<\n> 1800 >> 1801 1802 codeFileExtension() ::= ".pas" 1803 1804 true() ::= "True" 1805 false() ::= "False" 1806