CppCodeGenerator.java
上传用户:afrynkmhm
上传日期:2007-01-06
资源大小:1262k
文件大小:109k
源码类别:

编译器/解释器

开发平台:

Others

  1. package antlr;
  2. /* ANTLR Translator Generator
  3.  * Project led by Terence Parr at http://www.jGuru.com
  4.  * Software rights: http://www.antlr.org/RIGHTS.html
  5.  *
  6.  * $Id: //depot/code/org.antlr/release/antlr-2.7.0/antlr/CppCodeGenerator.java#1 $
  7.  */
  8. // C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
  9. import java.util.Enumeration;
  10. import java.util.Hashtable;
  11. import antlr.collections.impl.BitSet;
  12. import antlr.collections.impl.Vector;
  13. import java.io.PrintWriter; //SAS: changed for proper text file io
  14. import java.io.IOException;
  15. import java.io.FileWriter;
  16. /**Generate MyParser.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp and MyParserTokenTypes.hpp */
  17. public class CppCodeGenerator extends CodeGenerator {
  18. // non-zero if inside syntactic predicate generation
  19. protected int syntacticPredLevel = 0;
  20. // Are we generating ASTs (for parsers and tree parsers) right now?
  21. protected boolean genAST = false;
  22. // Are we saving the text consumed (for lexers) right now?
  23. protected boolean saveText = false;
  24. // Grammar parameters set up to handle different grammar classes.
  25. // These are used to get instanceof tests out of code generation
  26. String labeledElementType;
  27. String labeledElementASTType;
  28. String labeledElementInit;
  29. String commonExtraArgs;
  30. String commonExtraParams;
  31. String commonLocalVars;
  32. String lt1Value;
  33. String exceptionThrown;
  34. String throwNoViable;
  35. // Tracks the rule being generated.  Used for mapTreeId
  36. RuleBlock currentRule;
  37. // Tracks the rule or labeled subrule being generated.  Used for AST generation.
  38. String currentASTResult;
  39. // Mapping between the ids used in the current alt, and the
  40. // names of variables used to represent their AST values.
  41. Hashtable treeVariableMap = new Hashtable();
  42. // Count of unnamed generated variables
  43. int astVarNumber = 1;
  44. // Special value used to mark duplicate in treeVariableMap
  45. protected static final String NONUNIQUE = new String();
  46. private Vector semPreds;
  47. private static final String namespaceStd   = "ANTLR_USE_NAMESPACE(std)";
  48. private static final String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
  49. private static final String preIncludeCpp  = "pre_include_cpp";
  50. private static final String preIncludeHpp  = "pre_include_hpp";
  51. private static final String postIncludeCpp = "post_include_cpp";
  52. private static final String postIncludeHpp = "post_include_hpp";
  53. /** Create a C++ code-generator using the given Grammar.
  54.  * The caller must still call setTool, setBehavior, and setAnalyzer
  55.  * before generating code.
  56.  */
  57. public CppCodeGenerator() {
  58. super();
  59. charFormatter = new CppCharFormatter();
  60. }
  61. /** Adds a semantic predicate string to the sem pred vector
  62.     These strings will be used to build an array of sem pred names
  63.     when building a debugging parser.  This method should only be
  64.     called when the debug option is specified
  65.  */
  66. protected int addSemPred(String predicate) {
  67. semPreds.appendElement(predicate);
  68. return semPreds.size()-1;
  69. }
  70. public void exitIfError() {
  71. if (tool.hasError) {
  72. System.out.println("Exiting due to errors.");
  73. System.exit(1);
  74. }
  75. }
  76. /**Generate the parser, lexer, treeparser, and token types in C++ */
  77. public void gen() {
  78. // Do the code generation
  79. try {
  80. // Loop over all grammars
  81. Enumeration grammarIter = behavior.grammars.elements();
  82. while (grammarIter.hasMoreElements()) {
  83. Grammar g = (Grammar)grammarIter.nextElement();
  84. // Connect all the components to each other
  85. g.setGrammarAnalyzer(analyzer);
  86. g.setCodeGenerator(this);
  87. analyzer.setGrammar(g);
  88. // To get right overloading behavior across hetrogeneous grammars
  89. setupGrammarParameters(g);
  90. g.generate();
  91. exitIfError();
  92. }
  93. // Loop over all token managers (some of which are lexers)
  94. Enumeration tmIter = behavior.tokenManagers.elements();
  95. while (tmIter.hasMoreElements()) {
  96. TokenManager tm = (TokenManager)tmIter.nextElement();
  97. if (!tm.isReadOnly()) {
  98. // Write the token manager tokens as C++
  99. // this must appear before genTokenInterchange so that
  100. // labels are set on string literals
  101. genTokenTypes(tm);
  102. // Write the token manager tokens as plain text
  103. genTokenInterchange(tm);
  104. }
  105. exitIfError();
  106. }
  107. }
  108. catch (IOException e) {
  109. System.out.println(e.getMessage());
  110. }
  111. }
  112. /** Generate code for the given grammar element.
  113.  * @param blk The {...} action to generate
  114.  */
  115. public void gen(ActionElement action) {
  116. if ( DEBUG_CODE_GENERATOR ) System.out.println("genAction("+action+")");
  117. if ( action.isSemPred ) {
  118. genSemPred(action.actionText, action.line);
  119. }
  120. else {
  121. if ( grammar.hasSyntacticPredicate ) {
  122. println("if ( inputState->guessing==0 ) {");
  123. tabs++;
  124. }
  125. ActionTransInfo tInfo = new ActionTransInfo();
  126. String actionStr = processActionForTreeSpecifiers(action.actionText, action.getLine(), currentRule, tInfo);
  127. if ( tInfo.refRuleRoot!=null ) {
  128. // Somebody referenced "#rule", make sure translated var is valid
  129. // assignment to #rule is left as a ref also, meaning that assignments
  130. // with no other refs like "#rule = foo();" still forces this code to be
  131. // generated (unnecessarily).
  132. println(tInfo.refRuleRoot + " = "+labeledElementASTType+"(currentAST.root);");
  133. }
  134. // dump the translated action
  135. printAction(actionStr);
  136. if ( tInfo.assignToRoot ) {
  137. // Somebody did a "#rule=", reset internal currentAST.root
  138. println("currentAST.root = "+tInfo.refRuleRoot+";");
  139. // reset the child pointer too to be last sibling in sibling list
  140. println("currentAST.child = "+tInfo.refRuleRoot+"!="+namespaceAntlr+"nullAST &&"+tInfo.refRuleRoot+"->getFirstChild()!="+namespaceAntlr+"nullAST ?");
  141. tabs++;
  142. println(tInfo.refRuleRoot+"->getFirstChild() : "+tInfo.refRuleRoot+";");
  143. tabs--;
  144. println("currentAST.advanceChildToEnd();");
  145. }
  146. if ( grammar.hasSyntacticPredicate ) {
  147. tabs--;
  148. println("}");
  149. }
  150. }
  151. }
  152. /** Generate code for the given grammar element.
  153.  * @param blk The "x|y|z|..." block to generate
  154.  */
  155. public void gen(AlternativeBlock blk) {
  156. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen("+blk+")");
  157. println("{");
  158. genBlockPreamble(blk);
  159. // Tell AST generation to build subrule result
  160. String saveCurrentASTResult = currentASTResult;
  161. if (blk.getLabel() != null) {
  162. currentASTResult = blk.getLabel();
  163. }
  164. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  165. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
  166. genBlockFinish(howToFinish, throwNoViable);
  167. println("}");
  168. // Restore previous AST generation
  169. currentASTResult = saveCurrentASTResult;
  170. }
  171. /** Generate code for the given grammar element.
  172.  * @param blk The block-end element to generate.  Block-end
  173.  * elements are synthesized by the grammar parser to represent
  174.  * the end of a block.
  175.  */
  176. public void gen(BlockEndElement end) {
  177. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
  178. }
  179. /** Generate code for the given grammar element.
  180.  * @param blk The character literal reference to generate
  181.  */
  182. public void gen(CharLiteralElement atom) {
  183. if ( DEBUG_CODE_GENERATOR ) System.out.println("genChar("+atom+")");
  184. if ( atom.getLabel()!=null ) {
  185. println(atom.getLabel() + " = " + lt1Value + ";");
  186. }
  187. boolean oldsaveText = saveText;
  188. saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
  189. genMatch(atom);
  190. saveText = oldsaveText;
  191. }
  192. /** Generate code for the given grammar element.
  193.  * @param blk The character-range reference to generate
  194.  */
  195. public void gen(CharRangeElement r) {
  196. if ( r.getLabel()!=null  && syntacticPredLevel == 0) {
  197. println(r.getLabel() + " = " + lt1Value + ";");
  198. }
  199. println("matchRange("+textOrChar(r.beginText)+","+textOrChar(r.endText)+");");
  200. }
  201. /** Generate the lexer C++ files */
  202. public  void gen(LexerGrammar g) throws IOException {
  203. // If debugging, create a new sempred vector for this grammar
  204. if (g.debuggingOutput)
  205. semPreds = new Vector();
  206. setGrammar(g);
  207. if (!(grammar instanceof LexerGrammar)) {
  208. tool.panic("Internal error generating lexer");
  209. }
  210. genBody(g);
  211. genInclude(g);
  212. }
  213. /** Generate code for the given grammar element.
  214.  * @param blk The (...)+ block to generate
  215.  */
  216. public void gen(OneOrMoreBlock blk) {
  217. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
  218. String label;
  219. String cnt;
  220. println("{");
  221. genBlockPreamble(blk);
  222. if ( blk.getLabel() != null ) {
  223. cnt = "_cnt_"+blk.getLabel();
  224. }
  225. else {
  226. cnt = "_cnt" + blk.ID;
  227. }
  228. println("int "+cnt+"=0;");
  229. if ( blk.getLabel() != null ) {
  230. label = blk.getLabel();
  231. }
  232. else {
  233. label = "_loop" + blk.ID;
  234. }
  235. println("for (;;) {");
  236. tabs++;
  237. // Tell AST generation to build subrule result
  238. String saveCurrentASTResult = currentASTResult;
  239. if (blk.getLabel() != null) {
  240. currentASTResult = blk.getLabel();
  241. }
  242. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  243. // generate exit test if greedy set to false
  244. // and an alt is ambiguous with exit branch
  245. // or when lookahead derived purely from end-of-file
  246. // Lookahead analysis stops when end-of-file is hit,
  247. // returning set {epsilon}.  Since {epsilon} is not
  248. // ambig with any real tokens, no error is reported
  249. // by deterministic() routines and we have to check
  250. // for the case where the lookahead depth didn't get
  251. // set to NONDETERMINISTIC (this only happens when the
  252. // FOLLOW contains real atoms + epsilon).
  253. boolean generateNonGreedyExitPath = false;
  254. int nonGreedyExitDepth = grammar.maxk;
  255. if ( !blk.greedy &&
  256.  blk.exitLookaheadDepth<=grammar.maxk &&
  257.  blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  258. {
  259. generateNonGreedyExitPath = true;
  260. nonGreedyExitDepth = blk.exitLookaheadDepth;
  261. }
  262. else if ( !blk.greedy &&
  263.   blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  264. {
  265. generateNonGreedyExitPath = true;
  266. }
  267. // generate exit test if greedy set to false
  268. // and an alt is ambiguous with exit branch
  269. if ( generateNonGreedyExitPath ) {
  270. if ( DEBUG_CODE_GENERATOR ) {
  271. System.out.println("nongreedy (...)+ loop; exit depth is "+
  272.    blk.exitLookaheadDepth);
  273. }
  274. String predictExit =
  275. getLookaheadTestExpression(blk.exitCache,
  276.    nonGreedyExitDepth);
  277. println("// nongreedy exit test");
  278. println("if ( "+cnt+">=1 && "+predictExit+") goto "+label+";");
  279. }
  280. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  281. genBlockFinish(
  282. howToFinish, 
  283. "if ( "+cnt+">=1 ) { goto "+label+"; } else {" + throwNoViable + "}"
  284. );
  285. println(cnt+"++;");
  286. tabs--;
  287. println("}");
  288. println(label+":;");
  289. println("}");
  290. // Restore previous AST generation
  291. currentASTResult = saveCurrentASTResult;
  292. }
  293. /** Generate the parser C++ file */
  294. public void gen(ParserGrammar g) throws IOException {
  295. // if debugging, set up a new vector to keep track of sempred
  296. //   strings for this grammar
  297. if (g.debuggingOutput)
  298. semPreds = new Vector();
  299. setGrammar(g);
  300. if (!(grammar instanceof ParserGrammar)) {
  301. tool.panic("Internal error generating parser");
  302. }
  303. genBody(g);
  304. genInclude(g);
  305. }
  306. /** Generate code for the given grammar element.
  307.  * @param blk The rule-reference to generate
  308.  */
  309. public void gen(RuleRefElement rr) {
  310. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
  311. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  312. if (rs == null || !rs.isDefined())
  313. {
  314. // Is this redundant???
  315. tool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine());
  316. return;
  317. }
  318. if (!(rs instanceof RuleSymbol))
  319. {
  320. // Is this redundant???
  321. tool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine());
  322. return;
  323. }
  324. genErrorTryForElement(rr);
  325. // AST value for labeled rule refs in tree walker.
  326. // This is not AST construction;  it is just the input tree node value.
  327. if ( grammar instanceof TreeWalkerGrammar && 
  328. rr.getLabel() != null && 
  329. syntacticPredLevel == 0 )
  330. {
  331. println(rr.getLabel() + " = _t==ASTNULL ? "+namespaceAntlr+"nullAST : "+lt1Value+";");
  332. }
  333. // if in lexer and ! on rule ref or alt or rule, save buffer index to kill later
  334. if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  335. println("_saveIndex=text.length();");
  336. }
  337. // Process return value assignment if any
  338. printTabs();
  339. if (rr.idAssign != null)
  340. {
  341. // Warn if the rule has no return type
  342. if (rs.block.returnAction == null)
  343. {
  344. tool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine());
  345. }
  346. _print(rr.idAssign + "=");
  347. } else {
  348. // Warn about return value if any, but not inside syntactic predicate
  349. if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
  350. {
  351. tool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine());
  352. }
  353. }
  354. // Call the rule
  355. GenRuleInvocation(rr);
  356. // if in lexer and ! on element or alt or rule, save buffer index to kill later
  357. if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  358. println("text.erase(_saveIndex);");
  359. }
  360. // if not in a syntactic predicate
  361. if (syntacticPredLevel == 0) {
  362. boolean doNoGuessTest = (
  363. grammar.hasSyntacticPredicate &&
  364. (
  365. grammar.buildAST && rr.getLabel() != null || 
  366. (genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
  367. )
  368. );
  369. if (doNoGuessTest) {
  370. println("if (inputState->guessing==0) {"); 
  371. tabs++;
  372. }
  373. if (grammar.buildAST && rr.getLabel() != null) {
  374. // always gen variable for rule return on labeled rules
  375. println(rr.getLabel() + "_AST = "+labeledElementASTType+"(returnAST);");
  376. }
  377. if (genAST) {
  378. switch (rr.getAutoGenType()) {
  379. case GrammarElement.AUTO_GEN_NONE:
  380. // println("theASTFactory.addASTChild(currentAST, returnAST);");
  381. println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(returnAST));");
  382. break;
  383. case GrammarElement.AUTO_GEN_CARET:
  384. tool.error("Internal: encountered ^ after rule reference");
  385. break;
  386. default:
  387. break;
  388. }
  389. }
  390. // if a lexer and labeled, Token label defined at rule level, just set it here
  391. if ( grammar instanceof LexerGrammar && rr.getLabel() != null ) {
  392. println(rr.getLabel()+"=_returnToken;");
  393. }
  394. if (doNoGuessTest) {
  395. tabs--;
  396. println("}"); 
  397. }
  398. }
  399. genErrorCatchForElement(rr);
  400. }
  401. /** Generate code for the given grammar element.
  402.  * @param blk The string-literal reference to generate
  403.  */
  404. public void gen(StringLiteralElement atom) {
  405. if ( DEBUG_CODE_GENERATOR ) System.out.println("genString("+atom+")");
  406. // Variable declarations for labeled elements
  407. if (atom.getLabel()!=null && syntacticPredLevel == 0) {
  408. println(atom.getLabel() + " = " + lt1Value + ";");
  409. }
  410. // AST
  411. genElementAST(atom);
  412. // is there a bang on the literal?
  413. boolean oldsaveText = saveText;
  414. saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
  415. // matching
  416. genMatch(atom);
  417. saveText = oldsaveText;
  418. // tack on tree cursor motion if doing a tree walker
  419. if (grammar instanceof TreeWalkerGrammar) {
  420. println("_t = _t->getNextSibling();");
  421. }
  422. }
  423. /** Generate code for the given grammar element.
  424.  * @param blk The token-range reference to generate
  425.  */
  426. public void gen(TokenRangeElement r) {
  427. genErrorTryForElement(r);
  428. if ( r.getLabel()!=null  && syntacticPredLevel == 0) {
  429. println(r.getLabel() + " = " + lt1Value + ";");
  430. }
  431. // AST
  432. genElementAST(r);
  433. // match
  434. println("matchRange("+r.beginText+","+r.endText+");");
  435. genErrorCatchForElement(r);
  436. }
  437. /** Generate code for the given grammar element.
  438.  * @param blk The token-reference to generate
  439.  */
  440. public void gen(TokenRefElement atom) {
  441. if ( DEBUG_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
  442. if ( grammar instanceof LexerGrammar ) {
  443. tool.panic("Token reference found in lexer");
  444. }
  445. genErrorTryForElement(atom);
  446. // Assign Token value to token label variable
  447. if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
  448. println(atom.getLabel() + " = " + lt1Value + ";");
  449. }
  450. // AST
  451. genElementAST(atom);
  452. // matching
  453. genMatch(atom);
  454. genErrorCatchForElement(atom);
  455. // tack on tree cursor motion if doing a tree walker
  456. if (grammar instanceof TreeWalkerGrammar) {
  457. println("_t = _t->getNextSibling();");
  458. }
  459. }
  460. public void gen(TreeElement t) {
  461. // save AST cursor
  462. println(namespaceAntlr+"RefAST __t" + t.ID + " = _t;");
  463. // If there is a label on the root, then assign that to the variable
  464. if (t.root.getLabel() != null) {
  465. println(t.root.getLabel() + " = _t==ASTNULL ? "+namespaceAntlr+"nullAST :"+labeledElementASTType+"(_t);");
  466. }
  467. // Generate AST variables
  468. genElementAST(t.root);
  469. if (grammar.buildAST) {
  470. // Save the AST construction state
  471. println(namespaceAntlr+"ASTPair __currentAST" + t.ID + " = currentAST;");
  472. // Make the next item added a child of the TreeElement root
  473. println("currentAST.root = currentAST.child;");
  474. println("currentAST.child = "+namespaceAntlr+"nullAST;");
  475. }
  476. // match root
  477. genMatch(t.root);
  478. // move to list of children
  479. println("_t = _t->getFirstChild();"); 
  480. // walk list of children, generating code for each
  481. for (int i=0; i<t.getAlternatives().size(); i++) {
  482. Alternative a = t.getAlternativeAt(i);
  483. AlternativeElement e = a.head;
  484. while ( e != null ) {
  485. e.generate();
  486. e = e.next;
  487. }
  488. }
  489. if (grammar.buildAST) {
  490. // restore the AST construction state to that just after the
  491. // tree root was added
  492. println("currentAST = __currentAST" + t.ID + ";");
  493. }
  494. // restore AST cursor
  495. println("_t = __t" + t.ID + ";");
  496. // move cursor to sibling of tree just parsed
  497. println("_t = _t->getNextSibling();");
  498. }
  499. /** Generate the tree-parser C++ files */
  500. public void gen(TreeWalkerGrammar g) throws IOException {
  501. setGrammar(g);
  502. if (!(grammar instanceof TreeWalkerGrammar)) {
  503. tool.panic("Internal error generating tree-walker");
  504. }
  505. genBody(g);
  506. genInclude(g);
  507. }
  508. /** Generate code for the given grammar element.
  509.  * @param wc The wildcard element to generate
  510.  */
  511. public void gen(WildcardElement wc) {
  512. // Variable assignment for labeled elements
  513. if (wc.getLabel()!=null && syntacticPredLevel == 0) {
  514. println(wc.getLabel() + " = " + lt1Value + ";");
  515. }
  516. // AST
  517. genElementAST(wc);
  518. // Match anything but EOF
  519. if (grammar instanceof TreeWalkerGrammar) {
  520. println("if ( _t=="+namespaceAntlr+"nullAST ) throw "+namespaceAntlr+"MismatchedTokenException();");
  521. }
  522. else if (grammar instanceof LexerGrammar) {
  523. if ( grammar instanceof LexerGrammar &&
  524. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  525. println("_saveIndex=text.length();");
  526. }
  527. println("matchNot(EOF/*_CHAR*/);");
  528. if ( grammar instanceof LexerGrammar &&
  529. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  530. println("text.erase(_saveIndex);");      // kill text atom put in buffer
  531. }
  532. }
  533. else {
  534. println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
  535. }
  536. // tack on tree cursor motion if doing a tree walker
  537. if (grammar instanceof TreeWalkerGrammar) {
  538. println("_t = _t->getNextSibling();");
  539. }
  540. }
  541. /** Generate code for the given grammar element.
  542.  * @param blk The (...)* block to generate
  543.  */
  544. public void gen(ZeroOrMoreBlock blk) {
  545. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
  546. println("{");
  547. genBlockPreamble(blk);
  548. String label;
  549. if ( blk.getLabel() != null ) {
  550. label = blk.getLabel();
  551. }
  552. else {
  553. label = "_loop" + blk.ID;
  554. }
  555. println("for (;;) {");
  556. tabs++;
  557. // Tell AST generation to build subrule result
  558. String saveCurrentASTResult = currentASTResult;
  559. if (blk.getLabel() != null) {
  560. currentASTResult = blk.getLabel();
  561. }
  562. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  563. // generate exit test if greedy set to false
  564. // and an alt is ambiguous with exit branch
  565. // or when lookahead derived purely from end-of-file
  566. // Lookahead analysis stops when end-of-file is hit,
  567. // returning set {epsilon}.  Since {epsilon} is not
  568. // ambig with any real tokens, no error is reported
  569. // by deterministic() routines and we have to check
  570. // for the case where the lookahead depth didn't get
  571. // set to NONDETERMINISTIC (this only happens when the
  572. // FOLLOW contains real atoms + epsilon).
  573. boolean generateNonGreedyExitPath = false;
  574. int nonGreedyExitDepth = grammar.maxk;
  575. if ( !blk.greedy &&
  576.  blk.exitLookaheadDepth<=grammar.maxk &&
  577.  blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  578. {
  579. generateNonGreedyExitPath = true;
  580. nonGreedyExitDepth = blk.exitLookaheadDepth;
  581. }
  582. else if ( !blk.greedy &&
  583.   blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  584. {
  585. generateNonGreedyExitPath = true;
  586. }
  587. if ( generateNonGreedyExitPath ) {
  588. if ( DEBUG_CODE_GENERATOR ) {
  589. System.out.println("nongreedy (...)* loop; exit depth is "+
  590.    blk.exitLookaheadDepth);
  591. }
  592. String predictExit =
  593. getLookaheadTestExpression(blk.exitCache,
  594.    nonGreedyExitDepth);
  595. println("// nongreedy exit test");
  596. println("if ("+predictExit+") goto "+label+";");
  597. }
  598. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  599. genBlockFinish(howToFinish, "goto " + label + ";");
  600. tabs--;
  601. println("}");
  602. println(label+":;");
  603. println("}");
  604. // Restore previous AST generation
  605. currentASTResult = saveCurrentASTResult;
  606. }
  607. /** Generate an alternative.
  608.   * @param alt  The alternative to generate
  609.   * @param blk The block to which the alternative belongs
  610.   */
  611. protected void genAlt(Alternative alt, AlternativeBlock blk) {
  612. // Save the AST generation state, and set it to that of the alt
  613. boolean savegenAST = genAST;
  614. genAST = genAST && alt.getAutoGen();
  615. boolean oldsaveTest = saveText;
  616. saveText = saveText && alt.getAutoGen();
  617. // Reset the variable name map for the alternative
  618. Hashtable saveMap = treeVariableMap;
  619. treeVariableMap = new Hashtable();
  620. // Generate try block around the alt for  error handling
  621. if (alt.exceptionSpec != null) {
  622. println("try {      // for error handling");
  623. tabs++;
  624. }
  625. AlternativeElement elem = alt.head;
  626. while ( !(elem instanceof BlockEndElement) ) {
  627. elem.generate(); // alt can begin with anything. Ask target to gen.
  628. elem = elem.next;
  629. }
  630. if ( genAST) {
  631. if (blk instanceof RuleBlock) {
  632. // Set the AST return value for the rule
  633. RuleBlock rblk = (RuleBlock)blk;
  634. println(rblk.getRuleName() + "_AST = "+labeledElementASTType+"(currentAST.root);");
  635. else if (blk.getLabel() != null) {
  636. // ### future: also set AST value for labeled subrules.
  637. // println(blk.getLabel() + "_AST = "+labeledElementASTType+"(currentAST.root);");
  638. }
  639. }
  640. if (alt.exceptionSpec != null) {
  641. // close try block
  642. tabs--;
  643. println("}");
  644. genErrorHandler(alt.exceptionSpec);
  645. }
  646. genAST = savegenAST;
  647. saveText = oldsaveTest;
  648. treeVariableMap = saveMap;
  649. }
  650. /** Generate all the bitsets to be used in the parser or lexer
  651.  * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
  652.  * and the BitSet object declarations like "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
  653.  * Note that most languages do not support object initialization inside a
  654.  * class definition, so other code-generators may have to separate the
  655.  * bitset declarations from the initializations (e.g., put the initializations
  656.  * in the generated constructor instead).
  657.  * @param bitsetList The list of bitsets to generate.
  658.  * @param maxVocabulary Ensure that each generated bitset can contain at least this value.
  659.  */
  660. protected void genBitsets(
  661. Vector bitsetList,
  662. int maxVocabulary,
  663. String prefix
  664. ) {
  665. println("");
  666. for (int i = 0; i < bitsetList.size(); i++)
  667. {
  668. BitSet p = (BitSet)bitsetList.elementAt(i);
  669. // Ensure that generated BitSet is large enough for vocabulary
  670. p.growToInclude(maxVocabulary);
  671. // initialization data
  672. println(
  673. "const unsigned long " + prefix + getBitsetName(i) + "_data_" + "[] = { " +
  674. p.toStringOfHalfWords() + 
  675. " };"
  676. );
  677. // BitSet object
  678. println(
  679. "const "+namespaceAntlr+"BitSet " + prefix + getBitsetName(i) + "(" +
  680. getBitsetName(i) + "_data_," + p.size()/32 +
  681. ");"
  682. );
  683. }
  684. }
  685. protected void genBitsetsHeader(
  686. Vector bitsetList,
  687. int maxVocabulary
  688. ) {
  689. println("");
  690. for (int i = 0; i < bitsetList.size(); i++)
  691. {
  692. BitSet p = (BitSet)bitsetList.elementAt(i);
  693. // Ensure that generated BitSet is large enough for vocabulary
  694. p.growToInclude(maxVocabulary);
  695. // initialization data
  696. println("static const unsigned long " + getBitsetName(i) + "_data_" + "[];");
  697. // BitSet object
  698. println("static const "+namespaceAntlr+"BitSet " + getBitsetName(i) + ";");
  699. }
  700. }
  701. /** Generate the finish of a block, using a combination of the info
  702.  * returned from genCommonBlock() and the action to perform when
  703.  * no alts were taken
  704.  * @param howToFinish The return of genCommonBlock()
  705.  * @param noViableAction What to generate when no alt is taken
  706.  */
  707. private void genBlockFinish(CppBlockFinishingInfo howToFinish, String noViableAction)
  708. {
  709. if (howToFinish.needAnErrorClause &&
  710.  (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
  711. if ( howToFinish.generatedAnIf ) {
  712. println("else {");
  713. }
  714. else {
  715. println("{");
  716. }
  717. tabs++;
  718. println(noViableAction);
  719. tabs--;
  720. println("}");
  721. }
  722. if ( howToFinish.postscript!=null ) {
  723. println(howToFinish.postscript);
  724. }
  725. }
  726. /** Generate the header for a block, which may be a RuleBlock or a
  727.  * plain AlternativeBLock.  This generates any variable declarations,
  728.  * init-actions, and syntactic-predicate-testing variables.
  729.  * @blk The block for which the preamble is to be generated.
  730.  */
  731. protected void genBlockPreamble(AlternativeBlock blk) {
  732. // define labels for rule blocks.
  733. if ( blk instanceof RuleBlock ) {
  734. RuleBlock rblk = (RuleBlock)blk;
  735. if ( rblk.labeledElements!=null ) {
  736. for (int i=0; i<rblk.labeledElements.size(); i++) {
  737. AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
  738. //System.out.println("looking at labeled element: "+a);
  739. // Variables for labeled rule refs and subrules are different than
  740. // variables for grammar atoms.  This test is a little tricky because
  741. // we want to get all rule refs and ebnf, but not rule blocks or
  742. // syntactic predicates
  743. if (
  744. a instanceof RuleRefElement ||
  745. a instanceof AlternativeBlock &&
  746. !(a instanceof RuleBlock) &&
  747. !(a instanceof SynPredBlock)
  748. ) {
  749. if (
  750. !(a instanceof RuleRefElement) && 
  751. ((AlternativeBlock)a).not &&
  752. analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
  753. ) {
  754. // Special case for inverted subrules that will be inlined.
  755. // Treat these like token or char literal references
  756. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  757. if (grammar.buildAST) {
  758. println(labeledElementASTType+" " + a.getLabel() + "_AST = "+namespaceAntlr+"nullAST;");
  759. }
  760. }
  761. else {
  762. if (grammar.buildAST) {
  763. // Always gen AST variables for labeled elements, even if the
  764. // element itself is marked with !
  765. println(labeledElementASTType+" " + a.getLabel() + "_AST = "+namespaceAntlr+"nullAST;");
  766. }
  767. if ( grammar instanceof LexerGrammar ) {
  768. println(namespaceAntlr+"RefToken "+a.getLabel()+";");
  769. }
  770. if (grammar instanceof TreeWalkerGrammar) {
  771. // always generate rule-ref variables for tree walker
  772. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  773. }
  774. }
  775. }
  776. else {
  777. // It is a token or literal reference.  Generate the
  778. // correct variable type for this grammar
  779. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  780. // In addition, generate *_AST variables if building ASTs
  781. if (grammar.buildAST) {
  782. println(labeledElementASTType+" " + a.getLabel() + "_AST = "+namespaceAntlr+"nullAST;");
  783. }
  784. }
  785. }
  786. }
  787. }
  788. // dump out init action
  789. if ( blk.initAction!=null ) {
  790. printAction(
  791. processActionForTreeSpecifiers(blk.initAction, 0, currentRule, null)
  792. );
  793. }
  794. }
  795. public void genBody(LexerGrammar g) throws IOException {
  796. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".cpp");
  797. //SAS: changed for proper text file io
  798. genAST = false; // no way to gen trees.
  799. saveText = true; // save consumed characters.
  800. tabs=0;
  801. // Generate header common to all C++ output files
  802. genHeader(grammar.getClassName() + ".cpp");
  803. println((String)behavior.headerActions.get(preIncludeCpp));
  804. // Generate header specific to lexer C++ file
  805. println("#include "" + grammar.getClassName() + ".hpp"");
  806. println("#include "antlr/CharBuffer.hpp"");
  807. println("#include "antlr/TokenStreamException.hpp"");
  808. println("#include "antlr/TokenStreamIOException.hpp"");
  809. println("#include "antlr/TokenStreamRecognitionException.hpp"");
  810. println("#include "antlr/CharStreamException.hpp"");
  811. println("#include "antlr/CharStreamIOException.hpp"");
  812. println("#include "antlr/NoViableAltForCharException.hpp"");
  813. if (grammar.debuggingOutput)
  814. println("#include "antlr/DebuggingInputBuffer.hpp"");
  815. println("");
  816. println((String)behavior.headerActions.get(postIncludeCpp));
  817. if (tool.nameSpace != null)
  818. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  819. // Generate user-defined lexer file preamble
  820. println(grammar.preambleAction);
  821. // Generate lexer class definition
  822. String sup=null;
  823. if ( grammar.superClass!=null ) {
  824. sup = grammar.superClass;
  825. }
  826. else {
  827. sup = grammar.getSuperClass();
  828. if (sup.lastIndexOf('.') != -1)
  829. sup = sup.substring(sup.lastIndexOf('.')+1);
  830. sup = namespaceAntlr + sup;
  831. }
  832. //
  833. // Generate the constructor from InputStream
  834. //
  835. println(grammar.getClassName() + "::" + grammar.getClassName() + "(" + namespaceStd + "istream& in)");
  836. tabs++;
  837. // if debugging, wrap the input buffer in a debugger
  838. if (grammar.debuggingOutput)
  839. println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(new "+namespaceAntlr+"CharBuffer(in)))");
  840. else
  841. println(": " + sup + "(new "+namespaceAntlr+"CharBuffer(in))");
  842. tabs--;
  843. println("{");
  844. tabs++;
  845. // if debugging, set up array variables and call user-overridable
  846. //   debugging setup method
  847. if ( grammar.debuggingOutput ) {
  848. println("setRuleNames(_ruleNames);");
  849. println("setSemPredNames(_semPredNames);");
  850. println("setupDebugging();");
  851. }
  852. println("setCaseSensitive("+g.caseSensitive+");");
  853. println("initLiterals();");
  854. tabs--;
  855. println("}");
  856. println("");
  857. // Generate the constructor from InputBuffer
  858. println(grammar.getClassName() + "::" + grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib)");
  859. tabs++;
  860. // if debugging, wrap the input buffer in a debugger
  861. if (grammar.debuggingOutput)
  862. println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(ib))");
  863. else
  864. println(": " + sup + "(ib)");
  865. tabs--;
  866. println("{");
  867. tabs++;
  868. // if debugging, set up array variables and call user-overridable
  869. //   debugging setup method
  870. if ( grammar.debuggingOutput ) {
  871. println("setRuleNames(_ruleNames);");
  872. println("setSemPredNames(_semPredNames);");
  873. println("setupDebugging();");
  874. }
  875. println("setCaseSensitive("+g.caseSensitive+");");
  876. println("initLiterals();");
  877. tabs--;
  878. println("}");
  879. println("");
  880. // Generate the constructor from LexerSharedInputState
  881. println(grammar.getClassName() + "::" + grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state)");
  882. tabs++;
  883. println(": " + sup + "(state)");
  884. tabs--;
  885. println("{");
  886. tabs++;
  887. // if debugging, set up array variables and call user-overridable
  888. //   debugging setup method
  889. if ( grammar.debuggingOutput ) {
  890. println("setRuleNames(_ruleNames);");
  891. println("setSemPredNames(_semPredNames);");
  892. println("setupDebugging();");
  893. }
  894. println("setCaseSensitive("+g.caseSensitive+");");
  895. println("initLiterals();");
  896. tabs--;
  897. println("}");
  898. println("");
  899. println("void " + grammar.getClassName() + "::initLiterals()");
  900. println("{");
  901. tabs++;
  902. // Generate the initialization of the map
  903. // containing the string literals used in the lexer
  904. // The literals variable itself is in CharScanner
  905. /* TJP: get keys now and check to make sure it's a literal not
  906.  * a label to a literal; was dup'ing string literals before
  907.  * change.
  908.  *
  909. Enumeration ids = grammar.tokenManager.getTokenSymbolElements();
  910. while ( ids.hasMoreElements() ) {
  911. TokenSymbol sym = (TokenSymbol)ids.nextElement();
  912. if ( sym instanceof StringLiteralSymbol ) {
  913. StringLiteralSymbol s = (StringLiteralSymbol)sym;
  914. println("literals["+s.getId()+"] = "+s.getTokenType()+";");
  915. }
  916. }
  917. */
  918. // TJP changed it to following loop.
  919. Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
  920. while ( keys.hasMoreElements() ) {
  921. String key = (String)keys.nextElement();
  922. if ( key.charAt(0) != '"' ) {
  923. continue;
  924. }
  925. TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
  926. if ( sym instanceof StringLiteralSymbol ) {
  927. StringLiteralSymbol s = (StringLiteralSymbol)sym;
  928. println("literals["+s.getId()+"] = "+s.getTokenType()+";");
  929. }
  930. }
  931. // Generate the setting of various generated options.
  932. tabs--;
  933. println("}");
  934. // Generate getCaseSensitiveLiterals() method
  935. println("bool " + grammar.getClassName() + "::getCaseSensitiveLiterals() const");
  936. println("{");
  937. tabs++;
  938. println("return "+g.caseSensitiveLiterals + ";");
  939. tabs--;
  940. println("}");
  941. Enumeration ids;
  942. // generate the rule name array for debugging
  943. if (grammar.debuggingOutput) {
  944. println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
  945. tabs++;
  946. ids = grammar.rules.elements();
  947. int ruleNum=0;
  948. while ( ids.hasMoreElements() ) {
  949. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  950. if ( sym instanceof RuleSymbol)
  951. println("""+((RuleSymbol)sym).getId()+"",");
  952. }
  953. println("0");
  954. tabs--;
  955. println("};");
  956. }
  957. // Generate nextToken() rule.
  958. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  959. // user-defined lexer rules.
  960. genNextToken();
  961. // Generate code for each rule in the lexer
  962. ids = grammar.rules.elements();
  963. int ruleNum=0;
  964. while ( ids.hasMoreElements() ) {
  965. RuleSymbol sym = (RuleSymbol) ids.nextElement();
  966. // Don't generate the synthetic rules
  967. if (!sym.getId().equals("mnextToken")) {
  968. genRule(sym, false, ruleNum++, grammar.getClassName() + "::");
  969. }
  970. exitIfError();
  971. }
  972. // Generate the semantic predicate map for debugging
  973. if (grammar.debuggingOutput)
  974. genSemPredMap(grammar.getClassName() + "::");
  975. // Generate the bitsets used throughout the lexer
  976. genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size(), grammar.getClassName() + "::");
  977. println("");
  978. if (tool.nameSpace != null)
  979. println("ANTLR_END_NAMESPACE");
  980. // Close the lexer output stream
  981. currentOutput.close();
  982. currentOutput = null;
  983. }
  984. public void genBody(ParserGrammar g) throws IOException {
  985. // Open the output stream for the parser and set the currentOutput
  986. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".cpp");
  987. //SAS: changed for proper text file io
  988. genAST = grammar.buildAST;
  989. tabs = 0;
  990. // Generate the header common to all output files.
  991. genHeader(grammar.getClassName() + ".cpp");
  992. println((String)behavior.headerActions.get(preIncludeCpp));
  993. // Generate header for the parser
  994. println("#include "" + grammar.getClassName() + ".hpp"");
  995. println("#include "antlr/NoViableAltException.hpp"");
  996. println("#include "antlr/SemanticException.hpp"");
  997. println((String)behavior.headerActions.get(postIncludeCpp));
  998. if (tool.nameSpace != null)
  999. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  1000. // Output the user-defined parser preamble
  1001. println(grammar.preambleAction);
  1002. String sup=null;
  1003. if ( grammar.superClass!=null )
  1004. sup = grammar.superClass;
  1005. else {
  1006. sup = grammar.getSuperClass();
  1007. if (sup.lastIndexOf('.') != -1)
  1008. sup = sup.substring(sup.lastIndexOf('.')+1);
  1009. sup = namespaceAntlr + sup;
  1010. }
  1011. // set up an array of all the rule names so the debugger can
  1012. // keep track of them only by number -- less to store in tree...
  1013. if (grammar.debuggingOutput) {
  1014. println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
  1015. tabs++;
  1016. Enumeration ids = grammar.rules.elements();
  1017. int ruleNum=0;
  1018. while ( ids.hasMoreElements() ) {
  1019. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1020. if ( sym instanceof RuleSymbol)
  1021. println("""+((RuleSymbol)sym).getId()+"",");
  1022. }
  1023. println("0");
  1024. tabs--;
  1025. println("};");
  1026. }
  1027. // Generate parser class constructor from TokenBuffer
  1028. print(grammar.getClassName() + "::" + grammar.getClassName());
  1029. println("("+namespaceAntlr+"TokenBuffer& tokenBuf, int k)");
  1030. println(": " + sup + "(tokenBuf,k)");
  1031. println("{");
  1032. tabs++;
  1033. println("setTokenNames(_tokenNames);");
  1034. // if debugging, set up arrays and call the user-overridable
  1035. //   debugging setup method
  1036. if ( grammar.debuggingOutput ) {
  1037. println("setRuleNames(_ruleNames);");
  1038. println("setSemPredNames(_semPredNames);");
  1039. println("setupDebugging();");
  1040. }
  1041. tabs--;
  1042. println("}");
  1043. println("");
  1044. print(grammar.getClassName() + "::" + grammar.getClassName());
  1045. println("("+namespaceAntlr+"TokenBuffer& tokenBuf)");
  1046. println(": " + sup + "(tokenBuf," + grammar.maxk + ")");
  1047. println("{");
  1048. tabs++;
  1049. println("setTokenNames(_tokenNames);");
  1050. // if debugging, set up arrays and call the user-overridable
  1051. //   debugging setup method
  1052. if ( grammar.debuggingOutput ) {
  1053. println("setRuleNames(_ruleNames);");
  1054. println("setSemPredNames(_semPredNames);");
  1055. println("setupDebugging();");
  1056. }
  1057. tabs--;
  1058. println("}");
  1059. println("");
  1060. // Generate parser class constructor from TokenStream
  1061. print(grammar.getClassName() + "::" + grammar.getClassName());
  1062. println("("+namespaceAntlr+"TokenStream& lexer, int k)");
  1063. println(": " + sup + "(lexer,k)");
  1064. println("{");
  1065. tabs++;
  1066. println("setTokenNames(_tokenNames);");
  1067. // if debugging, set up arrays and call the user-overridable
  1068. //   debugging setup method
  1069. if ( grammar.debuggingOutput ) {
  1070. println("setRuleNames(_ruleNames);");
  1071. println("setSemPredNames(_semPredNames);");
  1072. println("setupDebugging(&lexer);");
  1073. }
  1074. tabs--;
  1075. println("}");
  1076. println("");
  1077. print(grammar.getClassName() + "::" + grammar.getClassName());
  1078. println("("+namespaceAntlr+"TokenStream& lexer)");
  1079. println(": " + sup + "(lexer," + grammar.maxk + ")");
  1080. println("{");
  1081. tabs++;
  1082. println("setTokenNames(_tokenNames);");
  1083. // if debugging, set up arrays and call the user-overridable
  1084. //   debugging setup method
  1085. if ( grammar.debuggingOutput ) {
  1086. println("setRuleNames(_ruleNames);");
  1087. println("setSemPredNames(_semPredNames);");
  1088. println("setupDebugging(&lexer);");
  1089. }
  1090. tabs--;
  1091. println("}");
  1092. println("");
  1093. print(grammar.getClassName() + "::" + grammar.getClassName());
  1094. println("(const "+namespaceAntlr+"ParserSharedInputState& state)");
  1095. println(": " + sup + "(state," + grammar.maxk + ")");
  1096. println("{");
  1097. tabs++;
  1098. println("setTokenNames(_tokenNames);");
  1099. // if debugging, set up arrays and call the user-overridable
  1100. //   debugging setup method
  1101. if ( grammar.debuggingOutput ) {
  1102. println("setRuleNames(_ruleNames);");
  1103. println("setSemPredNames(_semPredNames);");
  1104. println("setupDebugging(&lexer);");
  1105. }
  1106. tabs--;
  1107. println("}");
  1108. println("");
  1109. // Generate code for each rule in the grammar
  1110. Enumeration ids = grammar.rules.elements();
  1111. int ruleNum=0;
  1112. while ( ids.hasMoreElements() ) {
  1113. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1114. if ( sym instanceof RuleSymbol) {
  1115. RuleSymbol rs = (RuleSymbol)sym;
  1116. genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
  1117. }
  1118. exitIfError();
  1119. }
  1120. // Generate the token names
  1121. genTokenStrings(grammar.getClassName() + "::");
  1122. // Generate the bitsets used throughout the grammar
  1123. genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::");
  1124. // Generate the semantic predicate map for debugging
  1125. if (grammar.debuggingOutput)
  1126. genSemPredMap(grammar.getClassName() + "::");
  1127. // Close class definition
  1128. println("");
  1129. println("");
  1130. if (tool.nameSpace != null)
  1131. println("ANTLR_END_NAMESPACE");
  1132. // Close the parser output stream
  1133. currentOutput.close();
  1134. currentOutput = null;
  1135. }
  1136. public void genBody(TreeWalkerGrammar g) throws IOException {
  1137. // Open the output stream for the parser and set the currentOutput
  1138. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".cpp");
  1139. //SAS: changed for proper text file io
  1140. genAST = grammar.buildAST;
  1141. tabs = 0;
  1142. // Generate the header common to all output files.
  1143. genHeader(grammar.getClassName() + ".cpp");
  1144. println((String)behavior.headerActions.get(preIncludeCpp));
  1145. // Generate header for the parser
  1146. println("#include "" + grammar.getClassName() + ".hpp"");
  1147. println("#include "antlr/Token.hpp"");
  1148. println("#include "antlr/AST.hpp"");
  1149. // println("#include "antlr/ParserException.hpp"");
  1150. println("#include "antlr/NoViableAltException.hpp"");
  1151. println("#include "antlr/MismatchedTokenException.hpp"");
  1152. println("#include "antlr/SemanticException.hpp"");
  1153. println("#include "antlr/BitSet.hpp"");
  1154. println((String)behavior.headerActions.get(postIncludeCpp));
  1155. if (tool.nameSpace != null)
  1156. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  1157. // Output the user-defined parser premamble
  1158. println(grammar.preambleAction);
  1159. // Generate parser class definition
  1160. String sup=null;
  1161. if ( grammar.superClass!=null ) {
  1162. sup = grammar.superClass;
  1163. }
  1164. else {
  1165. sup = grammar.getSuperClass();
  1166. if (sup.lastIndexOf('.') != -1)
  1167. sup = sup.substring(sup.lastIndexOf('.')+1);
  1168. sup = namespaceAntlr + sup;
  1169. }
  1170. // Generate default parser class constructor
  1171. println(grammar.getClassName() + "::" + grammar.getClassName() + "() {");
  1172. tabs++;
  1173. println("setTokenNames(_tokenNames);");
  1174. tabs--;
  1175. println("}");
  1176. println("");
  1177. // Generate code for each rule in the grammar
  1178. Enumeration ids = grammar.rules.elements();
  1179. int ruleNum=0;
  1180. String ruleNameInits = "";
  1181. while ( ids.hasMoreElements() ) {
  1182. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1183. if ( sym instanceof RuleSymbol) {
  1184. RuleSymbol rs = (RuleSymbol)sym;
  1185. genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
  1186. }
  1187. exitIfError();
  1188. }
  1189. // Generate the token names
  1190. genTokenStrings(grammar.getClassName() + "::");
  1191. // Generate the bitsets used throughout the grammar
  1192. genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::");
  1193. // Close class definition
  1194. println("");
  1195. println("");
  1196. if (tool.nameSpace != null)
  1197. println("ANTLR_END_NAMESPACE");
  1198. // Close the parser output stream
  1199. currentOutput.close();
  1200. currentOutput = null;
  1201. }
  1202. /** Generate a series of case statements that implement a BitSet test.
  1203.  * @param p The Bitset for which cases are to be generated
  1204.  */
  1205. protected void genCases(BitSet p) {
  1206. if ( DEBUG_CODE_GENERATOR ) System.out.println("genCases("+p+")");
  1207. int[] elems;
  1208. elems = p.toArray();
  1209. // Wrap cases four-per-line for lexer, one-per-line for parser
  1210. int wrap = 1; //(grammar instanceof LexerGrammar) ? 4 : 1;
  1211. int j=1;
  1212. boolean startOfLine = true;
  1213. for (int i = 0; i < elems.length; i++) {
  1214. if (j==1) {
  1215. print("");
  1216. } else {
  1217. _print("  ");
  1218. }
  1219. _print("case " + getValueString(elems[i]) + ":");
  1220. if (j==wrap) {
  1221. _println(""); 
  1222. startOfLine = true;
  1223. j=1;
  1224. }
  1225. else {
  1226. j++;
  1227. startOfLine = false;
  1228. }
  1229. }
  1230. if (!startOfLine) {
  1231. _println("");
  1232. }
  1233. }
  1234. /**Generate common code for a block of alternatives; return a postscript
  1235.  * that needs to be generated at the end of the block.  Other routines
  1236.  * may append else-clauses and such for error checking before the postfix
  1237.  * is generated.
  1238.  * If the grammar is a lexer, then generate alternatives in an order where 
  1239.  * alternatives requiring deeper lookahead are generated first, and 
  1240.  * EOF in the lookahead set reduces the depth of the lookahead.
  1241.  * @param blk The block to generate
  1242.  * @param noTestForSingle If true, then it does not generate a test for a single alternative.
  1243.  */
  1244. public CppBlockFinishingInfo genCommonBlock(
  1245. AlternativeBlock blk,
  1246. boolean noTestForSingle)
  1247. {
  1248. int nIF=0;
  1249. boolean createdLL1Switch = false;
  1250. int closingBracesOfIFSequence = 0;
  1251. CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
  1252. if ( DEBUG_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");
  1253. // Save the AST generation state, and set it to that of the block
  1254. boolean savegenAST = genAST;
  1255. genAST = genAST && blk.getAutoGen();
  1256. boolean oldsaveTest = saveText;
  1257. saveText = saveText && blk.getAutoGen();
  1258. // Is this block inverted?  If so, generate special-case code
  1259. if (
  1260. blk.not &&
  1261. analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar)
  1262. ) {
  1263. Lookahead p = analyzer.look(1, blk);
  1264. // Variable assignment for labeled elements
  1265. if (blk.getLabel() != null && syntacticPredLevel == 0) {
  1266. println(blk.getLabel() + " = " + lt1Value + ";");
  1267. }
  1268. // AST
  1269. genElementAST(blk);
  1270. String astArgs="";
  1271. if (grammar instanceof TreeWalkerGrammar) {
  1272. astArgs="_t,";
  1273. }
  1274. // match the bitset for the alternative
  1275. println("match(" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ");");
  1276. // tack on tree cursor motion if doing a tree walker
  1277. if (grammar instanceof TreeWalkerGrammar) {
  1278. println("_t = _t->getNextSibling();");
  1279. }
  1280. return finishingInfo;
  1281. }
  1282. // Special handling for single alt
  1283. if (blk.getAlternatives().size() == 1) {
  1284. Alternative alt = blk.getAlternativeAt(0);
  1285. // Generate a warning if there is a synPred for single alt.
  1286. if (alt.synPred != null)
  1287. {
  1288. tool.warning(
  1289. "Syntactic predicate superfluous for single alternative",
  1290. grammar.getFilename(), 
  1291. blk.getAlternativeAt(0).synPred.getLine()
  1292. );
  1293. }
  1294. if (noTestForSingle) {
  1295. if (alt.semPred != null) {
  1296. // Generate validating predicate
  1297. genSemPred(alt.semPred, blk.line);
  1298. }
  1299. genAlt(alt, blk);
  1300. return finishingInfo;
  1301. }
  1302. }
  1303. // count number of simple LL(1) cases; only do switch for
  1304. // many LL(1) cases (no preds, no end of token refs)
  1305. // We don't care about exit paths for (...)*, (...)+
  1306. // because we don't explicitly have a test for them
  1307. // as an alt in the loop.
  1308. int nLL1 = 0;
  1309. for (int i=0; i<blk.getAlternatives().size(); i++) {
  1310. Alternative a = blk.getAlternativeAt(i);
  1311. if ( a.lookaheadDepth == 1 && a.semPred == null &&
  1312.   !a.cache[1].containsEpsilon()) {
  1313. nLL1++;
  1314. }
  1315. }
  1316. // do LL(1) cases
  1317. if ( nLL1 >= makeSwitchThreshold) {
  1318. // Determine the name of the item to be compared
  1319. String testExpr = lookaheadString(1);
  1320. createdLL1Switch = true;
  1321. // when parsing trees, convert null to valid tree node with NULL lookahead
  1322. if ( grammar instanceof TreeWalkerGrammar ) {
  1323. println("if (_t=="+namespaceAntlr+"nullAST) _t=ASTNULL;");
  1324. }
  1325. println("switch ( "+testExpr+") {");
  1326. for (int i=0; i<blk.alternatives.size(); i++) {
  1327. Alternative alt = blk.getAlternativeAt(i);
  1328. // ignore any non-LL(1) alts, predicated alts or end-of-token alts
  1329. if ( alt.lookaheadDepth!=1 || alt.semPred != null ||
  1330.   alt.cache[1].containsEpsilon() ) {
  1331. continue;
  1332. }
  1333. Lookahead p = alt.cache[1];
  1334. if (p.fset.degree() == 0 && !p.containsEpsilon()) {
  1335. tool.warning("Alternate omitted due to empty prediction set",
  1336. grammar.getFilename(),
  1337. alt.head.getLine());
  1338. }
  1339. else {
  1340. genCases(p.fset);
  1341. println("{");
  1342. tabs++;
  1343. genAlt(alt, blk);
  1344. println("break;");
  1345. tabs--;
  1346. println("}");
  1347. }
  1348. }
  1349. println("default:");
  1350. tabs++;
  1351. }
  1352. // do non-LL(1) and nondeterministic cases
  1353. // This is tricky in the lexer, because of cases like:
  1354. //     STAR : '*' ;
  1355. //     ASSIGN_STAR : "*=";
  1356. // Since nextToken is generated without a loop, then the STAR will
  1357. // have end-of-token as it's lookahead set for LA(2).  So, we must generate the
  1358. // alternatives containing trailing end-of-token in their lookahead sets *after*
  1359. // the alternatives without end-of-token.  This implements the usual
  1360. // lexer convention that longer matches come before shorter ones, e.g.
  1361. // "*=" matches ASSIGN_STAR not STAR
  1362. //
  1363. // For non-lexer grammars, this does not sort the alternates by depth
  1364. // Note that alts whose lookahead is purely end-of-token at k=1 end up
  1365. // as default or else clauses.
  1366. int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
  1367. for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
  1368. if ( DEBUG_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
  1369. for (int i=0; i<blk.alternatives.size(); i++) {
  1370. Alternative alt = blk.getAlternativeAt(i);
  1371. if ( DEBUG_CODE_GENERATOR ) System.out.println("genAlt: "+i);
  1372. // if we made a switch above, ignore what we already took care
  1373. // of.  Specifically, LL(1) alts with no preds
  1374. // that do not have end-of-token in their prediction set
  1375. if ( createdLL1Switch &&
  1376.   (alt.lookaheadDepth==1 && alt.semPred == null &&
  1377.    !alt.cache[1].containsEpsilon()) ) {
  1378. if ( DEBUG_CODE_GENERATOR ) System.out.println("ignoring alt because it was in the switch");
  1379. continue;
  1380. }
  1381. String e;
  1382. boolean unpredicted = false;
  1383. if (grammar instanceof LexerGrammar) {
  1384. // Calculate the "effective depth" of the alt, which is the max
  1385. // depth at which cache[depth]!=end-of-token
  1386. int effectiveDepth = alt.lookaheadDepth;
  1387. if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC) {
  1388. // use maximum lookahead
  1389. effectiveDepth = grammar.maxk;
  1390. }
  1391. while (
  1392. effectiveDepth >= 1 &&
  1393. alt.cache[effectiveDepth].containsEpsilon()
  1394. {
  1395. effectiveDepth--;
  1396. }
  1397. // Ignore alts whose effective depth is other than the ones we
  1398. // are generating for this iteration.
  1399. if (effectiveDepth != altDepth) {
  1400. if ( DEBUG_CODE_GENERATOR )
  1401. System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
  1402. continue;
  1403. }
  1404. unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
  1405. e = getLookaheadTestExpression(alt, effectiveDepth);
  1406. } else {
  1407. unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
  1408. e = getLookaheadTestExpression(alt, grammar.maxk);
  1409. }
  1410. if (unpredicted && alt.semPred==null && alt.synPred==null) {
  1411. // The alt has empty prediction set and no predicate to help out.
  1412. // if we have not generated
  1413. // a previous if, just put {...} around the end-of-token clause
  1414. if ( nIF==0 ) {
  1415. println("{");
  1416. }
  1417. else {
  1418. println("else {");
  1419. }
  1420. finishingInfo.needAnErrorClause = false;
  1421. // continue;
  1422. }
  1423. else { // check for sem and syn preds
  1424. // Add any semantic predicate expression to the lookahead test
  1425. if ( alt.semPred != null ) {
  1426. // if debugging, wrap the evaluation of the predicate in a method
  1427. // translate $ and # references
  1428. ActionTransInfo tInfo = new ActionTransInfo();
  1429. String actionStr = processActionForTreeSpecifiers(alt.semPred,
  1430.   blk.line,
  1431.   currentRule,
  1432.   tInfo);
  1433. // ignore translation info...we don't need to do anything with it.
  1434. // call that will inform SemanticPredicateListeners of the result
  1435. if (((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar)) && grammar.debuggingOutput)
  1436. e = "("+e+"&& fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
  1437. addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
  1438. else
  1439. e = "("+e+"&&("+actionStr +"))";
  1440. }
  1441. // Generate any syntactic predicates
  1442. if ( nIF>0 ) {
  1443. if ( alt.synPred != null ) {
  1444. println("else {");
  1445. tabs++;
  1446. genSynPred( alt.synPred, e );
  1447. closingBracesOfIFSequence++;
  1448. }
  1449. else {
  1450. println("else if " + e + " {");
  1451. }
  1452. }
  1453. else {
  1454. if ( alt.synPred != null ) {
  1455. genSynPred( alt.synPred, e );
  1456. }
  1457. else {
  1458. // when parsing trees, convert null to valid tree node
  1459. // with NULL lookahead.
  1460. if ( grammar instanceof TreeWalkerGrammar ) {
  1461. println("if (_t=="+namespaceAntlr+"nullAST) _t=ASTNULL;");
  1462. }
  1463. println("if " + e + " {");
  1464. }
  1465. }
  1466. }
  1467. nIF++;
  1468. tabs++;
  1469. genAlt(alt, blk);
  1470. tabs--;
  1471. println("}");
  1472. }
  1473. }
  1474. String ps = "";
  1475. for (int i=1; i<=closingBracesOfIFSequence; i++) {
  1476. tabs--; // does JavaCodeGenerator need this?
  1477. ps+="}";
  1478. }
  1479. // Restore the AST generation state
  1480. genAST = savegenAST;
  1481. // restore save text state
  1482. saveText=oldsaveTest;
  1483. // Return the finishing info.
  1484. if ( createdLL1Switch ) {
  1485. tabs--;
  1486. finishingInfo.postscript = ps+"}";
  1487. finishingInfo.generatedSwitch = true;
  1488. finishingInfo.generatedAnIf = nIF>0;
  1489. //return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement
  1490. }
  1491. else {
  1492. finishingInfo.postscript = ps;
  1493. finishingInfo.generatedSwitch = false;
  1494. finishingInfo.generatedAnIf = nIF>0;
  1495. //return new CppBlockFinishingInfo(ps, false,nIF>0);
  1496. }
  1497. return finishingInfo;
  1498. }
  1499. /** Generate code to link an element reference into the AST */
  1500. private void genElementAST(AlternativeElement el) {
  1501. // handle case where you're not building trees, but are in tree walker.
  1502. // Just need to get labels set up.
  1503. if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST ) {
  1504. String elementRef;
  1505. String astName;
  1506. // Generate names and declarations of the AST variable(s)
  1507. if (el.getLabel() == null) {
  1508. elementRef = lt1Value;
  1509. // Generate AST variables for unlabeled stuff
  1510. astName = "tmp" + astVarNumber + "_AST";
  1511. astVarNumber++;
  1512. // Map the generated AST variable in the alternate
  1513. mapTreeVariable(el, astName);
  1514. // Generate an "input" AST variable also
  1515. println(labeledElementASTType+" "+astName+"_in = "+elementRef+";");
  1516. }
  1517. return;
  1518. }
  1519. if (grammar.buildAST && syntacticPredLevel == 0) {
  1520. boolean doNoGuessTest = (
  1521. grammar.hasSyntacticPredicate &&
  1522. (
  1523. el.getLabel() != null ||
  1524. el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG
  1525. )
  1526. );
  1527. String elementRef;
  1528. String astName;
  1529. // Generate names and declarations of the AST variable(s)
  1530. if (el.getLabel() != null) {
  1531. elementRef = el.getLabel();
  1532. astName = el.getLabel() + "_AST";
  1533. } else {
  1534. elementRef = lt1Value;
  1535. // Generate AST variables for unlabeled stuff
  1536. astName = "tmp" + astVarNumber + "_AST";
  1537. astVarNumber++;
  1538. // Generate the declaration (can only build ASTs for atoms)
  1539. GrammarAtom ga = (GrammarAtom)el;
  1540. if ( ga.getASTNodeType()!=null ) {
  1541. // println(ga.getASTNodeType()+" " + astName + " = "+namespaceAntlr+"nullAST;");
  1542. println("Ref"+ga.getASTNodeType()+" " + astName + ";");
  1543. }
  1544. else {
  1545. println(labeledElementASTType+" " + astName + " = "+namespaceAntlr+"nullAST;");
  1546. }
  1547. // Map the generated AST variable in the alternate
  1548. mapTreeVariable(el, astName);
  1549. if (grammar instanceof TreeWalkerGrammar) {
  1550. // Generate an "input" AST variable also
  1551. println(labeledElementASTType+" " + astName + "_in = "+namespaceAntlr+"nullAST;");
  1552. }
  1553. }
  1554. // Enclose actions with !guessing
  1555. if (doNoGuessTest) {
  1556. println("if (inputState->guessing==0) {"); 
  1557. tabs++;
  1558. }
  1559. if (el.getLabel() != null) {
  1560. println(astName + " = "+
  1561. getASTCreateString((GrammarAtom)el,elementRef) + ";");
  1562. } else {
  1563. elementRef = lt1Value;
  1564. println(astName + " = "+
  1565. getASTCreateString((GrammarAtom)el,elementRef) + ";");
  1566. // Map the generated AST variable in the alternate
  1567. if (grammar instanceof TreeWalkerGrammar) {
  1568. // set "input" AST variable also
  1569. println(astName + "_in = " + elementRef + ";");
  1570. }
  1571. }
  1572. if (genAST) {
  1573. switch (el.getAutoGenType()) {
  1574. case GrammarElement.AUTO_GEN_NONE:
  1575. println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
  1576. break;
  1577. case GrammarElement.AUTO_GEN_CARET:
  1578. // println("astFactory.makeASTRoot(currentAST, " + astName + ");");
  1579. println("astFactory.makeASTRoot(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
  1580. break;
  1581. default:
  1582. break;
  1583. }
  1584. }
  1585. if (doNoGuessTest) {
  1586. tabs--;
  1587. println("}");
  1588. }
  1589. }
  1590. }
  1591. /** Close the try block and generate catch phrases 
  1592.  * if the element has a labeled handler in the rule 
  1593.  */
  1594. private void genErrorCatchForElement(AlternativeElement el) {
  1595. if (el.getLabel() == null) return;
  1596. String r = el.enclosingRuleName;
  1597. if ( grammar instanceof LexerGrammar ) {
  1598. r = CodeGenerator.lexerRuleName(el.enclosingRuleName);
  1599. }
  1600. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
  1601. if (rs == null) {
  1602. tool.panic("Enclosing rule not found!");
  1603. }
  1604. ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
  1605. if (ex != null) {
  1606. tabs--;
  1607. println("}");
  1608. genErrorHandler(ex);
  1609. }
  1610. }
  1611. /** Generate the catch phrases for a user-specified error handler */
  1612. private void genErrorHandler(ExceptionSpec ex) {
  1613. // Each ExceptionHandler in the ExceptionSpec is a separate catch
  1614. for (int i = 0; i < ex.handlers.size(); i++)
  1615. {
  1616. ExceptionHandler handler = (ExceptionHandler)ex.handlers.elementAt(i);
  1617. // Generate catch phrase
  1618. println("catch (" + handler.exceptionTypeAndName.getText() + ") {");
  1619. tabs++;
  1620. if (grammar.hasSyntacticPredicate) {
  1621. println("if (inputState->guessing==0) {");
  1622. tabs++;
  1623. }
  1624. // When not guessing, execute user handler action
  1625. printAction(
  1626. processActionForTreeSpecifiers(handler.action, 0, currentRule, null)
  1627. );
  1628. if (grammar.hasSyntacticPredicate) {
  1629. tabs--;
  1630. println("} else {");
  1631. tabs++;
  1632. // When guessing, rethrow exception
  1633. println(
  1634. "throw " + 
  1635. extractIdOfAction(handler.exceptionTypeAndName) + 
  1636. ";"
  1637. );
  1638. tabs--;
  1639. println("}");
  1640. }
  1641. // Close catch phrase
  1642. tabs--;
  1643. println("}");
  1644. }
  1645. }
  1646. /** Generate a try { opening if the element has a labeled handler in the rule */
  1647. private void genErrorTryForElement(AlternativeElement el) {
  1648. if (el.getLabel() == null) return;
  1649. String r = el.enclosingRuleName;
  1650. if ( grammar instanceof LexerGrammar ) {
  1651. r = CodeGenerator.lexerRuleName(el.enclosingRuleName);
  1652. }
  1653. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
  1654. if (rs == null) {
  1655. tool.panic("Enclosing rule not found!");
  1656. }
  1657. ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
  1658. if (ex != null) {
  1659. println("try { // for error handling");
  1660. tabs++;
  1661. }
  1662. }
  1663. /** Generate a header that is common to all C++ files */
  1664. protected void genHeader(String fileName) 
  1665. {
  1666. println("/* $ANTLR "+Tool.version+": "+
  1667. """+Tool.fileMinusPath(tool.grammarFile)+"""+
  1668. " -> "+
  1669. """+fileName+""$ */");
  1670. }
  1671. // these are unique to C++ mode
  1672. public void genInclude(LexerGrammar g) throws IOException {
  1673. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".hpp");
  1674. //SAS: changed for proper text file io
  1675. genAST = false; // no way to gen trees.
  1676. saveText = true; // save consumed characters.
  1677. tabs=0;
  1678. // Generate a guard wrapper
  1679. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  1680. println("#define INC_"+grammar.getClassName()+"_hpp_");
  1681. println("");
  1682. println((String)behavior.headerActions.get(preIncludeHpp));
  1683. println("#include "antlr/config.hpp"");
  1684. // Generate header common to all C++ output files
  1685. genHeader(grammar.getClassName() + ".hpp");
  1686. // Generate header specific to lexer header file
  1687. println("#include "antlr/CommonToken.hpp"");
  1688. println("#include "antlr/InputBuffer.hpp"");
  1689. println("#include "antlr/BitSet.hpp"");
  1690. println("#include "" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp"");
  1691. // Find the name of the super class
  1692. String sup=null;
  1693. if ( grammar.superClass!=null ) {
  1694. sup = grammar.superClass;
  1695. println("#include ""+sup+".hpp"");
  1696. }
  1697. else {
  1698. sup = grammar.getSuperClass();
  1699. if (sup.lastIndexOf('.') != -1)
  1700. sup = sup.substring(sup.lastIndexOf('.')+1);
  1701. println("#include "antlr/"+sup+".hpp"");
  1702. sup = namespaceAntlr + sup;
  1703. }
  1704. // Do not use printAction because we assume tabs==0
  1705. println((String)behavior.headerActions.get(postIncludeHpp));
  1706. if (tool.nameSpace != null)
  1707. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  1708. println((String)behavior.headerActions.get(""));
  1709. // print javadoc comment if any
  1710. if ( grammar.comment!=null ) {
  1711. _println(grammar.comment);
  1712. }
  1713. // Generate lexer class definition
  1714. print("class " + grammar.getClassName() + " : public " + sup);
  1715. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  1716. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  1717. if ( tsuffix != null ) {
  1718. String suffix = Tool.stripFrontBack(tsuffix.getText(),""",""");
  1719. if ( suffix != null ) {
  1720. print(", "+suffix);  // must be an interface name for Java
  1721. }
  1722. }
  1723. println(" {");
  1724. // Generate user-defined lexer class members
  1725. print(
  1726. processActionForTreeSpecifiers(grammar.classMemberAction, 0, currentRule, null)
  1727. );
  1728. // Generate initLiterals() method
  1729. tabs=0;
  1730. println("private:");
  1731. tabs=1;
  1732. println("void initLiterals();");
  1733. // Generate getCaseSensitiveLiterals() method
  1734. tabs=0;
  1735. println("public:");
  1736. tabs=1;
  1737. println("bool getCaseSensitiveLiterals() const;");
  1738. // Make constructors public
  1739. tabs=0;
  1740. println("public:");
  1741. tabs=1;
  1742. // Generate the constructor from std::istream
  1743. println(grammar.getClassName() + "(" + namespaceStd + "istream& in);");
  1744. // Generate the constructor from InputBuffer
  1745. println(grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib);");
  1746. println(grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state);");
  1747. // Generate nextToken() rule.
  1748. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  1749. // user-defined lexer rules.
  1750. println(namespaceAntlr+"RefToken nextToken();");
  1751. // Generate code for each rule in the lexer
  1752. Enumeration ids = grammar.rules.elements();
  1753. while ( ids.hasMoreElements() ) {
  1754. RuleSymbol sym = (RuleSymbol) ids.nextElement();
  1755. // Don't generate the synthetic rules
  1756. if (!sym.getId().equals("mnextToken")) {
  1757. genRuleHeader(sym, false);
  1758. }
  1759. exitIfError();
  1760. }
  1761. // Make the rest private
  1762. tabs=0;
  1763. println("private:");
  1764. tabs=1;
  1765. // generate the rule name array for debugging
  1766. if ( grammar.debuggingOutput ) {
  1767. println("static const char* _ruleNames[];");
  1768. }
  1769. // Generate the semantic predicate map for debugging
  1770. if (grammar.debuggingOutput)
  1771. println("static const char* _semPredNames[];");
  1772. // Generate the bitsets used throughout the lexer
  1773. genBitsetsHeader(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());
  1774. tabs=0;
  1775. println("};");
  1776. println("");
  1777. if (tool.nameSpace != null)
  1778. println("ANTLR_END_NAMESPACE");
  1779. // Generate a guard wrapper
  1780. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  1781. // Close the lexer output stream
  1782. currentOutput.close();
  1783. currentOutput = null;
  1784. }
  1785. public void genInclude(ParserGrammar g) throws IOException {
  1786. // Open the output stream for the parser and set the currentOutput
  1787. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".hpp");
  1788. //SAS: changed for proper text file io
  1789. genAST = grammar.buildAST;
  1790. tabs = 0;
  1791. // Generate a guard wrapper
  1792. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  1793. println("#define INC_"+grammar.getClassName()+"_hpp_");
  1794. println("");
  1795. println((String)behavior.headerActions.get(preIncludeHpp));
  1796. println("#include "antlr/config.hpp"");
  1797. // Generate the header common to all output files.
  1798. genHeader(grammar.getClassName() + ".hpp");
  1799. // Generate header for the parser
  1800. println("#include "antlr/TokenStream.hpp"");
  1801. println("#include "antlr/TokenBuffer.hpp"");
  1802. println("#include "" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp"");
  1803. // Generate parser class definition
  1804. String sup=null;
  1805. if ( grammar.superClass!=null ) {
  1806. sup = grammar.superClass;
  1807. println("#include ""+sup+".hpp"");
  1808. }
  1809. else {
  1810. sup = grammar.getSuperClass();
  1811. if (sup.lastIndexOf('.') != -1)
  1812. sup = sup.substring(sup.lastIndexOf('.')+1);
  1813. println("#include "antlr/"+sup+".hpp"");
  1814. sup = namespaceAntlr + sup;
  1815. }
  1816. println("");
  1817. // Do not use printAction because we assume tabs==0
  1818. println((String)behavior.headerActions.get(postIncludeHpp));
  1819. if (tool.nameSpace != null)
  1820. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  1821. println((String)behavior.headerActions.get(""));
  1822. // print javadoc comment if any
  1823. if ( grammar.comment!=null ) {
  1824. _println(grammar.comment);
  1825. }
  1826. print("class " + grammar.getClassName() + " : public " + sup);
  1827. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  1828. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  1829. if ( tsuffix != null ) {
  1830. String suffix = Tool.stripFrontBack(tsuffix.getText(),""",""");
  1831. if ( suffix != null )
  1832. print(", "+suffix);  // must be an interface name for Java
  1833. }
  1834. println(" {");
  1835. // set up an array of all the rule names so the debugger can
  1836. // keep track of them only by number -- less to store in tree...
  1837. if (grammar.debuggingOutput) {
  1838. println("public: static const char* _ruleNames[];");
  1839. }
  1840. // Generate user-defined parser class members
  1841. print(
  1842. processActionForTreeSpecifiers(grammar.classMemberAction, 0, currentRule, null)
  1843. );
  1844. // Generate parser class constructor from TokenBuffer
  1845. tabs=0;
  1846. println("protected:");
  1847. tabs=1;
  1848. println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf, int k);");
  1849. tabs=0;
  1850. println("public:");
  1851. tabs=1;
  1852. println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf);");
  1853. // Generate parser class constructor from TokenStream
  1854. tabs=0;
  1855. println("protected:");
  1856. tabs=1;
  1857. println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer, int k);");
  1858. tabs=0;
  1859. println("public:");
  1860. tabs=1;
  1861. println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer);");
  1862. println(grammar.getClassName()+"(const "+namespaceAntlr+"ParserSharedInputState& state);");
  1863. // Generate code for each rule in the grammar
  1864. Enumeration ids = grammar.rules.elements();
  1865. while ( ids.hasMoreElements() ) {
  1866. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1867. if ( sym instanceof RuleSymbol) {
  1868. RuleSymbol rs = (RuleSymbol)sym;
  1869. genRuleHeader(rs, rs.references.size()==0);
  1870. }
  1871. exitIfError();
  1872. }
  1873. // Make the rest private
  1874. tabs=0;
  1875. println("private:");
  1876. tabs=1;
  1877. // Generate the token names
  1878. println("static const char* _tokenNames[];");
  1879. // Generate the bitsets used throughout the grammar
  1880. genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
  1881. // Generate the semantic predicate map for debugging
  1882. if (grammar.debuggingOutput)
  1883. println("static const char* _semPredNames[];");
  1884. // Close class definition
  1885. tabs=0;
  1886. println("};");
  1887. println("");
  1888. if (tool.nameSpace != null)
  1889. println("ANTLR_END_NAMESPACE");
  1890. // Generate a guard wrapper
  1891. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  1892. // Close the parser output stream
  1893. currentOutput.close();
  1894. currentOutput = null;
  1895. }
  1896. public void genInclude(TreeWalkerGrammar g) throws IOException {
  1897. // Open the output stream for the parser and set the currentOutput
  1898. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + ".hpp");
  1899. //SAS: changed for proper text file io
  1900. genAST = grammar.buildAST;
  1901. tabs = 0;
  1902. // Generate a guard wrapper
  1903. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  1904. println("#define INC_"+grammar.getClassName()+"_hpp_");
  1905. println("");
  1906. println((String)behavior.headerActions.get(preIncludeHpp));
  1907. println("#include "antlr/config.hpp"");
  1908. println("#include "" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp"");
  1909. // Generate the header common to all output files.
  1910. genHeader(grammar.getClassName() + ".hpp");
  1911. // Find the name of the super class
  1912. String sup=null;
  1913. if ( grammar.superClass!=null ) {
  1914. sup = grammar.superClass;
  1915. println("#include ""+sup+".hpp"");
  1916. }
  1917. else {
  1918. sup = grammar.getSuperClass();
  1919. if (sup.lastIndexOf('.') != -1)
  1920. sup = sup.substring(sup.lastIndexOf('.')+1);
  1921. println("#include "antlr/"+sup+".hpp"");
  1922. sup = namespaceAntlr + sup;
  1923. }
  1924. println("");
  1925. // Generate header for the parser
  1926. // Do not use printAction because we assume tabs==0
  1927. println((String)behavior.headerActions.get(postIncludeHpp));
  1928. if (tool.nameSpace != null)
  1929. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  1930. println((String)behavior.headerActions.get(""));
  1931. // print javadoc comment if any
  1932. if ( grammar.comment!=null ) {
  1933. _println(grammar.comment);
  1934. }
  1935. // Generate parser class definition
  1936. print("class " + grammar.getClassName() + " : public "+sup);
  1937. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  1938. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  1939. if ( tsuffix != null ) {
  1940. String suffix = Tool.stripFrontBack(tsuffix.getText(),""",""");
  1941. if ( suffix != null ) {
  1942. print(", "+suffix);  // must be an interface name for Java
  1943. }
  1944. }
  1945. println(" {");
  1946. // Generate user-defined parser class members
  1947. print(
  1948. processActionForTreeSpecifiers(grammar.classMemberAction, 0, currentRule, null)
  1949. );
  1950. // Generate default parser class constructor
  1951. tabs=0;
  1952. println("public:");
  1953. tabs=1;
  1954. println(grammar.getClassName() + "();");
  1955. // Generate code for each rule in the grammar
  1956. Enumeration ids = grammar.rules.elements();
  1957. String ruleNameInits = "";
  1958. while ( ids.hasMoreElements() ) {
  1959. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1960. if ( sym instanceof RuleSymbol) {
  1961. RuleSymbol rs = (RuleSymbol)sym;
  1962. genRuleHeader(rs, rs.references.size()==0);
  1963. }
  1964. exitIfError();
  1965. }
  1966. // Make the rest private
  1967. tabs=0;
  1968. println("private:");
  1969. tabs=1;
  1970. // Generate the token names
  1971. println("static const char* _tokenNames[];");
  1972. // Generate the bitsets used throughout the grammar
  1973. genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
  1974. // Close class definition
  1975. tabs=0;
  1976. println("};");
  1977. println("");
  1978. if (tool.nameSpace != null)
  1979. println("ANTLR_END_NAMESPACE");
  1980. // Generate a guard wrapper
  1981. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  1982. // Close the parser output stream
  1983. currentOutput.close();
  1984. currentOutput = null;
  1985. }
  1986. private void genLiteralsTest() {
  1987. println("_ttype = testLiteralsTable(_ttype);");
  1988. }
  1989. private void genLiteralsTestForPartialToken() {
  1990. println("_ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype);");
  1991. }
  1992. protected void genMatch(BitSet b) {
  1993. }
  1994. protected void genMatch(GrammarAtom atom) {
  1995. if ( atom instanceof StringLiteralElement ) {
  1996. if ( grammar instanceof LexerGrammar ) {
  1997. genMatchUsingAtomText(atom);
  1998. }
  1999. else {
  2000. genMatchUsingAtomTokenType(atom);
  2001. }
  2002. }
  2003. else if ( atom instanceof CharLiteralElement ) {
  2004. if ( grammar instanceof LexerGrammar ) {
  2005. genMatchUsingAtomText(atom);
  2006. }
  2007. else {
  2008. tool.error("cannot ref character literals in grammar: "+atom);
  2009. }
  2010. }
  2011. else if ( atom instanceof TokenRefElement ) {
  2012. genMatchUsingAtomText(atom);
  2013. }
  2014. }
  2015. protected void genMatchUsingAtomText(GrammarAtom atom) {
  2016. // match() for trees needs the _t cursor
  2017. String astArgs="";
  2018. if (grammar instanceof TreeWalkerGrammar) {
  2019. astArgs="_t,";
  2020. }
  2021. // if in lexer and ! on element, save buffer index to kill later
  2022. if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  2023. println("_saveIndex=text.length();");
  2024. }
  2025. print(atom.not ? "matchNot(" : "match(");
  2026. _print(astArgs);
  2027. // print out what to match
  2028. if (atom.atomText.equals("EOF")) {
  2029. // horrible hack to handle EOF case
  2030. _print(namespaceAntlr+"Token::EOF_TYPE");
  2031. else {
  2032. _print(textOrChar(atom.atomText));
  2033. }
  2034. _println(");");
  2035. if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  2036. println("text.erase(_saveIndex);");      // kill text atom put in buffer
  2037. }
  2038. }
  2039. protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
  2040. // match() for trees needs the _t cursor
  2041. String astArgs="";
  2042. if (grammar instanceof TreeWalkerGrammar) {
  2043. astArgs="_t,";
  2044. }
  2045. // If the literal can be mangled, generate the symbolic constant instead
  2046. String mangledName = null;
  2047. String s = astArgs + getValueString(atom.getType());
  2048. // matching
  2049. println( (atom.not ? "matchNot(" : "match(") + s + ");");
  2050. }
  2051. /** Generate the nextToken() rule.
  2052.  * nextToken() is a synthetic lexer rule that is the implicit OR of all
  2053.  * user-defined lexer rules.
  2054.  * @param RuleBlock 
  2055.  */
  2056. public void genNextToken() {
  2057. // Are there any public rules?  If not, then just generate a
  2058. // fake nextToken().
  2059. boolean hasPublicRules = false;
  2060. for (int i = 0; i < grammar.rules.size(); i++) {
  2061. RuleSymbol rs = (RuleSymbol)grammar.rules.elementAt(i);
  2062. if ( rs.isDefined() && rs.access.equals("public") ) {
  2063. hasPublicRules = true;
  2064. break;
  2065. }
  2066. }
  2067. if (!hasPublicRules) {
  2068. println("");
  2069. println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken() { return "+namespaceAntlr+"RefToken(new "+namespaceAntlr+"CommonToken("+namespaceAntlr+"Token::EOF_TYPE, "")); }");
  2070. println("");
  2071. return;
  2072. }
  2073. // Create the synthesized nextToken() rule
  2074. RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
  2075. // Define the nextToken rule symbol
  2076. RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
  2077. nextTokenRs.setDefined();
  2078. nextTokenRs.setBlock(nextTokenBlk);
  2079. nextTokenRs.access = "private";
  2080. grammar.define(nextTokenRs);
  2081. // Analyze the nextToken rule
  2082. boolean ok = grammar.theLLkAnalyzer.deterministic(nextTokenBlk);
  2083. // Generate the next token rule
  2084. String filterRule=null;
  2085. if ( ((LexerGrammar)grammar).filterMode ) {
  2086. filterRule = ((LexerGrammar)grammar).filterRule;
  2087. }
  2088. println("");
  2089. println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken()");
  2090. println("{");
  2091. tabs++;
  2092. println(namespaceAntlr+"RefToken theRetToken;");
  2093. println("for (;;) {");
  2094. tabs++;
  2095. println(namespaceAntlr+"RefToken theRetToken;");
  2096. println("int _ttype = "+namespaceAntlr+"Token::INVALID_TYPE;");
  2097. if ( ((LexerGrammar)grammar).filterMode ) {
  2098. println("setCommitToPath(false);");
  2099. if ( filterRule!=null ) {
  2100. // Here's a good place to ensure that the filter rule actually exists
  2101. if ( !grammar.isDefined(CodeGenerator.lexerRuleName(filterRule)) ) {
  2102. grammar.tool.error("Filter rule "+filterRule+" does not exist in this lexer");
  2103. }
  2104. else {
  2105. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(CodeGenerator.lexerRuleName(filterRule));
  2106. if ( !rs.isDefined() ) {
  2107. grammar.tool.error("Filter rule "+filterRule+" does not exist in this lexer");
  2108. }
  2109. else if ( rs.access.equals("public") ) {
  2110. grammar.tool.error("Filter rule "+filterRule+" must be protected");
  2111. }
  2112. }
  2113. println("int _m;");
  2114. println("_m = mark();");
  2115. }
  2116. }
  2117. println("resetText();");
  2118. println("try {   // for char stream error handling");
  2119. tabs++;
  2120. // Generate try around whole thing to trap scanner errors
  2121. println("try {   // for lexical error handling");
  2122. tabs++;
  2123. // Test for public lexical rules with empty paths
  2124. for (int i=0; i<nextTokenBlk.getAlternatives().size(); i++) {
  2125. Alternative a = nextTokenBlk.getAlternativeAt(i);
  2126. if ( a.cache[1].containsEpsilon() ) {
  2127. tool.warning("found optional path in nextToken()");
  2128. }
  2129. }
  2130. // Generate the block
  2131. String newline = System.getProperty("line.separator");
  2132. CppBlockFinishingInfo howToFinish = genCommonBlock(nextTokenBlk, false);
  2133. String errFinish = "if (LA(1)==EOF_CHAR) {uponEOF(); _returnToken = makeToken("+namespaceAntlr+"Token::EOF_TYPE);}";
  2134. errFinish += newline+"tttt";
  2135. if ( ((LexerGrammar)grammar).filterMode ) {
  2136. if ( filterRule==null ) {
  2137. errFinish += "else {consume(); goto tryAgain;}";
  2138. }
  2139. else {
  2140. errFinish += "else {"+newline+
  2141. "tttttcommit();"+newline+
  2142. "ttttttry {m"+filterRule+"(false);}"+newline+
  2143. "tttttcatch("+namespaceAntlr+"RecognitionException& e) {"+newline+
  2144. "ttttt // catastrophic failure"+newline+
  2145. "ttttt reportError(e);"+newline+
  2146. "ttttt consume();"+newline+
  2147. "ttttt}"+newline+
  2148.   "tttttgoto tryAgain;"+newline+
  2149.   "tttt}";
  2150. }
  2151. }
  2152. else {
  2153. errFinish += "else {"+throwNoViable+"}";
  2154. }
  2155. genBlockFinish(howToFinish, errFinish);
  2156. // at this point a valid token has been matched, undo "mark" that was done
  2157. if ( ((LexerGrammar)grammar).filterMode && filterRule!=null ) {
  2158. println("commit();");
  2159. }
  2160. // Generate literals test if desired
  2161. // make sure _ttype is set first; note _returnToken must be
  2162. // non-null as the rule was required to create it.
  2163. println("if ( !_returnToken ) goto tryAgain; // found SKIP token");
  2164. println("_ttype = _returnToken->getType();");
  2165. if ( ((LexerGrammar)grammar).getTestLiterals()) {
  2166. genLiteralsTest();
  2167. }
  2168. // return token created by rule reference in switch
  2169. println("_returnToken->setType(_ttype);");
  2170. println("return _returnToken;");
  2171. // Close try block
  2172. tabs--;
  2173. println("}");
  2174. println("catch ("+namespaceAntlr+"RecognitionException& e) {");
  2175. tabs++;
  2176. if ( ((LexerGrammar)grammar).filterMode ) {
  2177. if ( filterRule==null ) {
  2178. println("if ( !getCommitToPath() ) {consume(); goto tryAgain;}");
  2179. }
  2180. else {
  2181. println("if ( !getCommitToPath() ) {");
  2182. tabs++;
  2183. println("rewind(_m);");
  2184. println("resetText();");
  2185. println("try {m"+filterRule+"(false);}");
  2186. println("catch("+namespaceAntlr+"RecognitionException& ee) {");
  2187. println(" // horrendous failure: error in filter rule");
  2188. println(" reportError(ee);");
  2189. println(" consume();");
  2190. println("}");
  2191. println("goto tryAgain;");
  2192. tabs--;
  2193. println("}");
  2194. }
  2195. }
  2196. if ( nextTokenBlk.getDefaultErrorHandler() ) {
  2197. println("reportError(e);");
  2198. println("consume();");
  2199. }
  2200. else {
  2201.     // pass on to invoking routine
  2202.     println("throw "+namespaceAntlr+"TokenStreamRecognitionException(e);");
  2203. }
  2204. tabs--;
  2205. println("}");
  2206. // close CharStreamException try
  2207. tabs--;
  2208. println("}");
  2209. println("catch ("+namespaceAntlr+"CharStreamIOException& csie) {");
  2210. println("   throw "+namespaceAntlr+"TokenStreamIOException(csie.io);");
  2211. println("}");
  2212. println("catch ("+namespaceAntlr+"CharStreamException& cse) {");
  2213. println("   throw "+namespaceAntlr+"TokenStreamException(cse.getMessage());");
  2214. println("}");
  2215. // close for-loop
  2216. _println("tryAgain:;");
  2217. tabs--;
  2218. println("}");
  2219. // close method nextToken
  2220. tabs--;
  2221. println("}");
  2222. println("");
  2223. }
  2224. /** Gen a named rule block.
  2225.  * ASTs are generated for each element of an alternative unless
  2226.  * the rule or the alternative have a '!' modifier.
  2227.  *
  2228.  * If an alternative defeats the default tree construction, it
  2229.  * must set <rule>_AST to the root of the returned AST.
  2230.  *
  2231.  * Each alternative that does automatic tree construction, builds
  2232.  * up root and child list pointers in an ASTPair structure.
  2233.  *
  2234.  * A rule finishes by setting the returnAST variable from the
  2235.  * ASTPair.
  2236.  *
  2237.  * @param rule The name of the rule to generate
  2238.  * @param startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)
  2239. */
  2240. public void genRule(RuleSymbol s, boolean startSymbol, int ruleNum, String prefix) {
  2241. // tabs=1; // JavaCodeGenerator needs this
  2242. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRule("+ s.getId() +")");
  2243. if ( !s.isDefined() ) {
  2244. tool.error("undefined rule: "+ s.getId());
  2245. return;
  2246. }
  2247. // Generate rule return type, name, arguments
  2248. RuleBlock rblk = s.getBlock();
  2249. currentRule = rblk;
  2250. currentASTResult = s.getId();
  2251. // Save the AST generation state, and set it to that of the rule
  2252. boolean savegenAST = genAST;
  2253. genAST = genAST && rblk.getAutoGen();
  2254. // boolean oldsaveTest = saveText;
  2255. saveText = rblk.getAutoGen();
  2256. // print javadoc comment if any
  2257. if ( s.comment!=null ) {
  2258. _println(s.comment);
  2259. }
  2260. // Gen method access and final qualifier
  2261. // print(s.access + " final ");
  2262. // Gen method return type (note lexer return action set at rule creation)
  2263. if (rblk.returnAction != null)
  2264. {
  2265. // Has specified return value
  2266. _print(extractTypeOfAction(rblk.returnAction, rblk.getLine()) + " ");
  2267. } else {
  2268. // No specified return value
  2269. _print("void ");
  2270. }
  2271. // Gen method name
  2272. _print(prefix + s.getId() + "(");
  2273. // Additional rule parameters common to all rules for this grammar
  2274. _print(commonExtraParams);
  2275. if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
  2276. _print(",");
  2277. }
  2278. // Gen arguments
  2279. if (rblk.argAction != null) 
  2280. {
  2281. // Has specified arguments
  2282. _println("");
  2283. tabs++;
  2284. println(rblk.argAction);
  2285. tabs--;
  2286. print(")");
  2287. } else {
  2288. // No specified arguments
  2289. _print(")");
  2290. }
  2291. // Gen throws clause and open curly
  2292. // _print(" throws " + exceptionThrown);
  2293. // if ( !(grammar instanceof TreeWalkerGrammar) ) {
  2294. // _print(", IOException");
  2295. // }
  2296. _println(" {");
  2297. tabs++;
  2298. // Convert return action to variable declaration
  2299. if (rblk.returnAction != null)
  2300. println(rblk.returnAction + ";");
  2301. // print out definitions needed by rules for various grammar types
  2302. println(commonLocalVars);
  2303. if (grammar.traceRules) {
  2304. println("Tracer traceInOut(this,""+ s.getId() +"");");
  2305. // if ( grammar instanceof TreeWalkerGrammar ) {
  2306. // println("traceIn(""+ s.getId() +"",_t);");
  2307. // }
  2308. // else {
  2309. // println("traceIn(""+ s.getId() +"");");
  2310. // }
  2311. }
  2312. if ( grammar instanceof LexerGrammar ) {
  2313. // lexer rule default return value is the rule's token name
  2314. // This is a horrible hack to support the built-in EOF lexer rule.
  2315. if (s.getId().equals("mEOF"))
  2316. println("_ttype = "+namespaceAntlr+"Token::EOF_TYPE;");
  2317. else
  2318. println("_ttype = "+ s.getId().substring(1)+";");
  2319. println("int _saveIndex;"); // used for element! (so we can kill text matched for element)
  2320. /*
  2321. println("boolean old_saveConsumedInput=saveConsumedInput;");
  2322. if ( !rblk.getAutoGen() ) {      // turn off "save input" if ! on rule
  2323. println("saveConsumedInput=false;");
  2324. }
  2325. */
  2326. }
  2327. // if debugging, write code to mark entry to the rule
  2328. if ( grammar.debuggingOutput)
  2329.     if (grammar instanceof ParserGrammar)
  2330. println("fireEnterRule(" + ruleNum + ",0);");
  2331. else if (grammar instanceof LexerGrammar)
  2332. println("fireEnterRule(" + ruleNum + ",_ttype);");
  2333. // Generate trace code if desired
  2334. // if ( grammar.debuggingOutput || grammar.traceRules) {
  2335. // println("try { // debugging");
  2336. // tabs++;
  2337. // }
  2338. // Initialize AST variables
  2339. if (grammar instanceof TreeWalkerGrammar) {
  2340. // "Input" value for rule
  2341. println(labeledElementASTType+" " + s.getId() + "_AST_in = "+labeledElementASTType+"(_t);");
  2342. }
  2343. if (grammar.buildAST) {
  2344. // Parser member used to pass AST returns from rule invocations
  2345. println("returnAST = "+namespaceAntlr+"nullAST;");
  2346. // Tracks AST construction
  2347. println(namespaceAntlr+"ASTPair currentAST;"); // = new ASTPair();");
  2348. // User-settable return value for rule.
  2349. println(labeledElementASTType+" " + s.getId() + "_AST = "+namespaceAntlr+"nullAST;");
  2350. }
  2351. genBlockPreamble(rblk);
  2352. println("");
  2353. // Search for an unlabeled exception specification attached to the rule
  2354. ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
  2355. // Generate try block around the entire rule for  error handling
  2356. if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
  2357. println("try {      // for error handling");
  2358. tabs++;
  2359. }
  2360. // Generate the alternatives
  2361. if ( rblk.alternatives.size()==1 ) {
  2362. // One alternative -- use simple form
  2363. Alternative alt = rblk.getAlternativeAt(0);
  2364. String pred = alt.semPred;
  2365. if ( pred!=null )
  2366. genSemPred(pred, currentRule.line);
  2367. if (alt.synPred != null) {
  2368. tool.warning(
  2369. "Syntactic predicate ignored for single alternative",
  2370. grammar.getFilename(), 
  2371. alt.synPred.getLine()
  2372. );
  2373. }
  2374. genAlt(alt, rblk);
  2375. }
  2376. else {
  2377. // Multiple alternatives -- generate complex form
  2378. boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
  2379. CppBlockFinishingInfo howToFinish = genCommonBlock(rblk, false);
  2380. genBlockFinish(howToFinish, throwNoViable);
  2381. }
  2382. // Generate catch phrase for error handling
  2383. if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
  2384. // Close the try block
  2385. tabs--;
  2386. println("}");
  2387. }
  2388. // Generate user-defined or default catch phrases
  2389. if (unlabeledUserSpec != null) {
  2390. genErrorHandler(unlabeledUserSpec);
  2391. }
  2392. else if (rblk.getDefaultErrorHandler()) {
  2393. // Generate default catch phrase
  2394. println("catch (" + exceptionThrown + "& ex) {");
  2395. tabs++;
  2396. // Generate code to handle error if not guessing
  2397. if (grammar.hasSyntacticPredicate) {
  2398. println("if (inputState->guessing==0) {");
  2399. tabs++;
  2400. }
  2401. println("reportError(ex);");
  2402. if ( !(grammar instanceof TreeWalkerGrammar) ) {
  2403. // Generate code to consume until token in k==1 follow set
  2404. Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, rblk.endNode);
  2405. String followSetName = getBitsetName(markBitsetForGen(follow.fset));
  2406. println("consume();");
  2407. println("consumeUntil(" + followSetName + ");");
  2408. } else {
  2409. // Just consume one token
  2410. println("if (_t!="+namespaceAntlr+"nullAST) {_t = _t->getNextSibling();}");
  2411. }
  2412. if (grammar.hasSyntacticPredicate) {
  2413. tabs--;
  2414. // When guessing, rethrow exception
  2415. println("} else {");
  2416. tabs++;
  2417. println("throw ex;");
  2418. tabs--;
  2419. println("}");
  2420. }
  2421. // Close catch phrase
  2422. tabs--;
  2423. println("}");
  2424. }
  2425. // Squirrel away the AST "return" value
  2426. if (grammar.buildAST) {
  2427. println("returnAST = " + s.getId() + "_AST;");
  2428. }
  2429. // Set return tree value for tree walkers
  2430. if ( grammar instanceof TreeWalkerGrammar ) {
  2431. println("_retTree = _t;");
  2432. }
  2433. // Generate literals test for lexer rules so marked
  2434. if (rblk.getTestLiterals()) {
  2435. if ( s.access.equals("protected") ) {
  2436. genLiteralsTestForPartialToken();
  2437. }
  2438. else {
  2439. genLiteralsTest();
  2440. }
  2441. }
  2442. // if doing a lexer rule, dump code to create token if necessary
  2443. if ( grammar instanceof LexerGrammar ) {
  2444. println("if ( _createToken && _token=="+namespaceAntlr+"nullToken && _ttype!="+namespaceAntlr+"Token::SKIP ) {");
  2445. println("   _token = makeToken(_ttype);");
  2446. println("   _token->setText(text.substr(_begin, text.length()-_begin));");
  2447. println("}");
  2448. println("_returnToken = _token;");
  2449. }
  2450. // Gen the return statement if there is one (lexer has hard-wired return action)
  2451. if (rblk.returnAction != null) {
  2452. println("return " + extractIdOfAction(rblk.returnAction, rblk.getLine()) + ";");
  2453. }
  2454. // if ( grammar.debuggingOutput || grammar.traceRules) {
  2455. //// tabs--;
  2456. //// println("} finally { // debugging");
  2457. //// tabs++;
  2458. //
  2459. // // Generate trace code if desired
  2460. // if ( grammar.debuggingOutput)
  2461. // if (grammar instanceof ParserGrammar)
  2462. // println("fireExitRule(" + ruleNum + ",0);");
  2463. // else if (grammar instanceof LexerGrammar)
  2464. // println("fireExitRule(" + ruleNum + ",_ttype);");
  2465. //
  2466. //// if (grammar.traceRules) {
  2467. //// if ( grammar instanceof TreeWalkerGrammar ) {
  2468. //// println("traceOut(""+ s.getId() +"",_t);");
  2469. //// }
  2470. //// else {
  2471. //// println("traceOut(""+ s.getId() +"");");
  2472. //// }
  2473. //// }
  2474. ////
  2475. //// tabs--;
  2476. //// println("}");
  2477. // }
  2478. tabs--;
  2479. println("}");
  2480. println("");
  2481. // Restore the AST generation state
  2482. genAST = savegenAST;
  2483. // restore char save state
  2484. // saveText = oldsaveTest;
  2485. }
  2486. public void genRuleHeader(RuleSymbol s, boolean startSymbol) {
  2487. tabs=1;
  2488. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRuleHeader("+ s.getId() +")");
  2489. if ( !s.isDefined() ) {
  2490. tool.error("undefined rule: "+ s.getId());
  2491. return;
  2492. }
  2493. // Generate rule return type, name, arguments
  2494. RuleBlock rblk = s.getBlock();
  2495. currentRule = rblk;
  2496. currentASTResult = s.getId();
  2497. // Save the AST generation state, and set it to that of the rule
  2498. boolean savegenAST = genAST;
  2499. genAST = genAST && rblk.getAutoGen();
  2500. // boolean oldsaveTest = saveText;
  2501. saveText = rblk.getAutoGen();
  2502. // Gen method access
  2503. print(s.access + ": ");
  2504. // Gen method return type (note lexer return action set at rule creation)
  2505. if (rblk.returnAction != null)
  2506. {
  2507. // Has specified return value
  2508. _print(extractTypeOfAction(rblk.returnAction, rblk.getLine()) + " ");
  2509. } else {
  2510. // No specified return value
  2511. _print("void ");
  2512. }
  2513. // Gen method name
  2514. _print(s.getId() + "(");
  2515. // Additional rule parameters common to all rules for this grammar
  2516. _print(commonExtraParams);
  2517. if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
  2518. _print(",");
  2519. }
  2520. // Gen arguments
  2521. if (rblk.argAction != null) 
  2522. {
  2523. // Has specified arguments
  2524. _println("");
  2525. tabs++;
  2526. println(rblk.argAction);
  2527. tabs--;
  2528. print(")");
  2529. } else {
  2530. // No specified arguments
  2531. _print(")");
  2532. }
  2533. _println(";");
  2534. tabs--;
  2535. // Restore the AST generation state
  2536. genAST = savegenAST;
  2537. // restore char save state
  2538. // saveText = oldsaveTest;
  2539. }
  2540. private void GenRuleInvocation(RuleRefElement rr) {
  2541. // dump rule name
  2542. _print(rr.targetRule + "(");
  2543. // lexers must tell rule if it should set _returnToken
  2544. if ( grammar instanceof LexerGrammar ) {
  2545. // if labeled, could access Token, so tell rule to create
  2546. if ( rr.getLabel() != null ) {
  2547. _print("true");
  2548. }
  2549. else {
  2550. _print("false");
  2551. }
  2552. if (commonExtraArgs.length() != 0 || rr.args!=null ) {
  2553. _print(",");
  2554. }
  2555. }
  2556. // Extra arguments common to all rules for this grammar
  2557. _print(commonExtraArgs);
  2558. if (commonExtraArgs.length() != 0 && rr.args!=null ) {
  2559. _print(",");
  2560. }
  2561. // Process arguments to method, if any
  2562. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  2563. if (rr.args != null)
  2564. {
  2565. // When not guessing, execute user arg action
  2566. ActionTransInfo tInfo = new ActionTransInfo();
  2567. String args = processActionForTreeSpecifiers(rr.args, 0, currentRule, tInfo);
  2568. if ( tInfo.assignToRoot || tInfo.refRuleRoot!=null ) {
  2569. tool.error("Arguments of rule reference '" + rr.targetRule + "' cannot set or ref #"+
  2570. currentRule.getRuleName()+" on line "+rr.getLine());
  2571. }
  2572. _print(args);
  2573. // Warn if the rule accepts no arguments
  2574. if (rs.block.argAction == null)
  2575. {
  2576. tool.warning("Rule '" + rr.targetRule + "' accepts no arguments",
  2577. grammar.getFilename(),
  2578. rr.getLine());
  2579. }
  2580. } else {
  2581. // For C++, no warning if rule has parameters, because there may be default
  2582. // values for all of the parameters
  2583. //if (rs.block.argAction != null) {
  2584. // tool.warning("Missing parameters on reference to rule "+rr.targetRule, rr.getLine());
  2585. //}
  2586. }
  2587. _println(");");
  2588. // move down to the first child while parsing
  2589. if ( grammar instanceof TreeWalkerGrammar ) {
  2590. println("_t = _retTree;");
  2591. }
  2592. }
  2593. protected void genSemPred(String pred, int line) {
  2594. // translate $ and # references
  2595. ActionTransInfo tInfo = new ActionTransInfo();
  2596. pred = processActionForTreeSpecifiers(pred, line, currentRule, tInfo);
  2597. // ignore translation info...we don't need to do anything with it.
  2598. String escapedPred = charFormatter.escapeString(pred);
  2599. // if debugging, wrap the semantic predicate evaluation in a method
  2600. // that can tell SemanticPredicateListeners the result
  2601. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  2602.   (grammar instanceof LexerGrammar)))
  2603. pred = "fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.VALIDATING," //FIXME
  2604. + addSemPred(escapedPred) + "," + pred + ")";
  2605. println("if (!(" + pred + "))");
  2606. tabs++;
  2607. println("throw "+namespaceAntlr+"SemanticException("" + escapedPred + "");");
  2608. tabs--;
  2609. }
  2610. /** Write an array of Strings which are the semantic predicate
  2611.  *  expressions.  The debugger will reference them by number only
  2612.  */
  2613. protected void genSemPredMap(String prefix) {
  2614. Enumeration e = semPreds.elements();
  2615. println("const char* " + prefix + "_semPredNames[] = {");
  2616. tabs++;
  2617. while(e.hasMoreElements())
  2618. println("""+e.nextElement()+"",");
  2619. println("0");
  2620. tabs--;
  2621. println("};");
  2622. }
  2623. protected void genSynPred(SynPredBlock blk, String lookaheadExpr) {
  2624. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen=>("+blk+")");
  2625. // Dump synpred result variable
  2626. println("bool synPredMatched" + blk.ID + " = false;");
  2627. // Gen normal lookahead test
  2628. println("if (" + lookaheadExpr + ") {");
  2629. tabs++;
  2630. // Save input state
  2631. if ( grammar instanceof TreeWalkerGrammar ) {
  2632. println(namespaceAntlr+"RefAST __t" + blk.ID + " = _t;");
  2633. }
  2634. else {
  2635. println("int _m" + blk.ID + " = mark();");
  2636. }
  2637. // Once inside the try, assume synpred works unless exception caught
  2638. println("synPredMatched" + blk.ID + " = true;");
  2639. println("inputState->guessing++;");
  2640. // if debugging, tell listeners that a synpred has started
  2641. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  2642.  (grammar instanceof LexerGrammar))) {
  2643. println("fireSyntacticPredicateStarted();");
  2644. }
  2645. syntacticPredLevel++;
  2646. println("try {");
  2647. tabs++;
  2648. gen((AlternativeBlock)blk); // gen code to test predicate
  2649. tabs--;
  2650. //println("System.out.println("pred "+blk+" succeeded");");
  2651. println("}");
  2652. println("catch (" + exceptionThrown + "& pe) {");
  2653. tabs++;
  2654. println("synPredMatched"+blk.ID+" = false;");
  2655. //println("System.out.println("pred "+blk+" failed");");
  2656. tabs--;
  2657. println("}");
  2658. // Restore input state
  2659. if ( grammar instanceof TreeWalkerGrammar ) {
  2660. println("_t = __t"+blk.ID+";");
  2661. }
  2662. else {
  2663. println("rewind(_m"+blk.ID+");");
  2664. }
  2665. println("inputState->guessing--;");
  2666. // if debugging, tell listeners how the synpred turned out
  2667. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  2668.      (grammar instanceof LexerGrammar))) {
  2669. println("if (synPredMatched" + blk.ID +")");
  2670. println("  fireSyntacticPredicateSucceeded();");
  2671. println("else");
  2672. println("  fireSyntacticPredicateFailed();");
  2673. }
  2674. syntacticPredLevel--;
  2675. tabs--;
  2676. // Close lookahead test
  2677. println("}");
  2678. // Test synpred result
  2679. println("if ( synPredMatched"+blk.ID+" ) {");
  2680. }
  2681. /** Generate a static array containing the names of the tokens,
  2682.  * indexed by the token type values.  This static array is used
  2683.  * to format error messages so that the token identifers or literal
  2684.  * strings are displayed instead of the token numbers.
  2685.  *
  2686.  * If a lexical rule has a paraphrase, use it rather than the
  2687.  * token label.
  2688.  */
  2689. public void genTokenStrings(String prefix) {
  2690. // Generate a string for each token.  This creates a static
  2691. // array of Strings indexed by token type.
  2692. // println("");
  2693. println("const char* " + prefix + "_tokenNames[] = {");
  2694. tabs++;
  2695. // Walk the token vocabulary and generate a Vector of strings
  2696. // from the tokens.
  2697. Vector v = grammar.tokenManager.getVocabulary();
  2698. for (int i = 0; i < v.size(); i++)
  2699. {
  2700. String s = (String)v.elementAt(i);
  2701. if (s == null)
  2702. {
  2703. s = "<"+String.valueOf(i)+">";
  2704. }
  2705. if ( !s.startsWith(""") && !s.startsWith("<") ) {
  2706. TokenSymbol ts = (TokenSymbol)grammar.tokenManager.getTokenSymbol(s);
  2707. if ( ts!=null && ts.getParaphrase()!=null ) {
  2708. s = antlr.Tool.stripFrontBack(ts.getParaphrase(), """, """);
  2709. }
  2710. }
  2711. print(charFormatter.literalString(s));
  2712. _println(",");
  2713. }
  2714. println("0");
  2715. // Close the string array initailizer
  2716. tabs--;
  2717. println("};");
  2718. }
  2719. /** Generate the token types C++ file */
  2720. protected void genTokenTypes(TokenManager tm) throws IOException {
  2721. // Open the token output header file and set the currentOutput stream
  2722. currentOutput = antlr.Tool.openOutputFile(tm.getName() + TokenTypesFileSuffix+".hpp");
  2723. //SAS: changed for proper text file io
  2724. tabs = 0;
  2725. // Generate a guard wrapper
  2726. println("#ifndef INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
  2727. println("#define INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
  2728. println("");
  2729. // println("#include "antlr/config.hpp"");
  2730. if (tool.nameSpace != null)
  2731. println("ANTLR_BEGIN_NAMESPACE("+tool.nameSpace+")");
  2732. // Generate the header common to all C++ files
  2733. genHeader(tm.getName() + TokenTypesFileSuffix+".hpp");
  2734. // Encapsulate the definitions in an interface.  This can be done
  2735. // because they are all constants.
  2736. println("struct " + tm.getName() + TokenTypesFileSuffix+" {");
  2737. tabs++;
  2738. println("enum {");
  2739. tabs++;
  2740. // Generate a definition for each token type
  2741. Vector v = tm.getVocabulary();
  2742. // Do special tokens manually
  2743. println("EOF_ = " + Token.EOF_TYPE + ",");
  2744. println("NULL_TREE_LOOKAHEAD = " + Token.NULL_TREE_LOOKAHEAD + ",");
  2745. for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
  2746. String s = (String)v.elementAt(i);
  2747. if (s != null) {
  2748. if ( s.startsWith(""") ) {
  2749. // a string literal
  2750. StringLiteralSymbol sl = (StringLiteralSymbol)tm.getTokenSymbol(s);
  2751. if ( sl==null ) {
  2752. antlr.Tool.panic("String literal "+s+" not in symbol table");
  2753. }
  2754. else if ( sl.label != null ) {
  2755. println(sl.label + " = " + i + ",");
  2756. }
  2757. else {
  2758. String mangledName = mangleLiteral(s);
  2759. if (mangledName != null) {
  2760. // We were able to create a meaningful mangled token name
  2761. println(mangledName + " = " + i + ",");
  2762. // if no label specified, make the label equal to the mangled name
  2763. sl.label = mangledName;
  2764. }
  2765. else {
  2766. println("// " + s + " = " + i);
  2767. }
  2768. }
  2769. }
  2770. else if ( !s.startsWith("<") ) {
  2771. println(s + " = " + i + ",");
  2772. }
  2773. }
  2774. }
  2775. // Close the enum
  2776. tabs--;
  2777. println("};");
  2778. // Close the interface
  2779. tabs--;
  2780. println("};");
  2781. if (tool.nameSpace != null)
  2782. println("ANTLR_END_NAMESPACE");
  2783. // Generate a guard wrapper
  2784. println("#endif /*INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_*/");
  2785. // Close the tokens output file
  2786. currentOutput.close();
  2787. currentOutput = null;
  2788. exitIfError();
  2789. }
  2790. /** Get a string for an expression to generate creation of an AST subtree.
  2791.   * @param v A Vector of String, where each element is an expression in the target language yielding an AST node.
  2792.   */
  2793. public String getASTCreateString(Vector v) {
  2794. if (v.size() == 0) {
  2795. return "";
  2796. }
  2797. StringBuffer buf = new StringBuffer();
  2798. buf.append(labeledElementASTType+
  2799. "(astFactory.make( (new "+namespaceAntlr+"ASTArray(" + v.size() +
  2800. "))");
  2801. for (int i = 0; i < v.size(); i++) {
  2802. buf.append("->add(" + v.elementAt(i) + ")");
  2803. }
  2804. buf.append("))");
  2805. return buf.toString();
  2806. }
  2807. /** Get a string for an expression to generate creating of an AST node
  2808.   * @param str The arguments to the AST constructor
  2809.   */
  2810. public String getASTCreateString(GrammarAtom atom, String str) {
  2811. if ( atom!=null && atom.getASTNodeType() != null ) {
  2812. return "Ref"+atom.getASTNodeType()+"(new "+atom.getASTNodeType()+"("+str+"))";
  2813. }
  2814. else {
  2815. return labeledElementASTType+"(astFactory.create(" + str + "))";
  2816. }
  2817. }
  2818. protected String getLookaheadTestExpression(Lookahead[] look, int k) {
  2819. StringBuffer e = new StringBuffer(100);
  2820. boolean first = true;
  2821. e.append("(");
  2822. for (int i = 1; i <= k; i++) {
  2823. BitSet p = look[i].fset;
  2824. if (!first) {
  2825. e.append(") && (");
  2826. }
  2827. first = false;
  2828. // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
  2829. // There is no way to predict what that token would be.  Just
  2830. // allow anything instead.
  2831. if (look[i].containsEpsilon()) {
  2832. e.append("true");
  2833. } else {
  2834. e.append(getLookaheadTestTerm(i, p));
  2835. }
  2836. }
  2837. e.append(")");
  2838. return e.toString();
  2839. }
  2840. /**Generate a lookahead test expression for an alternate.  This
  2841.  * will be a series of tests joined by '&&' and enclosed by '()',
  2842.  * the number of such tests being determined by the depth of the lookahead.
  2843.  */
  2844. protected String getLookaheadTestExpression(Alternative alt, int maxDepth) {
  2845. int depth = alt.lookaheadDepth;
  2846. if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
  2847. // if the decision is nondeterministic, do the best we can: LL(k)
  2848. // any predicates that are around will be generated later.
  2849. depth = grammar.maxk;
  2850. }
  2851. if ( maxDepth==0 ) {
  2852. // empty lookahead can result from alt with sem pred
  2853. // that can see end of token.  E.g., A : {pred}? ('a')? ;
  2854. return "true";
  2855. }
  2856. /*
  2857. boolean first = true;
  2858. for (int i=1; i<=depth && i<=maxDepth; i++) {
  2859. BitSet p = alt.cache[i].fset;
  2860. if (!first) {
  2861. e.append(") && (");
  2862. }
  2863. first = false;
  2864. // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
  2865. // There is no way to predict what that token would be.  Just
  2866. // allow anything instead.
  2867. if ( alt.cache[i].containsEpsilon() ) {
  2868. e.append("true");
  2869. }
  2870. else {
  2871. e.append(getLookaheadTestTerm(i, p));
  2872. }
  2873. }
  2874. e.append(")");
  2875. */
  2876. return "(" + getLookaheadTestExpression(alt.cache,depth) + ")";
  2877. }
  2878. /**Generate a depth==1 lookahead test expression given the BitSet.
  2879.  * This may be one of:
  2880.  * 1) a series of 'x==X||' tests
  2881.  * 2) a range test using >= && <= where possible,
  2882.  * 3) a bitset membership test for complex comparisons
  2883.  * @param k The lookahead level
  2884.  * @param p The lookahead set for level k
  2885.  */
  2886. protected String getLookaheadTestTerm(int k, BitSet p) {
  2887. // Determine the name of the item to be compared
  2888. String ts = lookaheadString(k);
  2889. // Generate a range expression if possible
  2890. int[] elems = p.toArray();
  2891. if (elementsAreRange(elems)) {
  2892. return getRangeExpression(k, elems);
  2893. }
  2894. // Generate a bitset membership test if possible
  2895. StringBuffer e;
  2896. int degree = p.degree();
  2897. if ( degree == 0 ) {
  2898. return "true";
  2899. }
  2900. if (degree >= bitsetTestThreshold) {
  2901. int bitsetIdx = markBitsetForGen(p);
  2902. return getBitsetName(bitsetIdx) + ".member(" + ts + ")";
  2903. }
  2904. // Otherwise, generate the long-winded series of "x==X||" tests
  2905. e = new StringBuffer();
  2906. for (int i = 0; i < elems.length; i++) {
  2907. // Get the compared-to item (token or character value)
  2908. String cs = getValueString(elems[i]);
  2909. // Generate the element comparison
  2910. if ( i>0 ) e.append("||");
  2911. e.append(ts);
  2912. e.append("==");
  2913. e.append(cs);
  2914. }
  2915. return e.toString();
  2916. }
  2917. /** Return an expression for testing a contiguous renage of elements
  2918.  * @param k The lookahead level
  2919.  * @param elems The elements representing the set, usually from BitSet.toArray().
  2920.  * @return String containing test expression.
  2921.  */
  2922. public String getRangeExpression(int k, int[] elems) {
  2923. if (!elementsAreRange(elems)) {
  2924. tool.panic("getRangeExpression called with non-range");
  2925. }
  2926. int begin = elems[0];
  2927. int end = elems[elems.length-1];
  2928. return 
  2929. "(" + lookaheadString(k) + " >= " + getValueString(begin) + " && " + 
  2930. lookaheadString(k) + " <= " + getValueString(end) + ")";
  2931. }
  2932. /** getValueString: get a string representation of a token or char value
  2933.  * @param value The token or char value
  2934.  */
  2935. private String getValueString(int value) {
  2936. String cs;
  2937. if ( grammar instanceof LexerGrammar ) {
  2938. cs = charFormatter.literalChar(value);
  2939. }
  2940. else {
  2941. TokenSymbol ts = grammar.tokenManager.getTokenSymbolAt(value);
  2942. if ( ts == null ) {
  2943. return ""+value; // return token type as string
  2944. // tool.panic("vocabulary for token type " + value + " is null");
  2945. }
  2946. String tId = ts.getId();
  2947. if ( ts instanceof StringLiteralSymbol ) {
  2948. // if string literal, use predefined label if any
  2949. // if no predefined, try to mangle into LITERAL_xxx.
  2950. // if can't mangle, use int value as last resort
  2951. StringLiteralSymbol sl = (StringLiteralSymbol)ts;
  2952. String label = sl.getLabel();
  2953. if ( label!=null ) {
  2954. cs = label;
  2955. }
  2956. else {
  2957. cs = mangleLiteral(tId);
  2958. if (cs == null) {
  2959. cs = String.valueOf(value);
  2960. }
  2961. }
  2962. }
  2963. else {
  2964. if ( tId.equals("EOF") )
  2965. cs = namespaceAntlr+"Token::EOF_TYPE";
  2966. else
  2967. cs = tId;
  2968. }
  2969. }
  2970. return cs;
  2971. }
  2972. /**Is the lookahead for this alt empty? */
  2973. protected boolean lookaheadIsEmpty(Alternative alt, int maxDepth) {
  2974. int depth = alt.lookaheadDepth;
  2975. if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
  2976. depth = grammar.maxk;
  2977. }
  2978. for (int i=1; i<=depth && i<=maxDepth; i++) {
  2979. BitSet p = alt.cache[i].fset;
  2980. if (p.degree() != 0) {
  2981. return false;
  2982. }
  2983. }
  2984. return true;
  2985. }
  2986. private String lookaheadString(int k) {
  2987. if (grammar instanceof TreeWalkerGrammar) {
  2988. return "_t->getType()";
  2989. return "LA(" + k + ")";
  2990. }
  2991. /** Mangle a string literal into a meaningful token name.  This is
  2992.   * only possible for literals that are all characters.  The resulting
  2993.   * mangled literal name is literalsPrefix with the text of the literal
  2994.   * appended.
  2995.   * @return A string representing the mangled literal, or null if not possible.
  2996.   */
  2997. private String mangleLiteral(String s) {
  2998. String mangled = antlr.Tool.literalsPrefix;
  2999. for (int i = 1; i < s.length()-1; i++) {
  3000. if (!Character.isLetter(s.charAt(i)) &&
  3001.  s.charAt(i) != '_') {
  3002. return null;
  3003. }
  3004. mangled += s.charAt(i);
  3005. }
  3006. if ( antlr.Tool.upperCaseMangledLiterals ) {
  3007. mangled = mangled.toUpperCase();
  3008. }
  3009. return mangled;
  3010. }
  3011. /** Map an identifier to it's corresponding tree-node variable.
  3012.   * This is context-sensitive, depending on the rule and alternative
  3013.   * being generated
  3014.   * @param idParam The identifier name to map
  3015.   * @return The mapped id (which may be the same as the input), or null if the mapping is invalid due to duplicates
  3016.   */
  3017. public String mapTreeId(String idParam, ActionTransInfo transInfo) {
  3018. // if not in an action of a rule, nothing to map.
  3019. if ( currentRule==null ) return idParam;
  3020. boolean in_var = false;
  3021. String id = idParam;
  3022. if (grammar instanceof TreeWalkerGrammar) {
  3023. if ( !grammar.buildAST ) {
  3024. in_var = true;
  3025. }
  3026. // If the id ends with "_in", then map it to the input variable
  3027. else if (id.length() > 3 && id.lastIndexOf("_in") == id.length()-3) {
  3028. // Strip off the "_in"
  3029. id = id.substring(0, id.length()-3);
  3030. in_var = true;
  3031. }
  3032. }
  3033. // Check the rule labels.  If id is a label, then the output
  3034. // variable is label_AST, and the input variable is plain label.
  3035. for (int i = 0; i < currentRule.labeledElements.size(); i++) {
  3036. AlternativeElement elt = (AlternativeElement)currentRule.labeledElements.elementAt(i);
  3037. if (elt.getLabel().equals(id)) {
  3038. return in_var ? id : id + "_AST";
  3039. }
  3040. }
  3041. // Failing that, check the id-to-variable map for the alternative.
  3042. // If the id is in the map, then output variable is the name in the
  3043. // map, and input variable is name_in
  3044. String s = (String)treeVariableMap.get(id);
  3045. if (s != null) {
  3046. if (s == NONUNIQUE) {
  3047. // There is more than one element with this id
  3048. return null;
  3049. } else if (s.equals(currentRule.getRuleName())) {
  3050. // a recursive call to the enclosing rule is 
  3051. // ambiguous with the rule itself.
  3052. return null;
  3053. } else {
  3054. return in_var ? s + "_in" : s;
  3055. }
  3056. }
  3057. // Failing that, check the rule name itself.  Output variable
  3058. // is rule_AST; input variable is rule_AST_in (treeparsers).
  3059. if (id.equals(currentRule.getRuleName())) {
  3060. String r = in_var ? id + "_AST_in" : id + "_AST";
  3061. if ( transInfo!=null ) {
  3062. if ( !in_var ) {
  3063. transInfo.refRuleRoot = r;
  3064. }
  3065. }
  3066. return r;
  3067. } else {
  3068. // id does not map to anything -- return itself.
  3069. return id;
  3070. }
  3071. }
  3072. /** Given an element and the name of an associated AST variable,
  3073.   * create a mapping between the element "name" and the variable name.
  3074.   */
  3075. private void mapTreeVariable(AlternativeElement e, String name)
  3076. {
  3077. // For tree elements, defer to the root
  3078. if (e instanceof TreeElement) {
  3079. mapTreeVariable( ((TreeElement)e).root, name);
  3080. return;
  3081. }
  3082. // Determine the name of the element, if any, for mapping purposes
  3083. String elName = null;
  3084. // Don't map labeled items
  3085. if (e.getLabel() == null) {
  3086. if (e instanceof TokenRefElement) {
  3087. // use the token id
  3088. elName = ((TokenRefElement)e).atomText;
  3089. }
  3090. else if (e instanceof RuleRefElement) {
  3091. // use the rule name
  3092. elName = ((RuleRefElement)e).targetRule;
  3093. }
  3094. }
  3095. // Add the element to the tree variable map if it has a name
  3096. if (elName != null) {
  3097. if (treeVariableMap.get(elName) != null) {
  3098. // Name is already in the map -- mark it as duplicate
  3099. treeVariableMap.remove(elName);
  3100. treeVariableMap.put(elName, NONUNIQUE);
  3101. }
  3102. else {
  3103. treeVariableMap.put(elName, name);
  3104. }
  3105. }
  3106. }
  3107.     protected String processActionForTreeSpecifiers(String actionStr,
  3108.     int line,
  3109.     RuleBlock currentRule,
  3110.     ActionTransInfo tInfo)
  3111.     {
  3112. return super.processActionForTreeSpecifiers(actionStr,
  3113.     line,
  3114.     currentRule,
  3115.     tInfo);
  3116.     }
  3117. private void setupGrammarParameters(Grammar g) {
  3118. if (g instanceof ParserGrammar) {
  3119. labeledElementASTType = namespaceAntlr+"RefAST";
  3120. if ( g.hasOption("ASTLabelType") ) {
  3121. Token tsuffix = g.getOption("ASTLabelType");
  3122. if ( tsuffix != null ) {
  3123. String suffix = Tool.stripFrontBack(tsuffix.getText(),""",""");
  3124. if ( suffix != null ) {
  3125. labeledElementASTType = suffix;
  3126. }
  3127. }
  3128. }
  3129. labeledElementType = namespaceAntlr+"RefToken ";
  3130. labeledElementInit = namespaceAntlr+"nullToken";
  3131. commonExtraArgs = "";
  3132. commonExtraParams = "";
  3133. commonLocalVars = "";
  3134. lt1Value = "LT(1)";
  3135. exceptionThrown = namespaceAntlr+"RecognitionException";
  3136. throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(LT(1), getFilename());";
  3137. }
  3138. else if (g instanceof LexerGrammar) {
  3139. labeledElementType = "char ";
  3140. labeledElementInit = "'\0'";
  3141. commonExtraArgs = "";
  3142. commonExtraParams = "bool _createToken";
  3143. commonLocalVars = "int _ttype; "+namespaceAntlr+"RefToken _token; int _begin=text.length();";
  3144. lt1Value = "LA(1)";
  3145. exceptionThrown = namespaceAntlr+"RecognitionException";
  3146. throwNoViable = "throw "+namespaceAntlr+"NoViableAltForCharException(LA(1), getFilename(), getLine());";
  3147. }
  3148. else if (g instanceof TreeWalkerGrammar) {
  3149. labeledElementASTType = namespaceAntlr+"RefAST";
  3150. labeledElementType = namespaceAntlr+"RefAST";
  3151. if ( g.hasOption("ASTLabelType") ) {
  3152. Token tsuffix = g.getOption("ASTLabelType");
  3153. if ( tsuffix != null ) {
  3154. String suffix = Tool.stripFrontBack(tsuffix.getText(),""",""");
  3155. if ( suffix != null ) {
  3156. labeledElementASTType = suffix;
  3157. labeledElementType = suffix;
  3158. }
  3159. }
  3160. }
  3161. if ( !g.hasOption("ASTLabelType") ) {
  3162. g.setOption("ASTLabelType", new Token(ANTLRTokenTypes.STRING_LITERAL,namespaceAntlr+"RefAST"));
  3163. }
  3164. labeledElementInit = namespaceAntlr+"nullAST";
  3165. commonExtraArgs = "_t";
  3166. commonExtraParams = namespaceAntlr+"RefAST _t";
  3167. commonLocalVars = "";
  3168. lt1Value = labeledElementASTType+"(_t)";
  3169. exceptionThrown = namespaceAntlr+"RecognitionException";
  3170. throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(_t);";
  3171. }
  3172. else {
  3173. tool.panic("Unknown grammar type");
  3174. }
  3175. }
  3176. private String textOrChar(String text) {
  3177. // check to see if the text is a single character
  3178. if (text.startsWith("'")) {
  3179. // assume it also ends with '
  3180. return charFormatter.literalChar(ANTLRLexer.tokenTypeForCharLiteral(text));
  3181. }
  3182. else
  3183. return text;
  3184. }
  3185. }