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