PageRenderTime 79ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/antlr-2.7.5/antlr/CppCodeGenerator.java

https://github.com/boo/boo-lang
Java | 4828 lines | 3515 code | 406 blank | 907 comment | 731 complexity | 6958d383017cebc6d256380b2df05dcf MD5 | raw file
Possible License(s): GPL-2.0
  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/license.html
  5. *
  6. * $Id: //depot/code/org.antlr/release/antlr-2.7.5/antlr/CppCodeGenerator.java#1 $
  7. */
  8. // C++ code generator by Pete Wells: pete@yamuna.demon.co.uk
  9. // #line generation contributed by: Ric Klaren <klaren@cs.utwente.nl>
  10. import java.util.Enumeration;
  11. import java.util.Hashtable;
  12. import antlr.collections.impl.BitSet;
  13. import antlr.collections.impl.Vector;
  14. import java.io.PrintWriter; //SAS: changed for proper text file io
  15. import java.io.IOException;
  16. import java.io.FileWriter;
  17. /** Generate MyParser.cpp, MyParser.hpp, MyLexer.cpp, MyLexer.hpp
  18. * and MyParserTokenTypes.hpp
  19. */
  20. public class CppCodeGenerator extends CodeGenerator {
  21. boolean DEBUG_CPP_CODE_GENERATOR = false;
  22. // non-zero if inside syntactic predicate generation
  23. protected int syntacticPredLevel = 0;
  24. // Are we generating ASTs (for parsers and tree parsers) right now?
  25. protected boolean genAST = false;
  26. // Are we saving the text consumed (for lexers) right now?
  27. protected boolean saveText = false;
  28. // Generate #line's
  29. protected boolean genHashLines = true;
  30. // Generate constructors or not
  31. protected boolean noConstructors = false;
  32. // Used to keep track of lineno in output
  33. protected int outputLine;
  34. protected String outputFile;
  35. // Grammar parameters set up to handle different grammar classes.
  36. // These are used to get instanceof tests out of code generation
  37. boolean usingCustomAST = false;
  38. String labeledElementType;
  39. String labeledElementASTType; // mostly the same as labeledElementType except in parsers
  40. String labeledElementASTInit;
  41. String labeledElementInit;
  42. String commonExtraArgs;
  43. String commonExtraParams;
  44. String commonLocalVars;
  45. String lt1Value;
  46. String exceptionThrown;
  47. String throwNoViable;
  48. // Tracks the rule being generated. Used for mapTreeId
  49. RuleBlock currentRule;
  50. // Tracks the rule or labeled subrule being generated. Used for AST generation.
  51. String currentASTResult;
  52. // Mapping between the ids used in the current alt, and the
  53. // names of variables used to represent their AST values.
  54. Hashtable treeVariableMap = new Hashtable();
  55. /** Used to keep track of which AST variables have been defined in a rule
  56. * (except for the #rule_name and #rule_name_in var's
  57. */
  58. Hashtable declaredASTVariables = new Hashtable();
  59. // Count of unnamed generated variables
  60. int astVarNumber = 1;
  61. // Special value used to mark duplicate in treeVariableMap
  62. protected static final String NONUNIQUE = new String();
  63. public static final int caseSizeThreshold = 127; // ascii is max
  64. private Vector semPreds;
  65. // Used to keep track of which (heterogeneous AST types are used)
  66. // which need to be set in the ASTFactory of the generated parser
  67. private Vector astTypes;
  68. private static String namespaceStd = "ANTLR_USE_NAMESPACE(std)";
  69. private static String namespaceAntlr = "ANTLR_USE_NAMESPACE(antlr)";
  70. private static NameSpace nameSpace = null;
  71. private static final String preIncludeCpp = "pre_include_cpp";
  72. private static final String preIncludeHpp = "pre_include_hpp";
  73. private static final String postIncludeCpp = "post_include_cpp";
  74. private static final String postIncludeHpp = "post_include_hpp";
  75. /** Create a C++ code-generator using the given Grammar.
  76. * The caller must still call setTool, setBehavior, and setAnalyzer
  77. * before generating code.
  78. */
  79. public CppCodeGenerator() {
  80. super();
  81. charFormatter = new CppCharFormatter();
  82. }
  83. /** Adds a semantic predicate string to the sem pred vector
  84. These strings will be used to build an array of sem pred names
  85. when building a debugging parser. This method should only be
  86. called when the debug option is specified
  87. */
  88. protected int addSemPred(String predicate) {
  89. semPreds.appendElement(predicate);
  90. return semPreds.size()-1;
  91. }
  92. public void exitIfError()
  93. {
  94. if (antlrTool.hasError())
  95. {
  96. antlrTool.fatalError("Exiting due to errors.");
  97. }
  98. }
  99. protected int countLines( String s )
  100. {
  101. int lines = 0;
  102. for( int i = 0; i < s.length(); i++ )
  103. {
  104. if( s.charAt(i) == '\n' )
  105. lines++;
  106. }
  107. return lines;
  108. }
  109. /** Output a String to the currentOutput stream.
  110. * Ignored if string is null.
  111. * @param s The string to output
  112. */
  113. protected void _print(String s)
  114. {
  115. if (s != null)
  116. {
  117. outputLine += countLines(s);
  118. currentOutput.print(s);
  119. }
  120. }
  121. /** Print an action without leading tabs, attempting to
  122. * preserve the current indentation level for multi-line actions
  123. * Ignored if string is null.
  124. * @param s The action string to output
  125. */
  126. protected void _printAction(String s)
  127. {
  128. if (s != null)
  129. {
  130. outputLine += countLines(s)+1;
  131. super._printAction(s);
  132. }
  133. }
  134. /** Print an action stored in a token surrounded by #line stuff */
  135. public void printAction(Token t)
  136. {
  137. if (t != null)
  138. {
  139. genLineNo(t.getLine());
  140. printTabs();
  141. _printAction(processActionForSpecialSymbols(t.getText(), t.getLine(),
  142. null, null) );
  143. genLineNo2();
  144. }
  145. }
  146. /** Print a header action by #line stuff also process any tree construction
  147. * @param name The name of the header part
  148. */
  149. public void printHeaderAction(String name)
  150. {
  151. Token a = (antlr.Token)behavior.headerActions.get(name);
  152. if (a != null)
  153. {
  154. genLineNo(a.getLine());
  155. println(processActionForSpecialSymbols(a.getText(), a.getLine(),
  156. null, null) );
  157. genLineNo2();
  158. }
  159. }
  160. /** Output a String followed by newline, to the currentOutput stream.
  161. * Ignored if string is null.
  162. * @param s The string to output
  163. */
  164. protected void _println(String s) {
  165. if (s != null) {
  166. outputLine += countLines(s)+1;
  167. currentOutput.println(s);
  168. }
  169. }
  170. /** Output tab indent followed by a String followed by newline,
  171. * to the currentOutput stream. Ignored if string is null.
  172. * @param s The string to output
  173. */
  174. protected void println(String s) {
  175. if (s != null) {
  176. printTabs();
  177. outputLine += countLines(s)+1;
  178. currentOutput.println(s);
  179. }
  180. }
  181. /** Generate a #line or // line depending on options */
  182. public void genLineNo(int line) {
  183. if ( line == 0 ) {
  184. line++;
  185. }
  186. if( genHashLines )
  187. _println("#line "+line+" \""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\"");
  188. }
  189. /** Generate a #line or // line depending on options */
  190. public void genLineNo(GrammarElement el)
  191. {
  192. if( el != null )
  193. genLineNo(el.getLine());
  194. }
  195. /** Generate a #line or // line depending on options */
  196. public void genLineNo(Token t)
  197. {
  198. if (t != null)
  199. genLineNo(t.getLine());
  200. }
  201. /** Generate a #line or // line depending on options */
  202. public void genLineNo2()
  203. {
  204. if( genHashLines )
  205. {
  206. _println("#line "+(outputLine+1)+" \""+outputFile+"\"");
  207. }
  208. }
  209. /// Bound safe isDigit
  210. private boolean charIsDigit( String s, int i )
  211. {
  212. return (i < s.length()) && Character.isDigit(s.charAt(i));
  213. }
  214. /** Normalize a string coming from antlr's lexer. E.g. translate java
  215. * escapes to values. Check their size (multibyte) bomb out if they are
  216. * multibyte (bit crude). Then reescape to C++ style things.
  217. * Used to generate strings for match() and matchRange()
  218. * @param lit the literal string
  219. * @param isCharLiteral if it's for a character literal
  220. * (enforced to be one length) and enclosed in '
  221. * FIXME: bombing out on mb chars. Should be done in Lexer.
  222. * FIXME: this is another horrible hack.
  223. * FIXME: life would be soooo much easier if the stuff from the lexer was
  224. * normalized in some way.
  225. */
  226. private String convertJavaToCppString( String lit, boolean isCharLiteral )
  227. {
  228. // System.out.println("convertJavaToCppLiteral: "+lit);
  229. String ret = new String();
  230. String s = lit;
  231. int i = 0;
  232. int val = 0;
  233. if( isCharLiteral ) // verify & strip off quotes
  234. {
  235. if( ! lit.startsWith("'") || ! lit.endsWith("'") )
  236. antlrTool.error("Invalid character literal: '"+lit+"'");
  237. }
  238. else
  239. {
  240. if( ! lit.startsWith("\"") || ! lit.endsWith("\"") )
  241. antlrTool.error("Invalid character string: '"+lit+"'");
  242. }
  243. s = lit.substring(1,lit.length()-1);
  244. String prefix="";
  245. int maxsize = 255;
  246. if( grammar instanceof LexerGrammar )
  247. {
  248. // vocab size seems to be 1 bigger than it actually is
  249. maxsize = ((LexerGrammar)grammar).charVocabulary.size() - 1;
  250. if( maxsize > 255 )
  251. prefix= "L";
  252. }
  253. // System.out.println("maxsize "+maxsize+" prefix "+prefix);
  254. while ( i < s.length() )
  255. {
  256. if( s.charAt(i) == '\\' )
  257. {
  258. if( s.length() == i+1 )
  259. antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
  260. // deal with escaped junk
  261. switch ( s.charAt(i+1) ) {
  262. case 'a' :
  263. val = 7;
  264. i += 2;
  265. break;
  266. case 'b' :
  267. val = 8;
  268. i += 2;
  269. break;
  270. case 't' :
  271. val = 9;
  272. i += 2;
  273. break;
  274. case 'n' :
  275. val = 10;
  276. i += 2;
  277. break;
  278. case 'f' :
  279. val = 12;
  280. i += 2;
  281. break;
  282. case 'r' :
  283. val = 13;
  284. i += 2;
  285. break;
  286. case '"' :
  287. case '\'' :
  288. case '\\' :
  289. val = s.charAt(i+1);
  290. i += 2;
  291. break;
  292. case 'u' :
  293. // Unicode char \u1234
  294. if( i+5 < s.length() )
  295. {
  296. val = Character.digit(s.charAt(i+2), 16) * 16 * 16 * 16 +
  297. Character.digit(s.charAt(i+3), 16) * 16 * 16 +
  298. Character.digit(s.charAt(i+4), 16) * 16 +
  299. Character.digit(s.charAt(i+5), 16);
  300. i += 6;
  301. }
  302. else
  303. antlrTool.error("Invalid escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
  304. break;
  305. case '0' : // \123
  306. case '1' :
  307. case '2' :
  308. case '3' :
  309. if( charIsDigit(s, i+2) )
  310. {
  311. if( charIsDigit(s, i+3) )
  312. {
  313. val = (s.charAt(i+1)-'0')*8*8 + (s.charAt(i+2)-'0')*8 +
  314. (s.charAt(i+3)-'0');
  315. i += 4;
  316. }
  317. else
  318. {
  319. val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
  320. i += 3;
  321. }
  322. }
  323. else
  324. {
  325. val = s.charAt(i+1)-'0';
  326. i += 2;
  327. }
  328. break;
  329. case '4' :
  330. case '5' :
  331. case '6' :
  332. case '7' :
  333. if ( charIsDigit(s, i+2) )
  334. {
  335. val = (s.charAt(i+1)-'0')*8 + (s.charAt(i+2)-'0');
  336. i += 3;
  337. }
  338. else
  339. {
  340. val = s.charAt(i+1)-'0';
  341. i += 2;
  342. }
  343. default:
  344. antlrTool.error("Unhandled escape in char literal: '"+lit+"' looking at '"+s.substring(i)+"'");
  345. val = 0;
  346. }
  347. }
  348. else
  349. val = s.charAt(i++);
  350. if( grammar instanceof LexerGrammar )
  351. {
  352. if( val > maxsize ) // abort if too big
  353. {
  354. String offender;
  355. if( ( 0x20 <= val ) && ( val < 0x7F ) )
  356. offender = charFormatter.escapeChar(val,true);
  357. else
  358. offender = "0x"+Integer.toString(val,16);
  359. antlrTool.error("Character out of range in "+(isCharLiteral?"char literal":"string constant")+": '"+s+"'");
  360. antlrTool.error("Vocabulary size: "+maxsize+" Character "+offender);
  361. }
  362. }
  363. if( isCharLiteral )
  364. {
  365. // we should be at end of char literal here..
  366. if( i != s.length() )
  367. antlrTool.error("Invalid char literal: '"+lit+"'");
  368. if( maxsize <= 255 )
  369. {
  370. if ( (val <= 255) && (val & 0x80) != 0 )
  371. // the joys of sign extension in the support lib *cough*
  372. // actually the support lib needs to be fixed but that's a bit
  373. // hairy too.
  374. ret = "static_cast<unsigned char>('"+charFormatter.escapeChar(val,true)+"')";
  375. else
  376. ret = "'"+charFormatter.escapeChar(val,true)+"'";
  377. }
  378. else
  379. {
  380. // so wchar_t is some implementation defined int like thing
  381. // so this may even lead to having 16 bit or 32 bit cases...
  382. // I smell some extra grammar options in the future :(
  383. ret = "L'"+charFormatter.escapeChar(val,true)+"'";
  384. }
  385. }
  386. else
  387. ret += charFormatter.escapeChar(val,true);
  388. }
  389. if( !isCharLiteral )
  390. ret = prefix+"\""+ret+"\"";
  391. return ret;
  392. }
  393. /** Generate the parser, lexer, treeparser, and token types in C++
  394. */
  395. public void gen() {
  396. // Do the code generation
  397. try {
  398. // Loop over all grammars
  399. Enumeration grammarIter = behavior.grammars.elements();
  400. while (grammarIter.hasMoreElements()) {
  401. Grammar g = (Grammar)grammarIter.nextElement();
  402. if ( g.debuggingOutput ) {
  403. antlrTool.error(g.getFilename()+": C++ mode does not support -debug");
  404. }
  405. // Connect all the components to each other
  406. g.setGrammarAnalyzer(analyzer);
  407. g.setCodeGenerator(this);
  408. analyzer.setGrammar(g);
  409. // To get right overloading behavior across hetrogeneous grammars
  410. setupGrammarParameters(g);
  411. g.generate();
  412. exitIfError();
  413. }
  414. // Loop over all token managers (some of which are lexers)
  415. Enumeration tmIter = behavior.tokenManagers.elements();
  416. while (tmIter.hasMoreElements()) {
  417. TokenManager tm = (TokenManager)tmIter.nextElement();
  418. if (!tm.isReadOnly()) {
  419. // Write the token manager tokens as C++
  420. // this must appear before genTokenInterchange so that
  421. // labels are set on string literals
  422. genTokenTypes(tm);
  423. // Write the token manager tokens as plain text
  424. genTokenInterchange(tm);
  425. }
  426. exitIfError();
  427. }
  428. }
  429. catch (IOException e) {
  430. antlrTool.reportException(e, null);
  431. }
  432. }
  433. /** Generate code for the given grammar element.
  434. * @param blk The {...} action to generate
  435. */
  436. public void gen(ActionElement action) {
  437. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAction("+action+")");
  438. if ( action.isSemPred ) {
  439. genSemPred(action.actionText, action.line);
  440. }
  441. else {
  442. if ( grammar.hasSyntacticPredicate ) {
  443. println("if ( inputState->guessing==0 ) {");
  444. tabs++;
  445. }
  446. ActionTransInfo tInfo = new ActionTransInfo();
  447. String actionStr = processActionForSpecialSymbols(action.actionText,
  448. action.getLine(),
  449. currentRule, tInfo);
  450. if ( tInfo.refRuleRoot!=null ) {
  451. // Somebody referenced "#rule", make sure translated var is valid
  452. // assignment to #rule is left as a ref also, meaning that assignments
  453. // with no other refs like "#rule = foo();" still forces this code to be
  454. // generated (unnecessarily).
  455. println(tInfo.refRuleRoot + " = "+labeledElementASTType+"(currentAST.root);");
  456. }
  457. // dump the translated action
  458. genLineNo(action);
  459. printAction(actionStr);
  460. genLineNo2();
  461. if ( tInfo.assignToRoot ) {
  462. // Somebody did a "#rule=", reset internal currentAST.root
  463. println("currentAST.root = "+tInfo.refRuleRoot+";");
  464. // reset the child pointer too to be last sibling in sibling list
  465. // now use if else in stead of x ? y : z to shut CC 4.2 up.
  466. println("if ( "+tInfo.refRuleRoot+"!="+labeledElementASTInit+" &&");
  467. tabs++;
  468. println(tInfo.refRuleRoot+"->getFirstChild() != "+labeledElementASTInit+" )");
  469. println(" currentAST.child = "+tInfo.refRuleRoot+"->getFirstChild();");
  470. tabs--;
  471. println("else");
  472. tabs++;
  473. println("currentAST.child = "+tInfo.refRuleRoot+";");
  474. tabs--;
  475. println("currentAST.advanceChildToEnd();");
  476. }
  477. if ( grammar.hasSyntacticPredicate ) {
  478. tabs--;
  479. println("}");
  480. }
  481. }
  482. }
  483. /** Generate code for the given grammar element.
  484. * @param blk The "x|y|z|..." block to generate
  485. */
  486. public void gen(AlternativeBlock blk) {
  487. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen("+blk+")");
  488. println("{");
  489. genBlockPreamble(blk);
  490. genBlockInitAction(blk);
  491. // Tell AST generation to build subrule result
  492. String saveCurrentASTResult = currentASTResult;
  493. if (blk.getLabel() != null) {
  494. currentASTResult = blk.getLabel();
  495. }
  496. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  497. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
  498. genBlockFinish(howToFinish, throwNoViable);
  499. println("}");
  500. // Restore previous AST generation
  501. currentASTResult = saveCurrentASTResult;
  502. }
  503. /** Generate code for the given grammar element.
  504. * @param blk The block-end element to generate. Block-end
  505. * elements are synthesized by the grammar parser to represent
  506. * the end of a block.
  507. */
  508. public void gen(BlockEndElement end) {
  509. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
  510. }
  511. /** Generate code for the given grammar element.
  512. * Only called from lexer grammars.
  513. * @param blk The character literal reference to generate
  514. */
  515. public void gen(CharLiteralElement atom) {
  516. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
  517. System.out.println("genChar("+atom+")");
  518. if ( ! (grammar instanceof LexerGrammar) )
  519. antlrTool.error("cannot ref character literals in grammar: "+atom);
  520. if ( atom.getLabel() != null ) {
  521. println(atom.getLabel() + " = " + lt1Value + ";");
  522. }
  523. boolean oldsaveText = saveText;
  524. saveText = saveText && atom.getAutoGenType() == GrammarElement.AUTO_GEN_NONE;
  525. // if in lexer and ! on element, save buffer index to kill later
  526. if ( !saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG )
  527. println("_saveIndex = text.length();");
  528. print(atom.not ? "matchNot(" : "match(");
  529. _print(convertJavaToCppString( atom.atomText, true ));
  530. _println(" /* charlit */ );");
  531. if ( !saveText || atom.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
  532. println("text.erase(_saveIndex);"); // kill text atom put in buffer
  533. saveText = oldsaveText;
  534. }
  535. /** Generate code for the given grammar element.
  536. * Only called from lexer grammars.
  537. * @param blk The character-range reference to generate
  538. */
  539. public void gen(CharRangeElement r) {
  540. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
  541. System.out.println("genCharRangeElement("+r.beginText+".."+r.endText+")");
  542. if ( ! (grammar instanceof LexerGrammar) )
  543. antlrTool.error("cannot ref character range in grammar: "+r);
  544. if ( r.getLabel() != null && syntacticPredLevel == 0) {
  545. println(r.getLabel() + " = " + lt1Value + ";");
  546. }
  547. // Correctly take care of saveIndex stuff...
  548. boolean save = ( grammar instanceof LexerGrammar &&
  549. ( !saveText ||
  550. r.getAutoGenType() == GrammarElement.AUTO_GEN_BANG )
  551. );
  552. if (save)
  553. println("_saveIndex=text.length();");
  554. println("matchRange("+convertJavaToCppString(r.beginText,true)+
  555. ","+convertJavaToCppString(r.endText,true)+");");
  556. if (save)
  557. println("text.erase(_saveIndex);");
  558. }
  559. /** Generate the lexer C++ files */
  560. public void gen(LexerGrammar g) throws IOException {
  561. // If debugging, create a new sempred vector for this grammar
  562. if (g.debuggingOutput)
  563. semPreds = new Vector();
  564. if( g.charVocabulary.size() > 256 )
  565. antlrTool.warning(g.getFilename()+": Vocabularies of this size still experimental in C++ mode (vocabulary size now: "+g.charVocabulary.size()+")");
  566. setGrammar(g);
  567. if (!(grammar instanceof LexerGrammar)) {
  568. antlrTool.panic("Internal error generating lexer");
  569. }
  570. genBody(g);
  571. genInclude(g);
  572. }
  573. /** Generate code for the given grammar element.
  574. * @param blk The (...)+ block to generate
  575. */
  576. public void gen(OneOrMoreBlock blk) {
  577. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
  578. String label;
  579. String cnt;
  580. println("{ // ( ... )+");
  581. genBlockPreamble(blk);
  582. if ( blk.getLabel() != null ) {
  583. cnt = "_cnt_"+blk.getLabel();
  584. }
  585. else {
  586. cnt = "_cnt" + blk.ID;
  587. }
  588. println("int "+cnt+"=0;");
  589. if ( blk.getLabel() != null ) {
  590. label = blk.getLabel();
  591. }
  592. else {
  593. label = "_loop" + blk.ID;
  594. }
  595. println("for (;;) {");
  596. tabs++;
  597. // generate the init action for ()+ ()* inside the loop
  598. // this allows us to do usefull EOF checking...
  599. genBlockInitAction(blk);
  600. // Tell AST generation to build subrule result
  601. String saveCurrentASTResult = currentASTResult;
  602. if (blk.getLabel() != null) {
  603. currentASTResult = blk.getLabel();
  604. }
  605. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  606. // generate exit test if greedy set to false
  607. // and an alt is ambiguous with exit branch
  608. // or when lookahead derived purely from end-of-file
  609. // Lookahead analysis stops when end-of-file is hit,
  610. // returning set {epsilon}. Since {epsilon} is not
  611. // ambig with any real tokens, no error is reported
  612. // by deterministic() routines and we have to check
  613. // for the case where the lookahead depth didn't get
  614. // set to NONDETERMINISTIC (this only happens when the
  615. // FOLLOW contains real atoms + epsilon).
  616. boolean generateNonGreedyExitPath = false;
  617. int nonGreedyExitDepth = grammar.maxk;
  618. if ( !blk.greedy &&
  619. blk.exitLookaheadDepth<=grammar.maxk &&
  620. blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  621. {
  622. generateNonGreedyExitPath = true;
  623. nonGreedyExitDepth = blk.exitLookaheadDepth;
  624. }
  625. else if ( !blk.greedy &&
  626. blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  627. {
  628. generateNonGreedyExitPath = true;
  629. }
  630. // generate exit test if greedy set to false
  631. // and an alt is ambiguous with exit branch
  632. if ( generateNonGreedyExitPath ) {
  633. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
  634. System.out.println("nongreedy (...)+ loop; exit depth is "+
  635. blk.exitLookaheadDepth);
  636. }
  637. String predictExit =
  638. getLookaheadTestExpression(blk.exitCache,
  639. nonGreedyExitDepth);
  640. println("// nongreedy exit test");
  641. println("if ( "+cnt+">=1 && "+predictExit+") goto "+label+";");
  642. }
  643. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  644. genBlockFinish(
  645. howToFinish,
  646. "if ( "+cnt+">=1 ) { goto "+label+"; } else {" + throwNoViable + "}"
  647. );
  648. println(cnt+"++;");
  649. tabs--;
  650. println("}");
  651. println(label+":;");
  652. println("} // ( ... )+");
  653. // Restore previous AST generation
  654. currentASTResult = saveCurrentASTResult;
  655. }
  656. /** Generate the parser C++ file */
  657. public void gen(ParserGrammar g) throws IOException {
  658. // if debugging, set up a new vector to keep track of sempred
  659. // strings for this grammar
  660. if (g.debuggingOutput)
  661. semPreds = new Vector();
  662. setGrammar(g);
  663. if (!(grammar instanceof ParserGrammar)) {
  664. antlrTool.panic("Internal error generating parser");
  665. }
  666. genBody(g);
  667. genInclude(g);
  668. }
  669. /** Generate code for the given grammar element.
  670. * @param blk The rule-reference to generate
  671. */
  672. public void gen(RuleRefElement rr)
  673. {
  674. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
  675. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  676. if (rs == null || !rs.isDefined())
  677. {
  678. // Is this redundant???
  679. antlrTool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine(), rr.getColumn());
  680. return;
  681. }
  682. if (!(rs instanceof RuleSymbol))
  683. {
  684. // Is this redundant???
  685. antlrTool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine(), rr.getColumn());
  686. return;
  687. }
  688. genErrorTryForElement(rr);
  689. // AST value for labeled rule refs in tree walker.
  690. // This is not AST construction; it is just the input tree node value.
  691. if ( grammar instanceof TreeWalkerGrammar &&
  692. rr.getLabel() != null &&
  693. syntacticPredLevel == 0 )
  694. {
  695. println(rr.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : "+lt1Value+";");
  696. }
  697. // if in lexer and ! on rule ref or alt or rule, save buffer index to
  698. // kill later
  699. if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) )
  700. {
  701. println("_saveIndex = text.length();");
  702. }
  703. // Process return value assignment if any
  704. printTabs();
  705. if (rr.idAssign != null)
  706. {
  707. // Warn if the rule has no return type
  708. if (rs.block.returnAction == null)
  709. {
  710. antlrTool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine(), rr.getColumn());
  711. }
  712. _print(rr.idAssign + "=");
  713. } else {
  714. // Warn about return value if any, but not inside syntactic predicate
  715. if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
  716. {
  717. antlrTool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine(), rr.getColumn());
  718. }
  719. }
  720. // Call the rule
  721. GenRuleInvocation(rr);
  722. // if in lexer and ! on element or alt or rule, save buffer index to kill later
  723. if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  724. println("text.erase(_saveIndex);");
  725. }
  726. // if not in a syntactic predicate
  727. if (syntacticPredLevel == 0)
  728. {
  729. boolean doNoGuessTest = (
  730. grammar.hasSyntacticPredicate &&
  731. (
  732. grammar.buildAST && rr.getLabel() != null ||
  733. (genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
  734. )
  735. );
  736. if (doNoGuessTest) {
  737. println("if (inputState->guessing==0) {");
  738. tabs++;
  739. }
  740. if (grammar.buildAST && rr.getLabel() != null)
  741. {
  742. // always gen variable for rule return on labeled rules
  743. // RK: hmm do I know here if the returnAST needs a cast ?
  744. println(rr.getLabel() + "_AST = returnAST;");
  745. }
  746. if (genAST)
  747. {
  748. switch (rr.getAutoGenType())
  749. {
  750. case GrammarElement.AUTO_GEN_NONE:
  751. if( usingCustomAST )
  752. println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST(returnAST));");
  753. else
  754. println("astFactory->addASTChild( currentAST, returnAST );");
  755. break;
  756. case GrammarElement.AUTO_GEN_CARET:
  757. // FIXME: RK: I'm not so sure this should be an error..
  758. // I think it might actually work and be usefull at times.
  759. antlrTool.error("Internal: encountered ^ after rule reference");
  760. break;
  761. default:
  762. break;
  763. }
  764. }
  765. // if a lexer and labeled, Token label defined at rule level, just set it here
  766. if ( grammar instanceof LexerGrammar && rr.getLabel() != null )
  767. {
  768. println(rr.getLabel()+"=_returnToken;");
  769. }
  770. if (doNoGuessTest)
  771. {
  772. tabs--;
  773. println("}");
  774. }
  775. }
  776. genErrorCatchForElement(rr);
  777. }
  778. /** Generate code for the given grammar element.
  779. * @param blk The string-literal reference to generate
  780. */
  781. public void gen(StringLiteralElement atom) {
  782. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genString("+atom+")");
  783. // Variable declarations for labeled elements
  784. if (atom.getLabel()!=null && syntacticPredLevel == 0) {
  785. println(atom.getLabel() + " = " + lt1Value + ";");
  786. }
  787. // AST
  788. genElementAST(atom);
  789. // is there a bang on the literal?
  790. boolean oldsaveText = saveText;
  791. saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
  792. // matching
  793. genMatch(atom);
  794. saveText = oldsaveText;
  795. // tack on tree cursor motion if doing a tree walker
  796. if (grammar instanceof TreeWalkerGrammar) {
  797. println("_t = _t->getNextSibling();");
  798. }
  799. }
  800. /** Generate code for the given grammar element.
  801. * @param blk The token-range reference to generate
  802. */
  803. public void gen(TokenRangeElement r) {
  804. genErrorTryForElement(r);
  805. if ( r.getLabel()!=null && syntacticPredLevel == 0) {
  806. println(r.getLabel() + " = " + lt1Value + ";");
  807. }
  808. // AST
  809. genElementAST(r);
  810. // match
  811. println("matchRange("+r.beginText+","+r.endText+");");
  812. genErrorCatchForElement(r);
  813. }
  814. /** Generate code for the given grammar element.
  815. * @param blk The token-reference to generate
  816. */
  817. public void gen(TokenRefElement atom) {
  818. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
  819. if ( grammar instanceof LexerGrammar ) {
  820. antlrTool.panic("Token reference found in lexer");
  821. }
  822. genErrorTryForElement(atom);
  823. // Assign Token value to token label variable
  824. if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
  825. println(atom.getLabel() + " = " + lt1Value + ";");
  826. }
  827. // AST
  828. genElementAST(atom);
  829. // matching
  830. genMatch(atom);
  831. genErrorCatchForElement(atom);
  832. // tack on tree cursor motion if doing a tree walker
  833. if (grammar instanceof TreeWalkerGrammar) {
  834. println("_t = _t->getNextSibling();");
  835. }
  836. }
  837. public void gen(TreeElement t) {
  838. // save AST cursor
  839. println(labeledElementType+" __t" + t.ID + " = _t;");
  840. // If there is a label on the root, then assign that to the variable
  841. if (t.root.getLabel() != null) {
  842. println(t.root.getLabel() + " = (_t == ASTNULL) ? "+labeledElementASTInit+" : _t;");
  843. }
  844. // check for invalid modifiers ! and ^ on tree element roots
  845. if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG ) {
  846. antlrTool.error("Suffixing a root node with '!' is not implemented",
  847. grammar.getFilename(), t.getLine(), t.getColumn());
  848. t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
  849. }
  850. if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET ) {
  851. antlrTool.warning("Suffixing a root node with '^' is redundant; already a root",
  852. grammar.getFilename(), t.getLine(), t.getColumn());
  853. t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
  854. }
  855. // Generate AST variables
  856. genElementAST(t.root);
  857. if (grammar.buildAST) {
  858. // Save the AST construction state
  859. println(namespaceAntlr+"ASTPair __currentAST" + t.ID + " = currentAST;");
  860. // Make the next item added a child of the TreeElement root
  861. println("currentAST.root = currentAST.child;");
  862. println("currentAST.child = "+labeledElementASTInit+";");
  863. }
  864. // match root
  865. if ( t.root instanceof WildcardElement ) {
  866. println("if ( _t == ASTNULL ) throw "+namespaceAntlr+"MismatchedTokenException();");
  867. }
  868. else {
  869. genMatch(t.root);
  870. }
  871. // move to list of children
  872. println("_t = _t->getFirstChild();");
  873. // walk list of children, generating code for each
  874. for (int i=0; i<t.getAlternatives().size(); i++) {
  875. Alternative a = t.getAlternativeAt(i);
  876. AlternativeElement e = a.head;
  877. while ( e != null ) {
  878. e.generate();
  879. e = e.next;
  880. }
  881. }
  882. if (grammar.buildAST) {
  883. // restore the AST construction state to that just after the
  884. // tree root was added
  885. println("currentAST = __currentAST" + t.ID + ";");
  886. }
  887. // restore AST cursor
  888. println("_t = __t" + t.ID + ";");
  889. // move cursor to sibling of tree just parsed
  890. println("_t = _t->getNextSibling();");
  891. }
  892. /** Generate the tree-parser C++ files */
  893. public void gen(TreeWalkerGrammar g) throws IOException {
  894. setGrammar(g);
  895. if (!(grammar instanceof TreeWalkerGrammar)) {
  896. antlrTool.panic("Internal error generating tree-walker");
  897. }
  898. genBody(g);
  899. genInclude(g);
  900. }
  901. /** Generate code for the given grammar element.
  902. * @param wc The wildcard element to generate
  903. */
  904. public void gen(WildcardElement wc) {
  905. // Variable assignment for labeled elements
  906. if (wc.getLabel()!=null && syntacticPredLevel == 0) {
  907. println(wc.getLabel() + " = " + lt1Value + ";");
  908. }
  909. // AST
  910. genElementAST(wc);
  911. // Match anything but EOF
  912. if (grammar instanceof TreeWalkerGrammar) {
  913. println("if ( _t == "+labeledElementASTInit+" ) throw "+namespaceAntlr+"MismatchedTokenException();");
  914. }
  915. else if (grammar instanceof LexerGrammar) {
  916. if ( grammar instanceof LexerGrammar &&
  917. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  918. println("_saveIndex = text.length();");
  919. }
  920. println("matchNot(EOF/*_CHAR*/);");
  921. if ( grammar instanceof LexerGrammar &&
  922. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  923. println("text.erase(_saveIndex);"); // kill text atom put in buffer
  924. }
  925. }
  926. else {
  927. println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
  928. }
  929. // tack on tree cursor motion if doing a tree walker
  930. if (grammar instanceof TreeWalkerGrammar) {
  931. println("_t = _t->getNextSibling();");
  932. }
  933. }
  934. /** Generate code for the given grammar element.
  935. * @param blk The (...)* block to generate
  936. */
  937. public void gen(ZeroOrMoreBlock blk) {
  938. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
  939. println("{ // ( ... )*");
  940. genBlockPreamble(blk);
  941. String label;
  942. if ( blk.getLabel() != null ) {
  943. label = blk.getLabel();
  944. }
  945. else {
  946. label = "_loop" + blk.ID;
  947. }
  948. println("for (;;) {");
  949. tabs++;
  950. // generate the init action for ()+ ()* inside the loop
  951. // this allows us to do usefull EOF checking...
  952. genBlockInitAction(blk);
  953. // Tell AST generation to build subrule result
  954. String saveCurrentASTResult = currentASTResult;
  955. if (blk.getLabel() != null) {
  956. currentASTResult = blk.getLabel();
  957. }
  958. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  959. // generate exit test if greedy set to false
  960. // and an alt is ambiguous with exit branch
  961. // or when lookahead derived purely from end-of-file
  962. // Lookahead analysis stops when end-of-file is hit,
  963. // returning set {epsilon}. Since {epsilon} is not
  964. // ambig with any real tokens, no error is reported
  965. // by deterministic() routines and we have to check
  966. // for the case where the lookahead depth didn't get
  967. // set to NONDETERMINISTIC (this only happens when the
  968. // FOLLOW contains real atoms + epsilon).
  969. boolean generateNonGreedyExitPath = false;
  970. int nonGreedyExitDepth = grammar.maxk;
  971. if ( !blk.greedy &&
  972. blk.exitLookaheadDepth<=grammar.maxk &&
  973. blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  974. {
  975. generateNonGreedyExitPath = true;
  976. nonGreedyExitDepth = blk.exitLookaheadDepth;
  977. }
  978. else if ( !blk.greedy &&
  979. blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  980. {
  981. generateNonGreedyExitPath = true;
  982. }
  983. if ( generateNonGreedyExitPath ) {
  984. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) {
  985. System.out.println("nongreedy (...)* loop; exit depth is "+
  986. blk.exitLookaheadDepth);
  987. }
  988. String predictExit =
  989. getLookaheadTestExpression(blk.exitCache,
  990. nonGreedyExitDepth);
  991. println("// nongreedy exit test");
  992. println("if ("+predictExit+") goto "+label+";");
  993. }
  994. CppBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  995. genBlockFinish(howToFinish, "goto " + label + ";");
  996. tabs--;
  997. println("}");
  998. println(label+":;");
  999. println("} // ( ... )*");
  1000. // Restore previous AST generation
  1001. currentASTResult = saveCurrentASTResult;
  1002. }
  1003. /** Generate an alternative.
  1004. * @param alt The alternative to generate
  1005. * @param blk The block to which the alternative belongs
  1006. */
  1007. protected void genAlt(Alternative alt, AlternativeBlock blk)
  1008. {
  1009. // Save the AST generation state, and set it to that of the alt
  1010. boolean savegenAST = genAST;
  1011. genAST = genAST && alt.getAutoGen();
  1012. boolean oldsaveTest = saveText;
  1013. saveText = saveText && alt.getAutoGen();
  1014. // Reset the variable name map for the alternative
  1015. Hashtable saveMap = treeVariableMap;
  1016. treeVariableMap = new Hashtable();
  1017. // Generate try block around the alt for error handling
  1018. if (alt.exceptionSpec != null) {
  1019. println("try { // for error handling");
  1020. tabs++;
  1021. }
  1022. AlternativeElement elem = alt.head;
  1023. while ( !(elem instanceof BlockEndElement) ) {
  1024. elem.generate(); // alt can begin with anything. Ask target to gen.
  1025. elem = elem.next;
  1026. }
  1027. if ( genAST)
  1028. {
  1029. if (blk instanceof RuleBlock)
  1030. {
  1031. // Set the AST return value for the rule
  1032. RuleBlock rblk = (RuleBlock)blk;
  1033. if( usingCustomAST )
  1034. println(rblk.getRuleName() + "_AST = "+labeledElementASTType+"(currentAST.root);");
  1035. else
  1036. println(rblk.getRuleName() + "_AST = currentAST.root;");
  1037. }
  1038. else if (blk.getLabel() != null) {
  1039. // ### future: also set AST value for labeled subrules.
  1040. // println(blk.getLabel() + "_AST = "+labeledElementASTType+"(currentAST.root);");
  1041. antlrTool.warning("Labeled subrules are not implemented", grammar.getFilename(), blk.getLine(), blk.getColumn());
  1042. }
  1043. }
  1044. if (alt.exceptionSpec != null)
  1045. {
  1046. // close try block
  1047. tabs--;
  1048. println("}");
  1049. genErrorHandler(alt.exceptionSpec);
  1050. }
  1051. genAST = savegenAST;
  1052. saveText = oldsaveTest;
  1053. treeVariableMap = saveMap;
  1054. }
  1055. /** Generate all the bitsets to be used in the parser or lexer
  1056. * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
  1057. * and the BitSet object declarations like
  1058. * "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
  1059. * Note that most languages do not support object initialization inside a
  1060. * class definition, so other code-generators may have to separate the
  1061. * bitset declarations from the initializations (e.g., put the
  1062. * initializations in the generated constructor instead).
  1063. * @param bitsetList The list of bitsets to generate.
  1064. * @param maxVocabulary Ensure that each generated bitset can contain at
  1065. * least this value.
  1066. * @param prefix string glued in from of bitset names used for namespace
  1067. * qualifications.
  1068. */
  1069. protected void genBitsets(
  1070. Vector bitsetList,
  1071. int maxVocabulary,
  1072. String prefix
  1073. )
  1074. {
  1075. TokenManager tm = grammar.tokenManager;
  1076. println("");
  1077. for (int i = 0; i < bitsetList.size(); i++)
  1078. {
  1079. BitSet p = (BitSet)bitsetList.elementAt(i);
  1080. // Ensure that generated BitSet is large enough for vocabulary
  1081. p.growToInclude(maxVocabulary);
  1082. // initialization data
  1083. println(
  1084. "const unsigned long " + prefix + getBitsetName(i) + "_data_" + "[] = { " +
  1085. p.toStringOfHalfWords() +
  1086. " };"
  1087. );
  1088. // Dump the contents of the bitset in readable format...
  1089. String t = "// ";
  1090. for( int j = 0; j < tm.getVocabulary().size(); j++ )
  1091. {
  1092. if ( p.member( j ) )
  1093. {
  1094. if ( (grammar instanceof LexerGrammar) )
  1095. {
  1096. // only dump out for pure printable ascii.
  1097. if( ( 0x20 <= j ) && ( j < 0x7F ) )
  1098. t += charFormatter.escapeChar(j,true)+" ";
  1099. else
  1100. t += "0x"+Integer.toString(j,16)+" ";
  1101. }
  1102. else
  1103. t += tm.getTokenStringAt(j)+" ";
  1104. if( t.length() > 70 )
  1105. {
  1106. println(t);
  1107. t = "// ";
  1108. }
  1109. }
  1110. }
  1111. if ( t != "// " )
  1112. println(t);
  1113. // BitSet object
  1114. println(
  1115. "const "+namespaceAntlr+"BitSet " + prefix + getBitsetName(i) + "(" +
  1116. getBitsetName(i) + "_data_," + p.size()/32 +
  1117. ");"
  1118. );
  1119. }
  1120. }
  1121. protected void genBitsetsHeader(
  1122. Vector bitsetList,
  1123. int maxVocabulary
  1124. ) {
  1125. println("");
  1126. for (int i = 0; i < bitsetList.size(); i++)
  1127. {
  1128. BitSet p = (BitSet)bitsetList.elementAt(i);
  1129. // Ensure that generated BitSet is large enough for vocabulary
  1130. p.growToInclude(maxVocabulary);
  1131. // initialization data
  1132. println("static const unsigned long " + getBitsetName(i) + "_data_" + "[];");
  1133. // BitSet object
  1134. println("static const "+namespaceAntlr+"BitSet " + getBitsetName(i) + ";");
  1135. }
  1136. }
  1137. /** Generate the finish of a block, using a combination of the info
  1138. * returned from genCommonBlock() and the action to perform when
  1139. * no alts were taken
  1140. * @param howToFinish The return of genCommonBlock()
  1141. * @param noViableAction What to generate when no alt is taken
  1142. */
  1143. private void genBlockFinish(CppBlockFinishingInfo howToFinish, String noViableAction)
  1144. {
  1145. if (howToFinish.needAnErrorClause &&
  1146. (howToFinish.generatedAnIf || howToFinish.generatedSwitch)) {
  1147. if ( howToFinish.generatedAnIf ) {
  1148. println("else {");
  1149. }
  1150. else {
  1151. println("{");
  1152. }
  1153. tabs++;
  1154. println(noViableAction);
  1155. tabs--;
  1156. println("}");
  1157. }
  1158. if ( howToFinish.postscript!=null ) {
  1159. println(howToFinish.postscript);
  1160. }
  1161. }
  1162. /** Generate the initaction for a block, which may be a RuleBlock or a
  1163. * plain AlternativeBLock.
  1164. * @blk The block for which the preamble is to be generated.
  1165. */
  1166. protected void genBlockInitAction( AlternativeBlock blk )
  1167. {
  1168. // dump out init action
  1169. if ( blk.initAction!=null ) {
  1170. genLineNo(blk);
  1171. printAction(processActionForSpecialSymbols(blk.initAction, blk.line,
  1172. currentRule, null) );
  1173. genLineNo2();
  1174. }
  1175. }
  1176. /** Generate the header for a block, which may be a RuleBlock or a
  1177. * plain AlternativeBlock. This generates any variable declarations
  1178. * and syntactic-predicate-testing variables.
  1179. * @blk The block for which the preamble is to be generated.
  1180. */
  1181. protected void genBlockPreamble(AlternativeBlock blk) {
  1182. // define labels for rule blocks.
  1183. if ( blk instanceof RuleBlock ) {
  1184. RuleBlock rblk = (RuleBlock)blk;
  1185. if ( rblk.labeledElements!=null ) {
  1186. for (int i=0; i<rblk.labeledElements.size(); i++) {
  1187. AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
  1188. //System.out.println("looking at labeled element: "+a);
  1189. // Variables for labeled rule refs and subrules are different than
  1190. // variables for grammar atoms. This test is a little tricky because
  1191. // we want to get all rule refs and ebnf, but not rule blocks or
  1192. // syntactic predicates
  1193. if (
  1194. a instanceof RuleRefElement ||
  1195. a instanceof AlternativeBlock &&
  1196. !(a instanceof RuleBlock) &&
  1197. !(a instanceof SynPredBlock) )
  1198. {
  1199. if ( !(a instanceof RuleRefElement) &&
  1200. ((AlternativeBlock)a).not &&
  1201. analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
  1202. ) {
  1203. // Special case for inverted subrules that will be
  1204. // inlined. Treat these like token or char literal
  1205. // references
  1206. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  1207. if (grammar.buildAST) {
  1208. genASTDeclaration( a );
  1209. }
  1210. }
  1211. else
  1212. {
  1213. if (grammar.buildAST)
  1214. {
  1215. // Always gen AST variables for labeled elements,
  1216. // even if the element itself is marked with !
  1217. genASTDeclaration( a );
  1218. }
  1219. if ( grammar instanceof LexerGrammar )
  1220. println(namespaceAntlr+"RefToken "+a.getLabel()+";");
  1221. if (grammar instanceof TreeWalkerGrammar) {
  1222. // always generate rule-ref variables for tree walker
  1223. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  1224. }
  1225. }
  1226. }
  1227. else
  1228. {
  1229. // It is a token or literal reference. Generate the
  1230. // correct variable type for this grammar
  1231. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  1232. // In addition, generate *_AST variables if building ASTs
  1233. if (grammar.buildAST)
  1234. {
  1235. if (a instanceof GrammarAtom &&
  1236. ((GrammarAtom)a).getASTNodeType() != null )
  1237. {
  1238. GrammarAtom ga = (GrammarAtom)a;
  1239. genASTDeclaration( a, "Ref"+ga.getASTNodeType() );
  1240. }
  1241. else
  1242. {
  1243. genASTDeclaration( a );
  1244. }
  1245. }
  1246. }
  1247. }
  1248. }
  1249. }
  1250. }
  1251. public void genBody(LexerGrammar g) throws IOException
  1252. {
  1253. outputFile = grammar.getClassName() + ".cpp";
  1254. outputLine = 1;
  1255. currentOutput = antlrTool.openOutputFile(outputFile);
  1256. //SAS: changed for proper text file io
  1257. genAST = false; // no way to gen trees.
  1258. saveText = true; // save consumed characters.
  1259. tabs=0;
  1260. // Generate header common to all C++ output files
  1261. genHeader(outputFile);
  1262. printHeaderAction(preIncludeCpp);
  1263. // Generate header specific to lexer C++ file
  1264. println("#include \"" + grammar.getClassName() + ".hpp\"");
  1265. println("#include <antlr/CharBuffer.hpp>");
  1266. println("#include <antlr/TokenStreamException.hpp>");
  1267. println("#include <antlr/TokenStreamIOException.hpp>");
  1268. println("#include <antlr/TokenStreamRecognitionException.hpp>");
  1269. println("#include <antlr/CharStreamException.hpp>");
  1270. println("#include <antlr/CharStreamIOException.hpp>");
  1271. println("#include <antlr/NoViableAltForCharException.hpp>");
  1272. if (grammar.debuggingOutput)
  1273. println("#include <antlr/DebuggingInputBuffer.hpp>");
  1274. println("");
  1275. printHeaderAction(postIncludeCpp);
  1276. if (nameSpace != null)
  1277. nameSpace.emitDeclarations(currentOutput);
  1278. // Generate user-defined lexer file preamble
  1279. printAction(grammar.preambleAction);
  1280. // Generate lexer class definition
  1281. String sup=null;
  1282. if ( grammar.superClass!=null ) {
  1283. sup = grammar.superClass;
  1284. }
  1285. else {
  1286. sup = grammar.getSuperClass();
  1287. if (sup.lastIndexOf('.') != -1)
  1288. sup = sup.substring(sup.lastIndexOf('.')+1);
  1289. sup = namespaceAntlr + sup;
  1290. }
  1291. if( noConstructors )
  1292. {
  1293. println("#if 0");
  1294. println("// constructor creation turned of with 'noConstructor' option");
  1295. }
  1296. //
  1297. // Generate the constructor from InputStream
  1298. //
  1299. println(grammar.getClassName() + "::" + grammar.getClassName() + "(" + namespaceStd + "istream& in)");
  1300. tabs++;
  1301. // if debugging, wrap the input buffer in a debugger
  1302. if (grammar.debuggingOutput)
  1303. println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(new "+namespaceAntlr+"CharBuffer(in)),"+g.caseSensitive+")");
  1304. else
  1305. println(": " + sup + "(new "+namespaceAntlr+"CharBuffer(in),"+g.caseSensitive+")");
  1306. tabs--;
  1307. println("{");
  1308. tabs++;
  1309. // if debugging, set up array variables and call user-overridable
  1310. // debugging setup method
  1311. if ( grammar.debuggingOutput ) {
  1312. println("setRuleNames(_ruleNames);");
  1313. println("setSemPredNames(_semPredNames);");
  1314. println("setupDebugging();");
  1315. }
  1316. // println("setCaseSensitive("+g.caseSensitive+");");
  1317. println("initLiterals();");
  1318. tabs--;
  1319. println("}");
  1320. println("");
  1321. // Generate the constructor from InputBuffer
  1322. println(grammar.getClassName() + "::" + grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib)");
  1323. tabs++;
  1324. // if debugging, wrap the input buffer in a debugger
  1325. if (grammar.debuggingOutput)
  1326. println(": " + sup + "(new "+namespaceAntlr+"DebuggingInputBuffer(ib),"+g.caseSensitive+")");
  1327. else
  1328. println(": " + sup + "(ib,"+g.caseSensitive+")");
  1329. tabs--;
  1330. println("{");
  1331. tabs++;
  1332. // if debugging, set up array variables and call user-overridable
  1333. // debugging setup method
  1334. if ( grammar.debuggingOutput ) {
  1335. println("setRuleNames(_ruleNames);");
  1336. println("setSemPredNames(_semPredNames);");
  1337. println("setupDebugging();");
  1338. }
  1339. // println("setCaseSensitive("+g.caseSensitive+");");
  1340. println("initLiterals();");
  1341. tabs--;
  1342. println("}");
  1343. println("");
  1344. // Generate the constructor from LexerSharedInputState
  1345. println(grammar.getClassName() + "::" + grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state)");
  1346. tabs++;
  1347. println(": " + sup + "(state,"+g.caseSensitive+")");
  1348. tabs--;
  1349. println("{");
  1350. tabs++;
  1351. // if debugging, set up array variables and call user-overridable
  1352. // debugging setup method
  1353. if ( grammar.debuggingOutput ) {
  1354. println("setRuleNames(_ruleNames);");
  1355. println("setSemPredNames(_semPredNames);");
  1356. println("setupDebugging();");
  1357. }
  1358. // println("setCaseSensitive("+g.caseSensitive+");");
  1359. println("initLiterals();");
  1360. tabs--;
  1361. println("}");
  1362. println("");
  1363. if( noConstructors )
  1364. {
  1365. println("// constructor creation turned of with 'noConstructor' option");
  1366. println("#endif");
  1367. }
  1368. println("void " + grammar.getClassName() + "::initLiterals()");
  1369. println("{");
  1370. tabs++;
  1371. // Generate the initialization of the map
  1372. // containing the string literals used in the lexer
  1373. // The literals variable itself is in CharScanner
  1374. Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
  1375. while ( keys.hasMoreElements() ) {
  1376. String key = (String)keys.nextElement();
  1377. if ( key.charAt(0) != '"' ) {
  1378. continue;
  1379. }
  1380. TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
  1381. if ( sym instanceof StringLiteralSymbol ) {
  1382. StringLiteralSymbol s = (StringLiteralSymbol)sym;
  1383. println("literals["+s.getId()+"] = "+s.getTokenType()+";");
  1384. }
  1385. }
  1386. // Generate the setting of various generated options.
  1387. tabs--;
  1388. println("}");
  1389. Enumeration ids;
  1390. // generate the rule name array for debugging
  1391. if (grammar.debuggingOutput) {
  1392. println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
  1393. tabs++;
  1394. ids = grammar.rules.elements();
  1395. int ruleNum=0;
  1396. while ( ids.hasMoreElements() ) {
  1397. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1398. if ( sym instanceof RuleSymbol)
  1399. println("\""+((RuleSymbol)sym).getId()+"\",");
  1400. }
  1401. println("0");
  1402. tabs--;
  1403. println("};");
  1404. }
  1405. // Generate nextToken() rule.
  1406. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  1407. // user-defined lexer rules.
  1408. genNextToken();
  1409. // Generate code for each rule in the lexer
  1410. ids = grammar.rules.elements();
  1411. int ruleNum=0;
  1412. while ( ids.hasMoreElements() ) {
  1413. RuleSymbol sym = (RuleSymbol) ids.nextElement();
  1414. // Don't generate the synthetic rules
  1415. if (!sym.getId().equals("mnextToken")) {
  1416. genRule(sym, false, ruleNum++, grammar.getClassName() + "::");
  1417. }
  1418. exitIfError();
  1419. }
  1420. // Generate the semantic predicate map for debugging
  1421. if (grammar.debuggingOutput)
  1422. genSemPredMap(grammar.getClassName() + "::");
  1423. // Generate the bitsets used throughout the lexer
  1424. genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size(), grammar.getClassName() + "::" );
  1425. println("");
  1426. if (nameSpace != null)
  1427. nameSpace.emitClosures(currentOutput);
  1428. // Close the lexer output stream
  1429. currentOutput.close();
  1430. currentOutput = null;
  1431. }
  1432. public void genInitFactory( Grammar g )
  1433. {
  1434. // Generate the method to initialize an ASTFactory when we're
  1435. // building AST's
  1436. String param_name = "factory ";
  1437. if( ! g.buildAST )
  1438. param_name = "";
  1439. println("void "+ g.getClassName() + "::initializeASTFactory( "+namespaceAntlr+"ASTFactory& "+param_name+")");
  1440. println("{");
  1441. tabs++;
  1442. if( g.buildAST )
  1443. {
  1444. // sort out custom AST types... synchronize token manager with token
  1445. // specs on rules (and other stuff we were able to see from
  1446. // action.g) (imperfect of course)
  1447. TokenManager tm = grammar.tokenManager;
  1448. Enumeration tokens = tm.getTokenSymbolKeys();
  1449. while( tokens.hasMoreElements() )
  1450. {
  1451. String tok = (String)tokens.nextElement();
  1452. TokenSymbol ts = tm.getTokenSymbol(tok);
  1453. // if we have a custom type and there's not a more local override
  1454. // of the tokentype then mark this as the type for the tokentype
  1455. if( ts.getASTNodeType() != null )
  1456. {
  1457. // ensure capacity with this pseudo vector...
  1458. astTypes.ensureCapacity(ts.getTokenType());
  1459. String type = (String)astTypes.elementAt(ts.getTokenType());
  1460. if( type == null )
  1461. astTypes.setElementAt(ts.getASTNodeType(),ts.getTokenType());
  1462. else
  1463. {
  1464. // give a warning over action taken if the types are unequal
  1465. if( ! ts.getASTNodeType().equals(type) )
  1466. {
  1467. antlrTool.warning("Token "+tok+" taking most specific AST type",grammar.getFilename(),1,1);
  1468. antlrTool.warning(" using "+type+" ignoring "+ts.getASTNodeType(),grammar.getFilename(),1,1);
  1469. }
  1470. }
  1471. }
  1472. }
  1473. // now actually write out all the registered types. (except the default
  1474. // type.
  1475. for( int i = 0; i < astTypes.size(); i++ )
  1476. {
  1477. String type = (String)astTypes.elementAt(i);
  1478. if( type != null )
  1479. {
  1480. println("factory.registerFactory("+i
  1481. +", \""+type+"\", "+type+"::factory);");
  1482. }
  1483. }
  1484. println("factory.setMaxNodeType("+grammar.tokenManager.maxTokenType()+");");
  1485. }
  1486. tabs--;
  1487. println("}");
  1488. }
  1489. // FIXME: and so why are we passing here a g param while inside
  1490. // we merrily use the global grammar.
  1491. public void genBody(ParserGrammar g) throws IOException
  1492. {
  1493. // Open the output stream for the parser and set the currentOutput
  1494. outputFile = grammar.getClassName() + ".cpp";
  1495. outputLine = 1;
  1496. currentOutput = antlrTool.openOutputFile(outputFile);
  1497. genAST = grammar.buildAST;
  1498. tabs = 0;
  1499. // Generate the header common to all output files.
  1500. genHeader(outputFile);
  1501. printHeaderAction(preIncludeCpp);
  1502. // Generate header for the parser
  1503. println("#include \"" + grammar.getClassName() + ".hpp\"");
  1504. println("#include <antlr/NoViableAltException.hpp>");
  1505. println("#include <antlr/SemanticException.hpp>");
  1506. println("#include <antlr/ASTFactory.hpp>");
  1507. printHeaderAction(postIncludeCpp);
  1508. if (nameSpace != null)
  1509. nameSpace.emitDeclarations(currentOutput);
  1510. // Output the user-defined parser preamble
  1511. printAction(grammar.preambleAction);
  1512. String sup=null;
  1513. if ( grammar.superClass!=null )
  1514. sup = grammar.superClass;
  1515. else {
  1516. sup = grammar.getSuperClass();
  1517. if (sup.lastIndexOf('.') != -1)
  1518. sup = sup.substring(sup.lastIndexOf('.')+1);
  1519. sup = namespaceAntlr + sup;
  1520. }
  1521. // set up an array of all the rule names so the debugger can
  1522. // keep track of them only by number -- less to store in tree...
  1523. if (grammar.debuggingOutput) {
  1524. println("const char* "+grammar.getClassName()+"::_ruleNames[] = {");
  1525. tabs++;
  1526. Enumeration ids = grammar.rules.elements();
  1527. int ruleNum=0;
  1528. while ( ids.hasMoreElements() ) {
  1529. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1530. if ( sym instanceof RuleSymbol)
  1531. println("\""+((RuleSymbol)sym).getId()+"\",");
  1532. }
  1533. println("0");
  1534. tabs--;
  1535. println("};");
  1536. }
  1537. // Generate _initialize function
  1538. // disabled since it isn't used anymore..
  1539. // println("void " + grammar.getClassName() + "::_initialize(void)");
  1540. // println("{");
  1541. // tabs++;
  1542. // if debugging, set up arrays and call the user-overridable
  1543. // debugging setup method
  1544. // if ( grammar.debuggingOutput ) {
  1545. // println("setRuleNames(_ruleNames);");
  1546. // println("setSemPredNames(_semPredNames);");
  1547. // println("setupDebugging();");
  1548. // }
  1549. // tabs--;
  1550. // println("}");
  1551. if( noConstructors )
  1552. {
  1553. println("#if 0");
  1554. println("// constructor creation turned of with 'noConstructor' option");
  1555. }
  1556. // Generate parser class constructor from TokenBuffer
  1557. print(grammar.getClassName() + "::" + grammar.getClassName());
  1558. println("("+namespaceAntlr+"TokenBuffer& tokenBuf, int k)");
  1559. println(": " + sup + "(tokenBuf,k)");
  1560. println("{");
  1561. // tabs++;
  1562. // println("_initialize();");
  1563. // tabs--;
  1564. println("}");
  1565. println("");
  1566. print(grammar.getClassName() + "::" + grammar.getClassName());
  1567. println("("+namespaceAntlr+"TokenBuffer& tokenBuf)");
  1568. println(": " + sup + "(tokenBuf," + grammar.maxk + ")");
  1569. println("{");
  1570. // tabs++;
  1571. // println("_initialize();");
  1572. // tabs--;
  1573. println("}");
  1574. println("");
  1575. // Generate parser class constructor from TokenStream
  1576. print(grammar.getClassName() + "::" + grammar.getClassName());
  1577. println("("+namespaceAntlr+"TokenStream& lexer, int k)");
  1578. println(": " + sup + "(lexer,k)");
  1579. println("{");
  1580. // tabs++;
  1581. // println("_initialize();");
  1582. // tabs--;
  1583. println("}");
  1584. println("");
  1585. print(grammar.getClassName() + "::" + grammar.getClassName());
  1586. println("("+namespaceAntlr+"TokenStream& lexer)");
  1587. println(": " + sup + "(lexer," + grammar.maxk + ")");
  1588. println("{");
  1589. // tabs++;
  1590. // println("_initialize();");
  1591. // tabs--;
  1592. println("}");
  1593. println("");
  1594. print(grammar.getClassName() + "::" + grammar.getClassName());
  1595. println("(const "+namespaceAntlr+"ParserSharedInputState& state)");
  1596. println(": " + sup + "(state," + grammar.maxk + ")");
  1597. println("{");
  1598. // tabs++;
  1599. // println("_initialize();");
  1600. // tabs--;
  1601. println("}");
  1602. println("");
  1603. if( noConstructors )
  1604. {
  1605. println("// constructor creation turned of with 'noConstructor' option");
  1606. println("#endif");
  1607. }
  1608. astTypes = new Vector();
  1609. // Generate code for each rule in the grammar
  1610. Enumeration ids = grammar.rules.elements();
  1611. int ruleNum=0;
  1612. while ( ids.hasMoreElements() ) {
  1613. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1614. if ( sym instanceof RuleSymbol) {
  1615. RuleSymbol rs = (RuleSymbol)sym;
  1616. genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
  1617. }
  1618. exitIfError();
  1619. }
  1620. genInitFactory( g );
  1621. // Generate the token names
  1622. genTokenStrings(grammar.getClassName() + "::");
  1623. // Generate the bitsets used throughout the grammar
  1624. genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );
  1625. // Generate the semantic predicate map for debugging
  1626. if (grammar.debuggingOutput)
  1627. genSemPredMap(grammar.getClassName() + "::");
  1628. // Close class definition
  1629. println("");
  1630. println("");
  1631. if (nameSpace != null)
  1632. nameSpace.emitClosures(currentOutput);
  1633. // Close the parser output stream
  1634. currentOutput.close();
  1635. currentOutput = null;
  1636. }
  1637. public void genBody(TreeWalkerGrammar g) throws IOException
  1638. {
  1639. // Open the output stream for the parser and set the currentOutput
  1640. outputFile = grammar.getClassName() + ".cpp";
  1641. outputLine = 1;
  1642. currentOutput = antlrTool.openOutputFile(outputFile);
  1643. //SAS: changed for proper text file io
  1644. genAST = grammar.buildAST;
  1645. tabs = 0;
  1646. // Generate the header common to all output files.
  1647. genHeader(outputFile);
  1648. printHeaderAction(preIncludeCpp);
  1649. // Generate header for the parser
  1650. println("#include \"" + grammar.getClassName() + ".hpp\"");
  1651. println("#include <antlr/Token.hpp>");
  1652. println("#include <antlr/AST.hpp>");
  1653. println("#include <antlr/NoViableAltException.hpp>");
  1654. println("#include <antlr/MismatchedTokenException.hpp>");
  1655. println("#include <antlr/SemanticException.hpp>");
  1656. println("#include <antlr/BitSet.hpp>");
  1657. printHeaderAction(postIncludeCpp);
  1658. if (nameSpace != null)
  1659. nameSpace.emitDeclarations(currentOutput);
  1660. // Output the user-defined parser premamble
  1661. printAction(grammar.preambleAction);
  1662. // Generate parser class definition
  1663. String sup = null;
  1664. if ( grammar.superClass!=null ) {
  1665. sup = grammar.superClass;
  1666. }
  1667. else {
  1668. sup = grammar.getSuperClass();
  1669. if (sup.lastIndexOf('.') != -1)
  1670. sup = sup.substring(sup.lastIndexOf('.')+1);
  1671. sup = namespaceAntlr + sup;
  1672. }
  1673. if( noConstructors )
  1674. {
  1675. println("#if 0");
  1676. println("// constructor creation turned of with 'noConstructor' option");
  1677. }
  1678. // Generate default parser class constructor
  1679. println(grammar.getClassName() + "::" + grammar.getClassName() + "()");
  1680. println("\t: "+namespaceAntlr+"TreeParser() {");
  1681. tabs++;
  1682. // println("setTokenNames(_tokenNames);");
  1683. tabs--;
  1684. println("}");
  1685. if( noConstructors )
  1686. {
  1687. println("// constructor creation turned of with 'noConstructor' option");
  1688. println("#endif");
  1689. }
  1690. println("");
  1691. astTypes = new Vector();
  1692. // Generate code for each rule in the grammar
  1693. Enumeration ids = grammar.rules.elements();
  1694. int ruleNum=0;
  1695. String ruleNameInits = "";
  1696. while ( ids.hasMoreElements() ) {
  1697. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1698. if ( sym instanceof RuleSymbol) {
  1699. RuleSymbol rs = (RuleSymbol)sym;
  1700. genRule(rs, rs.references.size()==0, ruleNum++, grammar.getClassName() + "::");
  1701. }
  1702. exitIfError();
  1703. }
  1704. // Generate the ASTFactory initialization function
  1705. genInitFactory( grammar );
  1706. // Generate the token names
  1707. genTokenStrings(grammar.getClassName() + "::");
  1708. // Generate the bitsets used throughout the grammar
  1709. genBitsets(bitsetsUsed, grammar.tokenManager.maxTokenType(), grammar.getClassName() + "::" );
  1710. // Close class definition
  1711. println("");
  1712. println("");
  1713. if (nameSpace != null)
  1714. nameSpace.emitClosures(currentOutput);
  1715. // Close the parser output stream
  1716. currentOutput.close();
  1717. currentOutput = null;
  1718. }
  1719. /** Generate a series of case statements that implement a BitSet test.
  1720. * @param p The Bitset for which cases are to be generated
  1721. */
  1722. protected void genCases(BitSet p) {
  1723. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCases("+p+")");
  1724. int[] elems;
  1725. elems = p.toArray();
  1726. // Wrap cases four-per-line for lexer, one-per-line for parser
  1727. int wrap = 1; //(grammar instanceof LexerGrammar) ? 4 : 1;
  1728. int j=1;
  1729. boolean startOfLine = true;
  1730. for (int i = 0; i < elems.length; i++) {
  1731. if (j==1) {
  1732. print("");
  1733. } else {
  1734. _print(" ");
  1735. }
  1736. _print("case " + getValueString(elems[i]) + ":");
  1737. if (j==wrap) {
  1738. _println("");
  1739. startOfLine = true;
  1740. j=1;
  1741. }
  1742. else {
  1743. j++;
  1744. startOfLine = false;
  1745. }
  1746. }
  1747. if (!startOfLine) {
  1748. _println("");
  1749. }
  1750. }
  1751. /** Generate common code for a block of alternatives; return a postscript
  1752. * that needs to be generated at the end of the block. Other routines
  1753. * may append else-clauses and such for error checking before the postfix
  1754. * is generated.
  1755. * If the grammar is a lexer, then generate alternatives in an order where
  1756. * alternatives requiring deeper lookahead are generated first, and
  1757. * EOF in the lookahead set reduces the depth of the lookahead.
  1758. * @param blk The block to generate
  1759. * @param noTestForSingle If true, then it does not generate a test for a single alternative.
  1760. */
  1761. public CppBlockFinishingInfo genCommonBlock(
  1762. AlternativeBlock blk,
  1763. boolean noTestForSingle )
  1764. {
  1765. int nIF=0;
  1766. boolean createdLL1Switch = false;
  1767. int closingBracesOfIFSequence = 0;
  1768. CppBlockFinishingInfo finishingInfo = new CppBlockFinishingInfo();
  1769. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genCommonBlk("+blk+")");
  1770. // Save the AST generation state, and set it to that of the block
  1771. boolean savegenAST = genAST;
  1772. genAST = genAST && blk.getAutoGen();
  1773. boolean oldsaveTest = saveText;
  1774. saveText = saveText && blk.getAutoGen();
  1775. // Is this block inverted? If so, generate special-case code
  1776. if ( blk.not &&
  1777. analyzer.subruleCanBeInverted(blk, grammar instanceof LexerGrammar) )
  1778. {
  1779. Lookahead p = analyzer.look(1, blk);
  1780. // Variable assignment for labeled elements
  1781. if (blk.getLabel() != null && syntacticPredLevel == 0) {
  1782. println(blk.getLabel() + " = " + lt1Value + ";");
  1783. }
  1784. // AST
  1785. genElementAST(blk);
  1786. String astArgs="";
  1787. if (grammar instanceof TreeWalkerGrammar) {
  1788. if( usingCustomAST )
  1789. astArgs=namespaceAntlr+"RefAST"+"(_t),";
  1790. else
  1791. astArgs="_t,";
  1792. }
  1793. // match the bitset for the alternative
  1794. println("match(" + astArgs + getBitsetName(markBitsetForGen(p.fset)) + ");");
  1795. // tack on tree cursor motion if doing a tree walker
  1796. if (grammar instanceof TreeWalkerGrammar)
  1797. {
  1798. println("_t = _t->getNextSibling();");
  1799. }
  1800. return finishingInfo;
  1801. }
  1802. // Special handling for single alt
  1803. if (blk.getAlternatives().size() == 1)
  1804. {
  1805. Alternative alt = blk.getAlternativeAt(0);
  1806. // Generate a warning if there is a synPred for single alt.
  1807. if (alt.synPred != null)
  1808. {
  1809. antlrTool.warning(
  1810. "Syntactic predicate superfluous for single alternative",
  1811. grammar.getFilename(),
  1812. blk.getAlternativeAt(0).synPred.getLine(),
  1813. blk.getAlternativeAt(0).synPred.getColumn()
  1814. );
  1815. }
  1816. if (noTestForSingle)
  1817. {
  1818. if (alt.semPred != null)
  1819. {
  1820. // Generate validating predicate
  1821. genSemPred(alt.semPred, blk.line);
  1822. }
  1823. genAlt(alt, blk);
  1824. return finishingInfo;
  1825. }
  1826. }
  1827. // count number of simple LL(1) cases; only do switch for
  1828. // many LL(1) cases (no preds, no end of token refs)
  1829. // We don't care about exit paths for (...)*, (...)+
  1830. // because we don't explicitly have a test for them
  1831. // as an alt in the loop.
  1832. //
  1833. // Also, we now count how many unicode lookahead sets
  1834. // there are--they must be moved to DEFAULT or ELSE
  1835. // clause.
  1836. int nLL1 = 0;
  1837. for (int i=0; i<blk.getAlternatives().size(); i++)
  1838. {
  1839. Alternative a = blk.getAlternativeAt(i);
  1840. if ( suitableForCaseExpression(a) )
  1841. nLL1++;
  1842. }
  1843. // do LL(1) cases
  1844. if ( nLL1 >= makeSwitchThreshold )
  1845. {
  1846. // Determine the name of the item to be compared
  1847. String testExpr = lookaheadString(1);
  1848. createdLL1Switch = true;
  1849. // when parsing trees, convert null to valid tree node with NULL lookahead
  1850. if ( grammar instanceof TreeWalkerGrammar )
  1851. {
  1852. println("if (_t == "+labeledElementASTInit+" )");
  1853. tabs++;
  1854. println("_t = ASTNULL;");
  1855. tabs--;
  1856. }
  1857. println("switch ( "+testExpr+") {");
  1858. for (int i=0; i<blk.alternatives.size(); i++)
  1859. {
  1860. Alternative alt = blk.getAlternativeAt(i);
  1861. // ignore any non-LL(1) alts, predicated alts or end-of-token alts
  1862. // or end-of-token alts for case expressions
  1863. if ( !suitableForCaseExpression(alt) )
  1864. {
  1865. continue;
  1866. }
  1867. Lookahead p = alt.cache[1];
  1868. if (p.fset.degree() == 0 && !p.containsEpsilon())
  1869. {
  1870. antlrTool.warning("Alternate omitted due to empty prediction set",
  1871. grammar.getFilename(),
  1872. alt.head.getLine(), alt.head.getColumn());
  1873. }
  1874. else
  1875. {
  1876. genCases(p.fset);
  1877. println("{");
  1878. tabs++;
  1879. genAlt(alt, blk);
  1880. println("break;");
  1881. tabs--;
  1882. println("}");
  1883. }
  1884. }
  1885. println("default:");
  1886. tabs++;
  1887. }
  1888. // do non-LL(1) and nondeterministic cases
  1889. // This is tricky in the lexer, because of cases like:
  1890. // STAR : '*' ;
  1891. // ASSIGN_STAR : "*=";
  1892. // Since nextToken is generated without a loop, then the STAR will
  1893. // have end-of-token as it's lookahead set for LA(2). So, we must generate the
  1894. // alternatives containing trailing end-of-token in their lookahead sets *after*
  1895. // the alternatives without end-of-token. This implements the usual
  1896. // lexer convention that longer matches come before shorter ones, e.g.
  1897. // "*=" matches ASSIGN_STAR not STAR
  1898. //
  1899. // For non-lexer grammars, this does not sort the alternates by depth
  1900. // Note that alts whose lookahead is purely end-of-token at k=1 end up
  1901. // as default or else clauses.
  1902. int startDepth = (grammar instanceof LexerGrammar) ? grammar.maxk : 0;
  1903. for (int altDepth = startDepth; altDepth >= 0; altDepth--) {
  1904. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("checking depth "+altDepth);
  1905. for (int i=0; i<blk.alternatives.size(); i++) {
  1906. Alternative alt = blk.getAlternativeAt(i);
  1907. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genAlt: "+i);
  1908. // if we made a switch above, ignore what we already took care
  1909. // of. Specifically, LL(1) alts with no preds
  1910. // that do not have end-of-token in their prediction set
  1911. if ( createdLL1Switch &&
  1912. suitableForCaseExpression(alt) )
  1913. {
  1914. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
  1915. System.out.println("ignoring alt because it was in the switch");
  1916. continue;
  1917. }
  1918. String e;
  1919. boolean unpredicted = false;
  1920. if (grammar instanceof LexerGrammar) {
  1921. // Calculate the "effective depth" of the alt, which is the max
  1922. // depth at which cache[depth]!=end-of-token
  1923. int effectiveDepth = alt.lookaheadDepth;
  1924. if (effectiveDepth == GrammarAnalyzer.NONDETERMINISTIC)
  1925. {
  1926. // use maximum lookahead
  1927. effectiveDepth = grammar.maxk;
  1928. }
  1929. while ( effectiveDepth >= 1 &&
  1930. alt.cache[effectiveDepth].containsEpsilon() )
  1931. {
  1932. effectiveDepth--;
  1933. }
  1934. // Ignore alts whose effective depth is other than the ones we
  1935. // are generating for this iteration.
  1936. if (effectiveDepth != altDepth)
  1937. {
  1938. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR )
  1939. System.out.println("ignoring alt because effectiveDepth!=altDepth;"+effectiveDepth+"!="+altDepth);
  1940. continue;
  1941. }
  1942. unpredicted = lookaheadIsEmpty(alt, effectiveDepth);
  1943. e = getLookaheadTestExpression(alt, effectiveDepth);
  1944. }
  1945. else
  1946. {
  1947. unpredicted = lookaheadIsEmpty(alt, grammar.maxk);
  1948. e = getLookaheadTestExpression(alt, grammar.maxk);
  1949. }
  1950. // Was it a big unicode range that forced unsuitability
  1951. // for a case expression?
  1952. if ( alt.cache[1].fset.degree() > caseSizeThreshold &&
  1953. suitableForCaseExpression(alt))
  1954. {
  1955. if ( nIF==0 )
  1956. {
  1957. // generate this only for the first if the elseif's
  1958. // are covered by this one
  1959. if ( grammar instanceof TreeWalkerGrammar ) {
  1960. println("if (_t == "+labeledElementASTInit+" )");
  1961. tabs++;
  1962. println("_t = ASTNULL;");
  1963. tabs--;
  1964. }
  1965. println("if " + e + " {");
  1966. }
  1967. else
  1968. println("else if " + e + " {");
  1969. }
  1970. else if (unpredicted &&
  1971. alt.semPred==null &&
  1972. alt.synPred==null)
  1973. {
  1974. // The alt has empty prediction set and no
  1975. // predicate to help out. if we have not
  1976. // generated a previous if, just put {...} around
  1977. // the end-of-token clause
  1978. if ( nIF==0 ) {
  1979. println("{");
  1980. }
  1981. else {
  1982. println("else {");
  1983. }
  1984. finishingInfo.needAnErrorClause = false;
  1985. }
  1986. else
  1987. {
  1988. // check for sem and syn preds
  1989. // Add any semantic predicate expression to the lookahead test
  1990. if ( alt.semPred != null ) {
  1991. // if debugging, wrap the evaluation of the predicate in a method
  1992. //
  1993. // translate $ and # references
  1994. ActionTransInfo tInfo = new ActionTransInfo();
  1995. String actionStr = processActionForSpecialSymbols(alt.semPred,
  1996. blk.line,
  1997. currentRule,
  1998. tInfo);
  1999. // ignore translation info...we don't need to do anything with it.
  2000. // call that will inform SemanticPredicateListeners of the
  2001. // result
  2002. if ( grammar.debuggingOutput &&
  2003. ((grammar instanceof ParserGrammar) || (grammar instanceof LexerGrammar))
  2004. )
  2005. e = "("+e+"&& fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.PREDICTING,"+ //FIXME
  2006. addSemPred(charFormatter.escapeString(actionStr))+","+actionStr+"))";
  2007. else
  2008. e = "("+e+"&&("+actionStr +"))";
  2009. }
  2010. // Generate any syntactic predicates
  2011. if ( nIF>0 ) {
  2012. if ( alt.synPred != null ) {
  2013. println("else {");
  2014. tabs++;
  2015. genSynPred( alt.synPred, e );
  2016. closingBracesOfIFSequence++;
  2017. }
  2018. else {
  2019. println("else if " + e + " {");
  2020. }
  2021. }
  2022. else {
  2023. if ( alt.synPred != null ) {
  2024. genSynPred( alt.synPred, e );
  2025. }
  2026. else {
  2027. // when parsing trees, convert null to valid tree node
  2028. // with NULL lookahead.
  2029. if ( grammar instanceof TreeWalkerGrammar ) {
  2030. println("if (_t == "+labeledElementASTInit+" )");
  2031. tabs++;
  2032. println("_t = ASTNULL;");
  2033. tabs--;
  2034. }
  2035. println("if " + e + " {");
  2036. }
  2037. }
  2038. }
  2039. nIF++;
  2040. tabs++;
  2041. genAlt(alt, blk);
  2042. tabs--;
  2043. println("}");
  2044. }
  2045. }
  2046. String ps = "";
  2047. for (int i=1; i<=closingBracesOfIFSequence; i++) {
  2048. tabs--; // does JavaCodeGenerator need this?
  2049. ps+="}";
  2050. }
  2051. // Restore the AST generation state
  2052. genAST = savegenAST;
  2053. // restore save text state
  2054. saveText=oldsaveTest;
  2055. // Return the finishing info.
  2056. if ( createdLL1Switch ) {
  2057. tabs--;
  2058. finishingInfo.postscript = ps+"}";
  2059. finishingInfo.generatedSwitch = true;
  2060. finishingInfo.generatedAnIf = nIF>0;
  2061. //return new CppBlockFinishingInfo(ps+"}",true,nIF>0); // close up switch statement
  2062. }
  2063. else {
  2064. finishingInfo.postscript = ps;
  2065. finishingInfo.generatedSwitch = false;
  2066. finishingInfo.generatedAnIf = nIF>0;
  2067. //return new CppBlockFinishingInfo(ps, false,nIF>0);
  2068. }
  2069. return finishingInfo;
  2070. }
  2071. private static boolean suitableForCaseExpression(Alternative a) {
  2072. return a.lookaheadDepth == 1 &&
  2073. a.semPred == null &&
  2074. !a.cache[1].containsEpsilon() &&
  2075. a.cache[1].fset.degree()<=caseSizeThreshold;
  2076. }
  2077. /** Generate code to link an element reference into the AST
  2078. */
  2079. private void genElementAST(AlternativeElement el) {
  2080. // handle case where you're not building trees, but are in tree walker.
  2081. // Just need to get labels set up.
  2082. if ( grammar instanceof TreeWalkerGrammar && !grammar.buildAST )
  2083. {
  2084. String elementRef;
  2085. String astName;
  2086. // Generate names and declarations of the AST variable(s)
  2087. if (el.getLabel() == null)
  2088. {
  2089. elementRef = lt1Value;
  2090. // Generate AST variables for unlabeled stuff
  2091. astName = "tmp" + astVarNumber + "_AST";
  2092. astVarNumber++;
  2093. // Map the generated AST variable in the alternate
  2094. mapTreeVariable(el, astName);
  2095. // Generate an "input" AST variable also
  2096. println(labeledElementASTType+" "+astName+"_in = "+elementRef+";");
  2097. }
  2098. return;
  2099. }
  2100. if (grammar.buildAST && syntacticPredLevel == 0)
  2101. {
  2102. boolean needASTDecl =
  2103. ( genAST && (el.getLabel() != null ||
  2104. el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG ));
  2105. // RK: if we have a grammar element always generate the decl
  2106. // since some guy can access it from an action and we can't
  2107. // peek ahead (well not without making a mess).
  2108. // I'd prefer taking this out.
  2109. if( el.getAutoGenType() != GrammarElement.AUTO_GEN_BANG &&
  2110. (el instanceof TokenRefElement) )
  2111. needASTDecl = true;
  2112. boolean doNoGuessTest =
  2113. ( grammar.hasSyntacticPredicate && needASTDecl );
  2114. String elementRef;
  2115. String astNameBase;
  2116. // Generate names and declarations of the AST variable(s)
  2117. if (el.getLabel() != null)
  2118. {
  2119. // if the element is labeled use that name...
  2120. elementRef = el.getLabel();
  2121. astNameBase = el.getLabel();
  2122. }
  2123. else
  2124. {
  2125. // else generate a temporary name...
  2126. elementRef = lt1Value;
  2127. // Generate AST variables for unlabeled stuff
  2128. astNameBase = "tmp" + astVarNumber;
  2129. astVarNumber++;
  2130. }
  2131. // Generate the declaration if required.
  2132. if ( needASTDecl )
  2133. {
  2134. if ( el instanceof GrammarAtom )
  2135. {
  2136. GrammarAtom ga = (GrammarAtom)el;
  2137. if ( ga.getASTNodeType()!=null )
  2138. {
  2139. genASTDeclaration( el, astNameBase, "Ref"+ga.getASTNodeType() );
  2140. // println("Ref"+ga.getASTNodeType()+" " + astName + ";");
  2141. }
  2142. else
  2143. {
  2144. genASTDeclaration( el, astNameBase, labeledElementASTType );
  2145. // println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
  2146. }
  2147. }
  2148. else
  2149. {
  2150. genASTDeclaration( el, astNameBase, labeledElementASTType );
  2151. // println(labeledElementASTType+" " + astName + " = "+labeledElementASTInit+";");
  2152. }
  2153. }
  2154. // for convenience..
  2155. String astName = astNameBase + "_AST";
  2156. // Map the generated AST variable in the alternate
  2157. mapTreeVariable(el, astName);
  2158. if (grammar instanceof TreeWalkerGrammar)
  2159. {
  2160. // Generate an "input" AST variable also
  2161. println(labeledElementASTType+" " + astName + "_in = "+labeledElementASTInit+";");
  2162. }
  2163. // Enclose actions with !guessing
  2164. if (doNoGuessTest) {
  2165. println("if ( inputState->guessing == 0 ) {");
  2166. tabs++;
  2167. }
  2168. // if something has a label assume it will be used
  2169. // so we must initialize the RefAST
  2170. if (el.getLabel() != null)
  2171. {
  2172. if ( el instanceof GrammarAtom )
  2173. {
  2174. println(astName + " = "+
  2175. getASTCreateString((GrammarAtom)el,elementRef) + ";");
  2176. }
  2177. else
  2178. {
  2179. println(astName + " = "+
  2180. getASTCreateString(elementRef) + ";");
  2181. }
  2182. }
  2183. // if it has no label but a declaration exists initialize it.
  2184. if( el.getLabel() == null && needASTDecl )
  2185. {
  2186. elementRef = lt1Value;
  2187. if ( el instanceof GrammarAtom )
  2188. {
  2189. println(astName + " = "+
  2190. getASTCreateString((GrammarAtom)el,elementRef) + ";");
  2191. }
  2192. else
  2193. {
  2194. println(astName + " = "+
  2195. getASTCreateString(elementRef) + ";");
  2196. }
  2197. // Map the generated AST variable in the alternate
  2198. if (grammar instanceof TreeWalkerGrammar)
  2199. {
  2200. // set "input" AST variable also
  2201. println(astName + "_in = " + elementRef + ";");
  2202. }
  2203. }
  2204. if (genAST)
  2205. {
  2206. switch (el.getAutoGenType())
  2207. {
  2208. case GrammarElement.AUTO_GEN_NONE:
  2209. if( usingCustomAST ||
  2210. (el instanceof GrammarAtom &&
  2211. ((GrammarAtom)el).getASTNodeType() != null) )
  2212. println("astFactory->addASTChild(currentAST, "+namespaceAntlr+"RefAST("+ astName + "));");
  2213. else
  2214. println("astFactory->addASTChild(currentAST, "+ astName + ");");
  2215. // println("astFactory.addASTChild(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
  2216. break;
  2217. case GrammarElement.AUTO_GEN_CARET:
  2218. if( usingCustomAST ||
  2219. (el instanceof GrammarAtom &&
  2220. ((GrammarAtom)el).getASTNodeType() != null) )
  2221. println("astFactory->makeASTRoot(currentAST, "+namespaceAntlr+"RefAST(" + astName + "));");
  2222. else
  2223. println("astFactory->makeASTRoot(currentAST, " + astName + ");");
  2224. break;
  2225. default:
  2226. break;
  2227. }
  2228. }
  2229. if (doNoGuessTest)
  2230. {
  2231. tabs--;
  2232. println("}");
  2233. }
  2234. }
  2235. }
  2236. /** Close the try block and generate catch phrases
  2237. * if the element has a labeled handler in the rule
  2238. */
  2239. private void genErrorCatchForElement(AlternativeElement el) {
  2240. if (el.getLabel() == null) return;
  2241. String r = el.enclosingRuleName;
  2242. if ( grammar instanceof LexerGrammar ) {
  2243. r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
  2244. }
  2245. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
  2246. if (rs == null) {
  2247. antlrTool.panic("Enclosing rule not found!");
  2248. }
  2249. ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
  2250. if (ex != null) {
  2251. tabs--;
  2252. println("}");
  2253. genErrorHandler(ex);
  2254. }
  2255. }
  2256. /** Generate the catch phrases for a user-specified error handler */
  2257. private void genErrorHandler(ExceptionSpec ex)
  2258. {
  2259. // Each ExceptionHandler in the ExceptionSpec is a separate catch
  2260. for (int i = 0; i < ex.handlers.size(); i++)
  2261. {
  2262. ExceptionHandler handler = (ExceptionHandler)ex.handlers.elementAt(i);
  2263. // Generate catch phrase
  2264. println("catch (" + handler.exceptionTypeAndName.getText() + ") {");
  2265. tabs++;
  2266. if (grammar.hasSyntacticPredicate) {
  2267. println("if (inputState->guessing==0) {");
  2268. tabs++;
  2269. }
  2270. // When not guessing, execute user handler action
  2271. ActionTransInfo tInfo = new ActionTransInfo();
  2272. genLineNo(handler.action);
  2273. printAction(
  2274. processActionForSpecialSymbols( handler.action.getText(),
  2275. handler.action.getLine(),
  2276. currentRule, tInfo )
  2277. );
  2278. genLineNo2();
  2279. if (grammar.hasSyntacticPredicate)
  2280. {
  2281. tabs--;
  2282. println("} else {");
  2283. tabs++;
  2284. // When guessing, rethrow exception
  2285. println("throw;");
  2286. tabs--;
  2287. println("}");
  2288. }
  2289. // Close catch phrase
  2290. tabs--;
  2291. println("}");
  2292. }
  2293. }
  2294. /** Generate a try { opening if the element has a labeled handler in the rule */
  2295. private void genErrorTryForElement(AlternativeElement el) {
  2296. if (el.getLabel() == null) return;
  2297. String r = el.enclosingRuleName;
  2298. if ( grammar instanceof LexerGrammar ) {
  2299. r = CodeGenerator.encodeLexerRuleName(el.enclosingRuleName);
  2300. }
  2301. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(r);
  2302. if (rs == null) {
  2303. antlrTool.panic("Enclosing rule not found!");
  2304. }
  2305. ExceptionSpec ex = rs.block.findExceptionSpec(el.getLabel());
  2306. if (ex != null) {
  2307. println("try { // for error handling");
  2308. tabs++;
  2309. }
  2310. }
  2311. /** Generate a header that is common to all C++ files */
  2312. protected void genHeader(String fileName)
  2313. {
  2314. println("/* $ANTLR "+antlrTool.version+": "+
  2315. "\""+antlrTool.fileMinusPath(antlrTool.grammarFile)+"\""+
  2316. " -> "+
  2317. "\""+fileName+"\"$ */");
  2318. }
  2319. // these are unique to C++ mode
  2320. public void genInclude(LexerGrammar g) throws IOException
  2321. {
  2322. outputFile = grammar.getClassName() + ".hpp";
  2323. outputLine = 1;
  2324. currentOutput = antlrTool.openOutputFile(outputFile);
  2325. //SAS: changed for proper text file io
  2326. genAST = false; // no way to gen trees.
  2327. saveText = true; // save consumed characters.
  2328. tabs=0;
  2329. // Generate a guard wrapper
  2330. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  2331. println("#define INC_"+grammar.getClassName()+"_hpp_");
  2332. println("");
  2333. printHeaderAction(preIncludeHpp);
  2334. println("#include <antlr/config.hpp>");
  2335. // Generate header common to all C++ output files
  2336. genHeader(outputFile);
  2337. // Generate header specific to lexer header file
  2338. println("#include <antlr/CommonToken.hpp>");
  2339. println("#include <antlr/InputBuffer.hpp>");
  2340. println("#include <antlr/BitSet.hpp>");
  2341. println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
  2342. // Find the name of the super class
  2343. String sup=null;
  2344. if ( grammar.superClass!=null ) {
  2345. sup = grammar.superClass;
  2346. println("\n// Include correct superclass header with a header statement for example:");
  2347. println("// header \"post_include_hpp\" {");
  2348. println("// #include \""+sup+".hpp\"");
  2349. println("// }");
  2350. println("// Or....");
  2351. println("// header {");
  2352. println("// #include \""+sup+".hpp\"");
  2353. println("// }\n");
  2354. }
  2355. else {
  2356. sup = grammar.getSuperClass();
  2357. if (sup.lastIndexOf('.') != -1)
  2358. sup = sup.substring(sup.lastIndexOf('.')+1);
  2359. println("#include <antlr/"+sup+".hpp>");
  2360. sup = namespaceAntlr + sup;
  2361. }
  2362. // Do not use printAction because we assume tabs==0
  2363. printHeaderAction(postIncludeHpp);
  2364. if (nameSpace != null)
  2365. nameSpace.emitDeclarations(currentOutput);
  2366. printHeaderAction("");
  2367. // print javadoc comment if any
  2368. if ( grammar.comment!=null ) {
  2369. _println(grammar.comment);
  2370. }
  2371. // Generate lexer class definition
  2372. print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
  2373. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  2374. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  2375. if ( tsuffix != null ) {
  2376. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  2377. if ( suffix != null ) {
  2378. print(", "+suffix); // must be an interface name for Java
  2379. }
  2380. }
  2381. println("{");
  2382. // Generate user-defined lexer class members
  2383. if (grammar.classMemberAction != null) {
  2384. genLineNo(grammar.classMemberAction);
  2385. print(
  2386. processActionForSpecialSymbols(grammar.classMemberAction.getText(),
  2387. grammar.classMemberAction.getLine(),
  2388. currentRule, null)
  2389. );
  2390. genLineNo2();
  2391. }
  2392. // Generate initLiterals() method
  2393. tabs=0;
  2394. println("private:");
  2395. tabs=1;
  2396. println("void initLiterals();");
  2397. // Generate getCaseSensitiveLiterals() method
  2398. tabs=0;
  2399. println("public:");
  2400. tabs=1;
  2401. println("bool getCaseSensitiveLiterals() const");
  2402. println("{");
  2403. tabs++;
  2404. println("return "+g.caseSensitiveLiterals + ";");
  2405. tabs--;
  2406. println("}");
  2407. // Make constructors public
  2408. tabs=0;
  2409. println("public:");
  2410. tabs=1;
  2411. if( noConstructors )
  2412. {
  2413. tabs = 0;
  2414. println("#if 0");
  2415. println("// constructor creation turned of with 'noConstructor' option");
  2416. tabs = 1;
  2417. }
  2418. // Generate the constructor from std::istream
  2419. println(grammar.getClassName() + "(" + namespaceStd + "istream& in);");
  2420. // Generate the constructor from InputBuffer
  2421. println(grammar.getClassName() + "("+namespaceAntlr+"InputBuffer& ib);");
  2422. println(grammar.getClassName() + "(const "+namespaceAntlr+"LexerSharedInputState& state);");
  2423. if( noConstructors )
  2424. {
  2425. tabs = 0;
  2426. println("// constructor creation turned of with 'noConstructor' option");
  2427. println("#endif");
  2428. tabs = 1;
  2429. }
  2430. // Generate nextToken() rule.
  2431. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  2432. // user-defined lexer rules.
  2433. println(namespaceAntlr+"RefToken nextToken();");
  2434. // Generate code for each rule in the lexer
  2435. Enumeration ids = grammar.rules.elements();
  2436. while ( ids.hasMoreElements() ) {
  2437. RuleSymbol sym = (RuleSymbol) ids.nextElement();
  2438. // Don't generate the synthetic rules
  2439. if (!sym.getId().equals("mnextToken")) {
  2440. genRuleHeader(sym, false);
  2441. }
  2442. exitIfError();
  2443. }
  2444. // Make the rest private
  2445. tabs=0;
  2446. println("private:");
  2447. tabs=1;
  2448. // generate the rule name array for debugging
  2449. if ( grammar.debuggingOutput ) {
  2450. println("static const char* _ruleNames[];");
  2451. }
  2452. // Generate the semantic predicate map for debugging
  2453. if (grammar.debuggingOutput)
  2454. println("static const char* _semPredNames[];");
  2455. // Generate the bitsets used throughout the lexer
  2456. genBitsetsHeader(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());
  2457. tabs=0;
  2458. println("};");
  2459. println("");
  2460. if (nameSpace != null)
  2461. nameSpace.emitClosures(currentOutput);
  2462. // Generate a guard wrapper
  2463. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  2464. // Close the lexer output stream
  2465. currentOutput.close();
  2466. currentOutput = null;
  2467. }
  2468. public void genInclude(ParserGrammar g) throws IOException
  2469. {
  2470. // Open the output stream for the parser and set the currentOutput
  2471. outputFile = grammar.getClassName() + ".hpp";
  2472. outputLine = 1;
  2473. currentOutput = antlrTool.openOutputFile(outputFile);
  2474. //SAS: changed for proper text file io
  2475. genAST = grammar.buildAST;
  2476. tabs = 0;
  2477. // Generate a guard wrapper
  2478. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  2479. println("#define INC_"+grammar.getClassName()+"_hpp_");
  2480. println("");
  2481. printHeaderAction(preIncludeHpp);
  2482. println("#include <antlr/config.hpp>");
  2483. // Generate the header common to all output files.
  2484. genHeader(outputFile);
  2485. // Generate header for the parser
  2486. println("#include <antlr/TokenStream.hpp>");
  2487. println("#include <antlr/TokenBuffer.hpp>");
  2488. println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
  2489. // Generate parser class definition
  2490. String sup=null;
  2491. if ( grammar.superClass!=null ) {
  2492. sup = grammar.superClass;
  2493. println("\n// Include correct superclass header with a header statement for example:");
  2494. println("// header \"post_include_hpp\" {");
  2495. println("// #include \""+sup+".hpp\"");
  2496. println("// }");
  2497. println("// Or....");
  2498. println("// header {");
  2499. println("// #include \""+sup+".hpp\"");
  2500. println("// }\n");
  2501. }
  2502. else {
  2503. sup = grammar.getSuperClass();
  2504. if (sup.lastIndexOf('.') != -1)
  2505. sup = sup.substring(sup.lastIndexOf('.')+1);
  2506. println("#include <antlr/"+sup+".hpp>");
  2507. sup = namespaceAntlr + sup;
  2508. }
  2509. println("");
  2510. // Do not use printAction because we assume tabs==0
  2511. printHeaderAction(postIncludeHpp);
  2512. if (nameSpace != null)
  2513. nameSpace.emitDeclarations(currentOutput);
  2514. printHeaderAction("");
  2515. // print javadoc comment if any
  2516. if ( grammar.comment!=null ) {
  2517. _println(grammar.comment);
  2518. }
  2519. // generate the actual class definition
  2520. print("class CUSTOM_API " + grammar.getClassName() + " : public " + sup);
  2521. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  2522. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  2523. if ( tsuffix != null ) {
  2524. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  2525. if ( suffix != null )
  2526. print(", "+suffix); // must be an interface name for Java
  2527. }
  2528. println("{");
  2529. // set up an array of all the rule names so the debugger can
  2530. // keep track of them only by number -- less to store in tree...
  2531. if (grammar.debuggingOutput) {
  2532. println("public: static const char* _ruleNames[];");
  2533. }
  2534. // Generate user-defined parser class members
  2535. if (grammar.classMemberAction != null) {
  2536. genLineNo(grammar.classMemberAction.getLine());
  2537. print(
  2538. processActionForSpecialSymbols(grammar.classMemberAction.getText(),
  2539. grammar.classMemberAction.getLine(),
  2540. currentRule, null)
  2541. );
  2542. genLineNo2();
  2543. }
  2544. println("public:");
  2545. tabs = 1;
  2546. println("void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");
  2547. // println("// called from constructors");
  2548. // println("void _initialize( void );");
  2549. // Generate parser class constructor from TokenBuffer
  2550. tabs=0;
  2551. if( noConstructors )
  2552. {
  2553. println("#if 0");
  2554. println("// constructor creation turned of with 'noConstructor' option");
  2555. }
  2556. println("protected:");
  2557. tabs=1;
  2558. println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf, int k);");
  2559. tabs=0;
  2560. println("public:");
  2561. tabs=1;
  2562. println(grammar.getClassName() + "("+namespaceAntlr+"TokenBuffer& tokenBuf);");
  2563. // Generate parser class constructor from TokenStream
  2564. tabs=0;
  2565. println("protected:");
  2566. tabs=1;
  2567. println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer, int k);");
  2568. tabs=0;
  2569. println("public:");
  2570. tabs=1;
  2571. println(grammar.getClassName()+"("+namespaceAntlr+"TokenStream& lexer);");
  2572. println(grammar.getClassName()+"(const "+namespaceAntlr+"ParserSharedInputState& state);");
  2573. if( noConstructors )
  2574. {
  2575. tabs = 0;
  2576. println("// constructor creation turned of with 'noConstructor' option");
  2577. println("#endif");
  2578. tabs = 1;
  2579. }
  2580. println("int getNumTokens() const");
  2581. println("{"); tabs++;
  2582. println("return "+grammar.getClassName()+"::NUM_TOKENS;");
  2583. tabs--; println("}");
  2584. println("const char* getTokenName( int type ) const");
  2585. println("{"); tabs++;
  2586. println("if( type > getNumTokens() ) return 0;");
  2587. println("return "+grammar.getClassName()+"::tokenNames[type];");
  2588. tabs--; println("}");
  2589. println("const char* const* getTokenNames() const");
  2590. println("{"); tabs++;
  2591. println("return "+grammar.getClassName()+"::tokenNames;");
  2592. tabs--; println("}");
  2593. // Generate code for each rule in the grammar
  2594. Enumeration ids = grammar.rules.elements();
  2595. while ( ids.hasMoreElements() ) {
  2596. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  2597. if ( sym instanceof RuleSymbol) {
  2598. RuleSymbol rs = (RuleSymbol)sym;
  2599. genRuleHeader(rs, rs.references.size()==0);
  2600. }
  2601. exitIfError();
  2602. }
  2603. // RK: when we are using a custom ast override Parser::getAST to return
  2604. // the custom AST type. Ok, this does not work anymore with newer
  2605. // compilers gcc 3.2.x and up. The reference counter is probably
  2606. // getting in the way.
  2607. // So now we just patch the return type back to RefAST
  2608. tabs = 0; println("public:"); tabs = 1;
  2609. println(namespaceAntlr+"RefAST getAST()");
  2610. println("{");
  2611. if( usingCustomAST )
  2612. {
  2613. tabs++;
  2614. println("return "+namespaceAntlr+"RefAST(returnAST);");
  2615. tabs--;
  2616. }
  2617. else
  2618. {
  2619. tabs++;
  2620. println("return returnAST;");
  2621. tabs--;
  2622. }
  2623. println("}");
  2624. println("");
  2625. tabs=0; println("protected:"); tabs=1;
  2626. println(labeledElementASTType+" returnAST;");
  2627. // Make the rest private
  2628. tabs=0;
  2629. println("private:");
  2630. tabs=1;
  2631. // Generate the token names
  2632. println("static const char* tokenNames[];");
  2633. // and how many there are of them
  2634. _println("#ifndef NO_STATIC_CONSTS");
  2635. println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
  2636. _println("#else");
  2637. println("enum {");
  2638. println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
  2639. println("};");
  2640. _println("#endif");
  2641. // Generate the bitsets used throughout the grammar
  2642. genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
  2643. // Generate the semantic predicate map for debugging
  2644. if (grammar.debuggingOutput)
  2645. println("static const char* _semPredNames[];");
  2646. // Close class definition
  2647. tabs=0;
  2648. println("};");
  2649. println("");
  2650. if (nameSpace != null)
  2651. nameSpace.emitClosures(currentOutput);
  2652. // Generate a guard wrapper
  2653. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  2654. // Close the parser output stream
  2655. currentOutput.close();
  2656. currentOutput = null;
  2657. }
  2658. public void genInclude(TreeWalkerGrammar g) throws IOException
  2659. {
  2660. // Open the output stream for the parser and set the currentOutput
  2661. outputFile = grammar.getClassName() + ".hpp";
  2662. outputLine = 1;
  2663. currentOutput = antlrTool.openOutputFile(outputFile);
  2664. //SAS: changed for proper text file io
  2665. genAST = grammar.buildAST;
  2666. tabs = 0;
  2667. // Generate a guard wrapper
  2668. println("#ifndef INC_"+grammar.getClassName()+"_hpp_");
  2669. println("#define INC_"+grammar.getClassName()+"_hpp_");
  2670. println("");
  2671. printHeaderAction(preIncludeHpp);
  2672. println("#include <antlr/config.hpp>");
  2673. println("#include \"" + grammar.tokenManager.getName() + TokenTypesFileSuffix+".hpp\"");
  2674. // Generate the header common to all output files.
  2675. genHeader(outputFile);
  2676. // Find the name of the super class
  2677. String sup=null;
  2678. if ( grammar.superClass!=null ) {
  2679. sup = grammar.superClass;
  2680. println("\n// Include correct superclass header with a header statement for example:");
  2681. println("// header \"post_include_hpp\" {");
  2682. println("// #include \""+sup+".hpp\"");
  2683. println("// }");
  2684. println("// Or....");
  2685. println("// header {");
  2686. println("// #include \""+sup+".hpp\"");
  2687. println("// }\n");
  2688. }
  2689. else {
  2690. sup = grammar.getSuperClass();
  2691. if (sup.lastIndexOf('.') != -1)
  2692. sup = sup.substring(sup.lastIndexOf('.')+1);
  2693. println("#include <antlr/"+sup+".hpp>");
  2694. sup = namespaceAntlr + sup;
  2695. }
  2696. println("");
  2697. // Generate header for the parser
  2698. //
  2699. // Do not use printAction because we assume tabs==0
  2700. printHeaderAction(postIncludeHpp);
  2701. if (nameSpace != null)
  2702. nameSpace.emitDeclarations(currentOutput);
  2703. printHeaderAction("");
  2704. // print javadoc comment if any
  2705. if ( grammar.comment!=null ) {
  2706. _println(grammar.comment);
  2707. }
  2708. // Generate parser class definition
  2709. print("class CUSTOM_API " + grammar.getClassName() + " : public "+sup);
  2710. println(", public " + grammar.tokenManager.getName() + TokenTypesFileSuffix);
  2711. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  2712. if ( tsuffix != null ) {
  2713. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  2714. if ( suffix != null ) {
  2715. print(", "+suffix); // must be an interface name for Java
  2716. }
  2717. }
  2718. println("{");
  2719. // Generate user-defined parser class members
  2720. if (grammar.classMemberAction != null) {
  2721. genLineNo(grammar.classMemberAction.getLine());
  2722. print(
  2723. processActionForSpecialSymbols(grammar.classMemberAction.getText(),
  2724. grammar.classMemberAction.getLine(),
  2725. currentRule, null)
  2726. );
  2727. genLineNo2();
  2728. }
  2729. // Generate default parser class constructor
  2730. tabs=0;
  2731. println("public:");
  2732. if( noConstructors )
  2733. {
  2734. println("#if 0");
  2735. println("// constructor creation turned of with 'noConstructor' option");
  2736. }
  2737. tabs=1;
  2738. println(grammar.getClassName() + "();");
  2739. if( noConstructors )
  2740. {
  2741. tabs = 0;
  2742. println("#endif");
  2743. tabs = 1;
  2744. }
  2745. // Generate declaration for the initializeFactory method
  2746. println("static void initializeASTFactory( "+namespaceAntlr+"ASTFactory& factory );");
  2747. println("int getNumTokens() const");
  2748. println("{"); tabs++;
  2749. println("return "+grammar.getClassName()+"::NUM_TOKENS;");
  2750. tabs--; println("}");
  2751. println("const char* getTokenName( int type ) const");
  2752. println("{"); tabs++;
  2753. println("if( type > getNumTokens() ) return 0;");
  2754. println("return "+grammar.getClassName()+"::tokenNames[type];");
  2755. tabs--; println("}");
  2756. println("const char* const* getTokenNames() const");
  2757. println("{"); tabs++;
  2758. println("return "+grammar.getClassName()+"::tokenNames;");
  2759. tabs--; println("}");
  2760. // Generate code for each rule in the grammar
  2761. Enumeration ids = grammar.rules.elements();
  2762. String ruleNameInits = "";
  2763. while ( ids.hasMoreElements() ) {
  2764. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  2765. if ( sym instanceof RuleSymbol) {
  2766. RuleSymbol rs = (RuleSymbol)sym;
  2767. genRuleHeader(rs, rs.references.size()==0);
  2768. }
  2769. exitIfError();
  2770. }
  2771. tabs = 0; println("public:"); tabs = 1;
  2772. println(namespaceAntlr+"RefAST getAST()");
  2773. println("{");
  2774. if( usingCustomAST )
  2775. {
  2776. tabs++;
  2777. println("return "+namespaceAntlr+"RefAST(returnAST);");
  2778. tabs--;
  2779. }
  2780. else
  2781. {
  2782. tabs++;
  2783. println("return returnAST;");
  2784. tabs--;
  2785. }
  2786. println("}");
  2787. println("");
  2788. tabs=0; println("protected:"); tabs=1;
  2789. println(labeledElementASTType+" returnAST;");
  2790. println(labeledElementASTType+" _retTree;");
  2791. // Make the rest private
  2792. tabs=0;
  2793. println("private:");
  2794. tabs=1;
  2795. // Generate the token names
  2796. println("static const char* tokenNames[];");
  2797. // and how many there are of them
  2798. _println("#ifndef NO_STATIC_CONSTS");
  2799. println("static const int NUM_TOKENS = "+grammar.tokenManager.getVocabulary().size()+";");
  2800. _println("#else");
  2801. println("enum {");
  2802. println("\tNUM_TOKENS = "+grammar.tokenManager.getVocabulary().size());
  2803. println("};");
  2804. _println("#endif");
  2805. // Generate the bitsets used throughout the grammar
  2806. genBitsetsHeader(bitsetsUsed, grammar.tokenManager.maxTokenType());
  2807. // Close class definition
  2808. tabs=0;
  2809. println("};");
  2810. println("");
  2811. if (nameSpace != null)
  2812. nameSpace.emitClosures(currentOutput);
  2813. // Generate a guard wrapper
  2814. println("#endif /*INC_"+grammar.getClassName()+"_hpp_*/");
  2815. // Close the parser output stream
  2816. currentOutput.close();
  2817. currentOutput = null;
  2818. }
  2819. /// for convenience
  2820. protected void genASTDeclaration( AlternativeElement el ) {
  2821. genASTDeclaration( el, labeledElementASTType );
  2822. }
  2823. /// for convenience
  2824. protected void genASTDeclaration( AlternativeElement el, String node_type ) {
  2825. genASTDeclaration( el, el.getLabel(), node_type );
  2826. }
  2827. /// Generate (if not already done) a declaration for the AST for el.
  2828. protected void genASTDeclaration( AlternativeElement el, String var_name, String node_type ) {
  2829. // already declared?
  2830. if( declaredASTVariables.contains(el) )
  2831. return;
  2832. String init = labeledElementASTInit;
  2833. if (el instanceof GrammarAtom &&
  2834. ((GrammarAtom)el).getASTNodeType() != null )
  2835. init = "Ref"+((GrammarAtom)el).getASTNodeType()+"("+labeledElementASTInit+")";
  2836. // emit code
  2837. println(node_type+" " + var_name + "_AST = "+init+";");
  2838. // mark as declared
  2839. declaredASTVariables.put(el, el);
  2840. }
  2841. private void genLiteralsTest() {
  2842. println("_ttype = testLiteralsTable(_ttype);");
  2843. }
  2844. private void genLiteralsTestForPartialToken() {
  2845. println("_ttype = testLiteralsTable(text.substr(_begin, text.length()-_begin),_ttype);");
  2846. }
  2847. protected void genMatch(BitSet b) {
  2848. }
  2849. protected void genMatch(GrammarAtom atom) {
  2850. if ( atom instanceof StringLiteralElement ) {
  2851. if ( grammar instanceof LexerGrammar ) {
  2852. genMatchUsingAtomText(atom);
  2853. }
  2854. else {
  2855. genMatchUsingAtomTokenType(atom);
  2856. }
  2857. }
  2858. else if ( atom instanceof CharLiteralElement ) {
  2859. // Lexer case is handled in the gen( CharLiteralElement x )
  2860. antlrTool.error("cannot ref character literals in grammar: "+atom);
  2861. }
  2862. else if ( atom instanceof TokenRefElement ) {
  2863. genMatchUsingAtomTokenType(atom);
  2864. } else if (atom instanceof WildcardElement) {
  2865. gen((WildcardElement)atom);
  2866. }
  2867. }
  2868. protected void genMatchUsingAtomText(GrammarAtom atom) {
  2869. // match() for trees needs the _t cursor
  2870. String astArgs="";
  2871. if (grammar instanceof TreeWalkerGrammar) {
  2872. if( usingCustomAST )
  2873. astArgs=namespaceAntlr+"RefAST"+"(_t),";
  2874. else
  2875. astArgs="_t,";
  2876. }
  2877. // if in lexer and ! on element, save buffer index to kill later
  2878. if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  2879. println("_saveIndex = text.length();");
  2880. }
  2881. print(atom.not ? "matchNot(" : "match(");
  2882. _print(astArgs);
  2883. // print out what to match
  2884. if (atom.atomText.equals("EOF")) {
  2885. // horrible hack to handle EOF case
  2886. _print(namespaceAntlr+"Token::EOF_TYPE");
  2887. }
  2888. else
  2889. {
  2890. if( grammar instanceof LexerGrammar ) // lexer needs special handling
  2891. {
  2892. String cppstring = convertJavaToCppString( atom.atomText, false );
  2893. _print(cppstring);
  2894. }
  2895. else
  2896. _print(atom.atomText);
  2897. }
  2898. _println(");");
  2899. if ( grammar instanceof LexerGrammar && (!saveText||atom.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  2900. println("text.erase(_saveIndex);"); // kill text atom put in buffer
  2901. }
  2902. }
  2903. protected void genMatchUsingAtomTokenType(GrammarAtom atom) {
  2904. // match() for trees needs the _t cursor
  2905. String astArgs="";
  2906. if (grammar instanceof TreeWalkerGrammar) {
  2907. if( usingCustomAST )
  2908. astArgs=namespaceAntlr+"RefAST"+"(_t),";
  2909. else
  2910. astArgs="_t,";
  2911. }
  2912. // If the literal can be mangled, generate the symbolic constant instead
  2913. String s = astArgs + getValueString(atom.getType());
  2914. // matching
  2915. println( (atom.not ? "matchNot(" : "match(") + s + ");");
  2916. }
  2917. /** Generate the nextToken() rule.
  2918. * nextToken() is a synthetic lexer rule that is the implicit OR of all
  2919. * user-defined lexer rules.
  2920. * @param RuleBlock
  2921. */
  2922. public void genNextToken() {
  2923. // Are there any public rules? If not, then just generate a
  2924. // fake nextToken().
  2925. boolean hasPublicRules = false;
  2926. for (int i = 0; i < grammar.rules.size(); i++) {
  2927. RuleSymbol rs = (RuleSymbol)grammar.rules.elementAt(i);
  2928. if ( rs.isDefined() && rs.access.equals("public") ) {
  2929. hasPublicRules = true;
  2930. break;
  2931. }
  2932. }
  2933. if (!hasPublicRules) {
  2934. println("");
  2935. println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken() { return "+namespaceAntlr+"RefToken(new "+namespaceAntlr+"CommonToken("+namespaceAntlr+"Token::EOF_TYPE, \"\")); }");
  2936. println("");
  2937. return;
  2938. }
  2939. // Create the synthesized nextToken() rule
  2940. RuleBlock nextTokenBlk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
  2941. // Define the nextToken rule symbol
  2942. RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
  2943. nextTokenRs.setDefined();
  2944. nextTokenRs.setBlock(nextTokenBlk);
  2945. nextTokenRs.access = "private";
  2946. grammar.define(nextTokenRs);
  2947. // Analyze the nextToken rule
  2948. boolean ok = grammar.theLLkAnalyzer.deterministic(nextTokenBlk);
  2949. // Generate the next token rule
  2950. String filterRule=null;
  2951. if ( ((LexerGrammar)grammar).filterMode ) {
  2952. filterRule = ((LexerGrammar)grammar).filterRule;
  2953. }
  2954. println("");
  2955. println(namespaceAntlr+"RefToken "+grammar.getClassName()+"::nextToken()");
  2956. println("{");
  2957. tabs++;
  2958. println(namespaceAntlr+"RefToken theRetToken;");
  2959. println("for (;;) {");
  2960. tabs++;
  2961. println(namespaceAntlr+"RefToken theRetToken;");
  2962. println("int _ttype = "+namespaceAntlr+"Token::INVALID_TYPE;");
  2963. if ( ((LexerGrammar)grammar).filterMode ) {
  2964. println("setCommitToPath(false);");
  2965. if ( filterRule!=null ) {
  2966. // Here's a good place to ensure that the filter rule actually exists
  2967. if ( !grammar.isDefined(CodeGenerator.encodeLexerRuleName(filterRule)) ) {
  2968. grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
  2969. }
  2970. else {
  2971. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(CodeGenerator.encodeLexerRuleName(filterRule));
  2972. if ( !rs.isDefined() ) {
  2973. grammar.antlrTool.error("Filter rule "+filterRule+" does not exist in this lexer");
  2974. }
  2975. else if ( rs.access.equals("public") ) {
  2976. grammar.antlrTool.error("Filter rule "+filterRule+" must be protected");
  2977. }
  2978. }
  2979. println("int _m;");
  2980. println("_m = mark();");
  2981. }
  2982. }
  2983. println("resetText();");
  2984. // Generate try around whole thing to trap scanner errors
  2985. println("try { // for lexical and char stream error handling");
  2986. tabs++;
  2987. // Test for public lexical rules with empty paths
  2988. for (int i=0; i<nextTokenBlk.getAlternatives().size(); i++) {
  2989. Alternative a = nextTokenBlk.getAlternativeAt(i);
  2990. if ( a.cache[1].containsEpsilon() ) {
  2991. antlrTool.warning("found optional path in nextToken()");
  2992. }
  2993. }
  2994. // Generate the block
  2995. String newline = System.getProperty("line.separator");
  2996. CppBlockFinishingInfo howToFinish = genCommonBlock(nextTokenBlk, false);
  2997. String errFinish = "if (LA(1)==EOF_CHAR)"+newline+
  2998. "\t\t\t\t{"+newline+"\t\t\t\t\tuponEOF();"+newline+
  2999. "\t\t\t\t\t_returnToken = makeToken("+namespaceAntlr+"Token::EOF_TYPE);"+
  3000. newline+"\t\t\t\t}";
  3001. errFinish += newline+"\t\t\t\t";
  3002. if ( ((LexerGrammar)grammar).filterMode ) {
  3003. if ( filterRule==null ) {
  3004. errFinish += "else {consume(); goto tryAgain;}";
  3005. }
  3006. else {
  3007. errFinish += "else {"+newline+
  3008. "\t\t\t\t\tcommit();"+newline+
  3009. "\t\t\t\t\ttry {m"+filterRule+"(false);}"+newline+
  3010. "\t\t\t\t\tcatch("+namespaceAntlr+"RecognitionException& e) {"+newline+
  3011. "\t\t\t\t\t // catastrophic failure"+newline+
  3012. "\t\t\t\t\t reportError(e);"+newline+
  3013. "\t\t\t\t\t consume();"+newline+
  3014. "\t\t\t\t\t}"+newline+
  3015. "\t\t\t\t\tgoto tryAgain;"+newline+
  3016. "\t\t\t\t}";
  3017. }
  3018. }
  3019. else {
  3020. errFinish += "else {"+throwNoViable+"}";
  3021. }
  3022. genBlockFinish(howToFinish, errFinish);
  3023. // at this point a valid token has been matched, undo "mark" that was done
  3024. if ( ((LexerGrammar)grammar).filterMode && filterRule!=null ) {
  3025. println("commit();");
  3026. }
  3027. // Generate literals test if desired
  3028. // make sure _ttype is set first; note _returnToken must be
  3029. // non-null as the rule was required to create it.
  3030. println("if ( !_returnToken )"+newline+
  3031. "\t\t\t\tgoto tryAgain; // found SKIP token"+newline);
  3032. println("_ttype = _returnToken->getType();");
  3033. if ( ((LexerGrammar)grammar).getTestLiterals()) {
  3034. genLiteralsTest();
  3035. }
  3036. // return token created by rule reference in switch
  3037. println("_returnToken->setType(_ttype);");
  3038. println("return _returnToken;");
  3039. // Close try block
  3040. tabs--;
  3041. println("}");
  3042. println("catch ("+namespaceAntlr+"RecognitionException& e) {");
  3043. tabs++;
  3044. if ( ((LexerGrammar)grammar).filterMode ) {
  3045. if ( filterRule==null ) {
  3046. println("if ( !getCommitToPath() ) {");
  3047. tabs++;
  3048. println("consume();");
  3049. println("goto tryAgain;");
  3050. tabs--;
  3051. println("}");
  3052. }
  3053. else {
  3054. println("if ( !getCommitToPath() ) {");
  3055. tabs++;
  3056. println("rewind(_m);");
  3057. println("resetText();");
  3058. println("try {m"+filterRule+"(false);}");
  3059. println("catch("+namespaceAntlr+"RecognitionException& ee) {");
  3060. println(" // horrendous failure: error in filter rule");
  3061. println(" reportError(ee);");
  3062. println(" consume();");
  3063. println("}");
  3064. // println("goto tryAgain;");
  3065. tabs--;
  3066. println("}");
  3067. println("else");
  3068. }
  3069. }
  3070. if ( nextTokenBlk.getDefaultErrorHandler() ) {
  3071. println("{");
  3072. tabs++;
  3073. println("reportError(e);");
  3074. println("consume();");
  3075. tabs--;
  3076. println("}");
  3077. }
  3078. else {
  3079. // pass on to invoking routine
  3080. tabs++;
  3081. println("throw "+namespaceAntlr+"TokenStreamRecognitionException(e);");
  3082. tabs--;
  3083. }
  3084. // close CharStreamException try
  3085. tabs--;
  3086. println("}");
  3087. println("catch ("+namespaceAntlr+"CharStreamIOException& csie) {");
  3088. println("\tthrow "+namespaceAntlr+"TokenStreamIOException(csie.io);");
  3089. println("}");
  3090. println("catch ("+namespaceAntlr+"CharStreamException& cse) {");
  3091. println("\tthrow "+namespaceAntlr+"TokenStreamException(cse.getMessage());");
  3092. println("}");
  3093. // close for-loop
  3094. _println("tryAgain:;");
  3095. tabs--;
  3096. println("}");
  3097. // close method nextToken
  3098. tabs--;
  3099. println("}");
  3100. println("");
  3101. }
  3102. /** Gen a named rule block.
  3103. * ASTs are generated for each element of an alternative unless
  3104. * the rule or the alternative have a '!' modifier.
  3105. *
  3106. * If an alternative defeats the default tree construction, it
  3107. * must set <rule>_AST to the root of the returned AST.
  3108. *
  3109. * Each alternative that does automatic tree construction, builds
  3110. * up root and child list pointers in an ASTPair structure.
  3111. *
  3112. * A rule finishes by setting the returnAST variable from the
  3113. * ASTPair.
  3114. *
  3115. * @param rule The name of the rule to generate
  3116. * @param startSymbol true if the rule is a start symbol (i.e., not referenced elsewhere)
  3117. */
  3118. public void genRule(RuleSymbol s, boolean startSymbol, int ruleNum, String prefix) {
  3119. // tabs=1; // JavaCodeGenerator needs this
  3120. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRule("+ s.getId() +")");
  3121. if ( !s.isDefined() ) {
  3122. antlrTool.error("undefined rule: "+ s.getId());
  3123. return;
  3124. }
  3125. // Generate rule return type, name, arguments
  3126. RuleBlock rblk = s.getBlock();
  3127. currentRule = rblk;
  3128. currentASTResult = s.getId();
  3129. // clear list of declared ast variables..
  3130. declaredASTVariables.clear();
  3131. // Save the AST generation state, and set it to that of the rule
  3132. boolean savegenAST = genAST;
  3133. genAST = genAST && rblk.getAutoGen();
  3134. // boolean oldsaveTest = saveText;
  3135. saveText = rblk.getAutoGen();
  3136. // print javadoc comment if any
  3137. if ( s.comment!=null ) {
  3138. _println(s.comment);
  3139. }
  3140. // Gen method return type (note lexer return action set at rule creation)
  3141. if (rblk.returnAction != null)
  3142. {
  3143. // Has specified return value
  3144. _print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
  3145. } else {
  3146. // No specified return value
  3147. _print("void ");
  3148. }
  3149. // Gen method name
  3150. _print(prefix + s.getId() + "(");
  3151. // Additional rule parameters common to all rules for this grammar
  3152. _print(commonExtraParams);
  3153. if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
  3154. _print(",");
  3155. }
  3156. // Gen arguments
  3157. if (rblk.argAction != null)
  3158. {
  3159. // Has specified arguments
  3160. _println("");
  3161. // FIXME: make argAction also a token? Hmmmmm
  3162. // genLineNo(rblk);
  3163. tabs++;
  3164. // Process arguments for default arguments
  3165. // newer gcc's don't accept these in two places (header/cpp)
  3166. //
  3167. // Old appraoch with StringBuffer gave trouble with gcj.
  3168. //
  3169. // RK: Actually this breaks with string default arguments containing
  3170. // a comma's or equal signs. Then again the old StringBuffer method
  3171. // suffered from the same.
  3172. String oldarg = rblk.argAction;
  3173. String newarg = "";
  3174. String comma = "";
  3175. int eqpos = oldarg.indexOf( '=' );
  3176. if( eqpos != -1 )
  3177. {
  3178. int cmpos = 0;
  3179. while( cmpos != -1 && eqpos != -1 )
  3180. {
  3181. newarg = newarg + comma + oldarg.substring( 0, eqpos ).trim();
  3182. comma = ", ";
  3183. cmpos = oldarg.indexOf( ',', eqpos );
  3184. if( cmpos != -1 )
  3185. {
  3186. // cut off part we just handled
  3187. oldarg = oldarg.substring( cmpos+1 ).trim();
  3188. eqpos = oldarg.indexOf( '=' );
  3189. if( eqpos == -1 )
  3190. newarg = newarg+comma+oldarg;
  3191. }
  3192. }
  3193. }
  3194. else
  3195. newarg = oldarg;
  3196. println( newarg );
  3197. // println(rblk.argAction);
  3198. tabs--;
  3199. print(") ");
  3200. // genLineNo2(); // gcc gives error on the brace... hope it works for the others too
  3201. } else {
  3202. // No specified arguments
  3203. _print(") ");
  3204. }
  3205. _println("{");
  3206. tabs++;
  3207. if (grammar.traceRules) {
  3208. if ( grammar instanceof TreeWalkerGrammar ) {
  3209. if ( usingCustomAST )
  3210. println("Tracer traceInOut(this,\""+ s.getId() +"\","+namespaceAntlr+"RefAST"+"(_t));");
  3211. else
  3212. println("Tracer traceInOut(this,\""+ s.getId() +"\",_t);");
  3213. }
  3214. else {
  3215. println("Tracer traceInOut(this, \""+ s.getId() +"\");");
  3216. }
  3217. }
  3218. // Convert return action to variable declaration
  3219. if (rblk.returnAction != null)
  3220. {
  3221. genLineNo(rblk);
  3222. println(rblk.returnAction + ";");
  3223. genLineNo2();
  3224. }
  3225. // print out definitions needed by rules for various grammar types
  3226. if (!commonLocalVars.equals(""))
  3227. println(commonLocalVars);
  3228. if ( grammar instanceof LexerGrammar ) {
  3229. // RK: why is this here? It seems not supported in the rest of the
  3230. // tool.
  3231. // lexer rule default return value is the rule's token name
  3232. // This is a horrible hack to support the built-in EOF lexer rule.
  3233. if (s.getId().equals("mEOF"))
  3234. println("_ttype = "+namespaceAntlr+"Token::EOF_TYPE;");
  3235. else
  3236. println("_ttype = "+ s.getId().substring(1)+";");
  3237. println(namespaceStd+"string::size_type _saveIndex;"); // used for element! (so we can kill text matched for element)
  3238. /*
  3239. println("boolean old_saveConsumedInput=saveConsumedInput;");
  3240. if ( !rblk.getAutoGen() ) { // turn off "save input" if ! on rule
  3241. println("saveConsumedInput=false;");
  3242. }
  3243. */
  3244. }
  3245. // if debugging, write code to mark entry to the rule
  3246. if ( grammar.debuggingOutput)
  3247. if (grammar instanceof ParserGrammar)
  3248. println("fireEnterRule(" + ruleNum + ",0);");
  3249. else if (grammar instanceof LexerGrammar)
  3250. println("fireEnterRule(" + ruleNum + ",_ttype);");
  3251. // Generate trace code if desired
  3252. // if ( grammar.debuggingOutput || grammar.traceRules) {
  3253. // println("try { // debugging");
  3254. // tabs++;
  3255. // }
  3256. // Initialize AST variables
  3257. if (grammar instanceof TreeWalkerGrammar) {
  3258. // "Input" value for rule
  3259. // println(labeledElementASTType+" " + s.getId() + "_AST_in = "+labeledElementASTType+"(_t);");
  3260. println(labeledElementASTType+" " + s.getId() + "_AST_in = (_t == ASTNULL) ? "+labeledElementASTInit+" : _t;");
  3261. }
  3262. if (grammar.buildAST) {
  3263. // Parser member used to pass AST returns from rule invocations
  3264. println("returnAST = "+labeledElementASTInit+";");
  3265. // Tracks AST construction
  3266. println(namespaceAntlr+"ASTPair currentAST;"); // = new ASTPair();");
  3267. // User-settable return value for rule.
  3268. println(labeledElementASTType+" " + s.getId() + "_AST = "+labeledElementASTInit+";");
  3269. }
  3270. genBlockPreamble(rblk);
  3271. genBlockInitAction(rblk);
  3272. println("");
  3273. // Search for an unlabeled exception specification attached to the rule
  3274. ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
  3275. // Generate try block around the entire rule for error handling
  3276. if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
  3277. println("try { // for error handling");
  3278. tabs++;
  3279. }
  3280. // Generate the alternatives
  3281. if ( rblk.alternatives.size()==1 )
  3282. {
  3283. // One alternative -- use simple form
  3284. Alternative alt = rblk.getAlternativeAt(0);
  3285. String pred = alt.semPred;
  3286. if ( pred!=null )
  3287. genSemPred(pred, currentRule.line);
  3288. if (alt.synPred != null) {
  3289. antlrTool.warning(
  3290. "Syntactic predicate ignored for single alternative",
  3291. grammar.getFilename(),
  3292. alt.synPred.getLine(),
  3293. alt.synPred.getColumn()
  3294. );
  3295. }
  3296. genAlt(alt, rblk);
  3297. }
  3298. else
  3299. {
  3300. // Multiple alternatives -- generate complex form
  3301. boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
  3302. CppBlockFinishingInfo howToFinish = genCommonBlock(rblk, false);
  3303. genBlockFinish(howToFinish, throwNoViable);
  3304. }
  3305. // Generate catch phrase for error handling
  3306. if (unlabeledUserSpec != null || rblk.getDefaultErrorHandler() ) {
  3307. // Close the try block
  3308. tabs--;
  3309. println("}");
  3310. }
  3311. // Generate user-defined or default catch phrases
  3312. if (unlabeledUserSpec != null)
  3313. {
  3314. genErrorHandler(unlabeledUserSpec);
  3315. }
  3316. else if (rblk.getDefaultErrorHandler())
  3317. {
  3318. // Generate default catch phrase
  3319. println("catch (" + exceptionThrown + "& ex) {");
  3320. tabs++;
  3321. // Generate code to handle error if not guessing
  3322. if (grammar.hasSyntacticPredicate) {
  3323. println("if( inputState->guessing == 0 ) {");
  3324. tabs++;
  3325. }
  3326. println("reportError(ex);");
  3327. if ( !(grammar instanceof TreeWalkerGrammar) )
  3328. {
  3329. // Generate code to consume until token in k==1 follow set
  3330. Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, rblk.endNode);
  3331. String followSetName = getBitsetName(markBitsetForGen(follow.fset));
  3332. println("recover(ex," + followSetName + ");");
  3333. }
  3334. else
  3335. {
  3336. // Just consume one token
  3337. println("if ( _t != "+labeledElementASTInit+" )");
  3338. tabs++;
  3339. println("_t = _t->getNextSibling();");
  3340. tabs--;
  3341. }
  3342. if (grammar.hasSyntacticPredicate)
  3343. {
  3344. tabs--;
  3345. // When guessing, rethrow exception
  3346. println("} else {");
  3347. tabs++;
  3348. println("throw;");
  3349. tabs--;
  3350. println("}");
  3351. }
  3352. // Close catch phrase
  3353. tabs--;
  3354. println("}");
  3355. }
  3356. // Squirrel away the AST "return" value
  3357. if (grammar.buildAST) {
  3358. println("returnAST = " + s.getId() + "_AST;");
  3359. }
  3360. // Set return tree value for tree walkers
  3361. if ( grammar instanceof TreeWalkerGrammar ) {
  3362. println("_retTree = _t;");
  3363. }
  3364. // Generate literals test for lexer rules so marked
  3365. if (rblk.getTestLiterals()) {
  3366. if ( s.access.equals("protected") ) {
  3367. genLiteralsTestForPartialToken();
  3368. }
  3369. else {
  3370. genLiteralsTest();
  3371. }
  3372. }
  3373. // if doing a lexer rule, dump code to create token if necessary
  3374. if ( grammar instanceof LexerGrammar ) {
  3375. println("if ( _createToken && _token=="+namespaceAntlr+"nullToken && _ttype!="+namespaceAntlr+"Token::SKIP ) {");
  3376. println(" _token = makeToken(_ttype);");
  3377. println(" _token->setText(text.substr(_begin, text.length()-_begin));");
  3378. println("}");
  3379. println("_returnToken = _token;");
  3380. // It should be easy for an optimizing compiler to realize this does nothing
  3381. // but it avoids the warning about the variable being unused.
  3382. println("_saveIndex=0;");
  3383. }
  3384. // Gen the return statement if there is one (lexer has hard-wired return action)
  3385. if (rblk.returnAction != null) {
  3386. println("return " + extractIdOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + ";");
  3387. }
  3388. // if ( grammar.debuggingOutput || grammar.traceRules) {
  3389. //// tabs--;
  3390. //// println("} finally { // debugging");
  3391. //// tabs++;
  3392. //
  3393. // // Generate trace code if desired
  3394. // if ( grammar.debuggingOutput)
  3395. // if (grammar instanceof ParserGrammar)
  3396. // println("fireExitRule(" + ruleNum + ",0);");
  3397. // else if (grammar instanceof LexerGrammar)
  3398. // println("fireExitRule(" + ruleNum + ",_ttype);");
  3399. //
  3400. //// if (grammar.traceRules) {
  3401. //// if ( grammar instanceof TreeWalkerGrammar ) {
  3402. //// println("traceOut(\""+ s.getId() +"\",_t);");
  3403. //// }
  3404. //// else {
  3405. //// println("traceOut(\""+ s.getId() +"\");");
  3406. //// }
  3407. //// }
  3408. ////
  3409. //// tabs--;
  3410. //// println("}");
  3411. // }
  3412. tabs--;
  3413. println("}");
  3414. println("");
  3415. // Restore the AST generation state
  3416. genAST = savegenAST;
  3417. // restore char save state
  3418. // saveText = oldsaveTest;
  3419. }
  3420. public void genRuleHeader(RuleSymbol s, boolean startSymbol) {
  3421. tabs=1;
  3422. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("genRuleHeader("+ s.getId() +")");
  3423. if ( !s.isDefined() ) {
  3424. antlrTool.error("undefined rule: "+ s.getId());
  3425. return;
  3426. }
  3427. // Generate rule return type, name, arguments
  3428. RuleBlock rblk = s.getBlock();
  3429. currentRule = rblk;
  3430. currentASTResult = s.getId();
  3431. // Save the AST generation state, and set it to that of the rule
  3432. boolean savegenAST = genAST;
  3433. genAST = genAST && rblk.getAutoGen();
  3434. // boolean oldsaveTest = saveText;
  3435. saveText = rblk.getAutoGen();
  3436. // Gen method access
  3437. print(s.access + ": ");
  3438. // Gen method return type (note lexer return action set at rule creation)
  3439. if (rblk.returnAction != null)
  3440. {
  3441. // Has specified return value
  3442. _print(extractTypeOfAction(rblk.returnAction, rblk.getLine(), rblk.getColumn()) + " ");
  3443. } else {
  3444. // No specified return value
  3445. _print("void ");
  3446. }
  3447. // Gen method name
  3448. _print(s.getId() + "(");
  3449. // Additional rule parameters common to all rules for this grammar
  3450. _print(commonExtraParams);
  3451. if (commonExtraParams.length() != 0 && rblk.argAction != null ) {
  3452. _print(",");
  3453. }
  3454. // Gen arguments
  3455. if (rblk.argAction != null)
  3456. {
  3457. // Has specified arguments
  3458. _println("");
  3459. tabs++;
  3460. println(rblk.argAction);
  3461. tabs--;
  3462. print(")");
  3463. } else {
  3464. // No specified arguments
  3465. _print(")");
  3466. }
  3467. _println(";");
  3468. tabs--;
  3469. // Restore the AST generation state
  3470. genAST = savegenAST;
  3471. // restore char save state
  3472. // saveText = oldsaveTest;
  3473. }
  3474. private void GenRuleInvocation(RuleRefElement rr) {
  3475. // dump rule name
  3476. _print(rr.targetRule + "(");
  3477. // lexers must tell rule if it should set _returnToken
  3478. if ( grammar instanceof LexerGrammar ) {
  3479. // if labeled, could access Token, so tell rule to create
  3480. if ( rr.getLabel() != null ) {
  3481. _print("true");
  3482. }
  3483. else {
  3484. _print("false");
  3485. }
  3486. if (commonExtraArgs.length() != 0 || rr.args!=null ) {
  3487. _print(",");
  3488. }
  3489. }
  3490. // Extra arguments common to all rules for this grammar
  3491. _print(commonExtraArgs);
  3492. if (commonExtraArgs.length() != 0 && rr.args!=null ) {
  3493. _print(",");
  3494. }
  3495. // Process arguments to method, if any
  3496. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  3497. if (rr.args != null)
  3498. {
  3499. // When not guessing, execute user arg action
  3500. ActionTransInfo tInfo = new ActionTransInfo();
  3501. // FIXME: fix line number passed to processActionForTreeSpecifiers here..
  3502. // this one might be a bit off..
  3503. String args = processActionForSpecialSymbols(rr.args, rr.line,
  3504. currentRule, tInfo);
  3505. if ( tInfo.assignToRoot || tInfo.refRuleRoot!=null )
  3506. {
  3507. antlrTool.error("Arguments of rule reference '" + rr.targetRule + "' cannot set or ref #"+
  3508. currentRule.getRuleName()+" on line "+rr.getLine());
  3509. }
  3510. _print(args);
  3511. // Warn if the rule accepts no arguments
  3512. if (rs.block.argAction == null)
  3513. {
  3514. antlrTool.warning("Rule '" + rr.targetRule + "' accepts no arguments",
  3515. grammar.getFilename(),
  3516. rr.getLine(), rr.getColumn());
  3517. }
  3518. }
  3519. else
  3520. {
  3521. // For C++, no warning if rule has parameters, because there may be default
  3522. // values for all of the parameters
  3523. //if (rs.block.argAction != null) {
  3524. // tool.warning("Missing parameters on reference to rule "+rr.targetRule, rr.getLine());
  3525. //}
  3526. }
  3527. _println(");");
  3528. // move down to the first child while parsing
  3529. if ( grammar instanceof TreeWalkerGrammar ) {
  3530. println("_t = _retTree;");
  3531. }
  3532. }
  3533. protected void genSemPred(String pred, int line) {
  3534. // translate $ and # references
  3535. ActionTransInfo tInfo = new ActionTransInfo();
  3536. pred = processActionForSpecialSymbols(pred, line, currentRule, tInfo);
  3537. // ignore translation info...we don't need to do anything with it.
  3538. String escapedPred = charFormatter.escapeString(pred);
  3539. // if debugging, wrap the semantic predicate evaluation in a method
  3540. // that can tell SemanticPredicateListeners the result
  3541. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  3542. (grammar instanceof LexerGrammar)))
  3543. pred = "fireSemanticPredicateEvaluated(antlr.debug.SemanticPredicateEvent.VALIDATING," //FIXME
  3544. + addSemPred(escapedPred) + "," + pred + ")";
  3545. println("if (!(" + pred + "))");
  3546. tabs++;
  3547. println("throw "+namespaceAntlr+"SemanticException(\"" + escapedPred + "\");");
  3548. tabs--;
  3549. }
  3550. /** Write an array of Strings which are the semantic predicate
  3551. * expressions. The debugger will reference them by number only
  3552. */
  3553. protected void genSemPredMap(String prefix) {
  3554. Enumeration e = semPreds.elements();
  3555. println("const char* " + prefix + "_semPredNames[] = {");
  3556. tabs++;
  3557. while(e.hasMoreElements())
  3558. println("\""+e.nextElement()+"\",");
  3559. println("0");
  3560. tabs--;
  3561. println("};");
  3562. }
  3563. protected void genSynPred(SynPredBlock blk, String lookaheadExpr) {
  3564. if ( DEBUG_CODE_GENERATOR || DEBUG_CPP_CODE_GENERATOR ) System.out.println("gen=>("+blk+")");
  3565. // Dump synpred result variable
  3566. println("bool synPredMatched" + blk.ID + " = false;");
  3567. // Gen normal lookahead test
  3568. println("if (" + lookaheadExpr + ") {");
  3569. tabs++;
  3570. // Save input state
  3571. if ( grammar instanceof TreeWalkerGrammar ) {
  3572. println(labeledElementType + " __t" + blk.ID + " = _t;");
  3573. }
  3574. else {
  3575. println("int _m" + blk.ID + " = mark();");
  3576. }
  3577. // Once inside the try, assume synpred works unless exception caught
  3578. println("synPredMatched" + blk.ID + " = true;");
  3579. println("inputState->guessing++;");
  3580. // if debugging, tell listeners that a synpred has started
  3581. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  3582. (grammar instanceof LexerGrammar))) {
  3583. println("fireSyntacticPredicateStarted();");
  3584. }
  3585. syntacticPredLevel++;
  3586. println("try {");
  3587. tabs++;
  3588. gen((AlternativeBlock)blk); // gen code to test predicate
  3589. tabs--;
  3590. //println("System.out.println(\"pred "+blk+" succeeded\");");
  3591. println("}");
  3592. println("catch (" + exceptionThrown + "& pe) {");
  3593. tabs++;
  3594. println("synPredMatched"+blk.ID+" = false;");
  3595. //println("System.out.println(\"pred "+blk+" failed\");");
  3596. tabs--;
  3597. println("}");
  3598. // Restore input state
  3599. if ( grammar instanceof TreeWalkerGrammar ) {
  3600. println("_t = __t"+blk.ID+";");
  3601. }
  3602. else {
  3603. println("rewind(_m"+blk.ID+");");
  3604. }
  3605. println("inputState->guessing--;");
  3606. // if debugging, tell listeners how the synpred turned out
  3607. if (grammar.debuggingOutput && ((grammar instanceof ParserGrammar) ||
  3608. (grammar instanceof LexerGrammar))) {
  3609. println("if (synPredMatched" + blk.ID +")");
  3610. println(" fireSyntacticPredicateSucceeded();");
  3611. println("else");
  3612. println(" fireSyntacticPredicateFailed();");
  3613. }
  3614. syntacticPredLevel--;
  3615. tabs--;
  3616. // Close lookahead test
  3617. println("}");
  3618. // Test synpred result
  3619. println("if ( synPredMatched"+blk.ID+" ) {");
  3620. }
  3621. /** Generate a static array containing the names of the tokens,
  3622. * indexed by the token type values. This static array is used
  3623. * to format error messages so that the token identifers or literal
  3624. * strings are displayed instead of the token numbers.
  3625. *
  3626. * If a lexical rule has a paraphrase, use it rather than the
  3627. * token label.
  3628. */
  3629. public void genTokenStrings(String prefix) {
  3630. // Generate a string for each token. This creates a static
  3631. // array of Strings indexed by token type.
  3632. // println("");
  3633. println("const char* " + prefix + "tokenNames[] = {");
  3634. tabs++;
  3635. // Walk the token vocabulary and generate a Vector of strings
  3636. // from the tokens.
  3637. Vector v = grammar.tokenManager.getVocabulary();
  3638. for (int i = 0; i < v.size(); i++)
  3639. {
  3640. String s = (String)v.elementAt(i);
  3641. if (s == null)
  3642. {
  3643. s = "<"+String.valueOf(i)+">";
  3644. }
  3645. if ( !s.startsWith("\"") && !s.startsWith("<") ) {
  3646. TokenSymbol ts = (TokenSymbol)grammar.tokenManager.getTokenSymbol(s);
  3647. if ( ts!=null && ts.getParaphrase()!=null ) {
  3648. s = StringUtils.stripFrontBack(ts.getParaphrase(), "\"", "\"");
  3649. }
  3650. }
  3651. print(charFormatter.literalString(s));
  3652. _println(",");
  3653. }
  3654. println("0");
  3655. // Close the string array initailizer
  3656. tabs--;
  3657. println("};");
  3658. }
  3659. /** Generate the token types C++ file */
  3660. protected void genTokenTypes(TokenManager tm) throws IOException {
  3661. // Open the token output header file and set the currentOutput stream
  3662. outputFile = tm.getName() + TokenTypesFileSuffix+".hpp";
  3663. outputLine = 1;
  3664. currentOutput = antlrTool.openOutputFile(outputFile);
  3665. //SAS: changed for proper text file io
  3666. tabs = 0;
  3667. // Generate a guard wrapper
  3668. println("#ifndef INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
  3669. println("#define INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_");
  3670. println("");
  3671. if (nameSpace != null)
  3672. nameSpace.emitDeclarations(currentOutput);
  3673. // Generate the header common to all C++ files
  3674. genHeader(outputFile);
  3675. // Encapsulate the definitions in an interface. This can be done
  3676. // because they are all constants.
  3677. println("");
  3678. println("#ifndef CUSTOM_API");
  3679. println("# define CUSTOM_API");
  3680. println("#endif");
  3681. println("");
  3682. // In the case that the .hpp is included from C source (flexLexer!)
  3683. // we just turn things into a plain enum
  3684. println("#ifdef __cplusplus");
  3685. println("struct CUSTOM_API " + tm.getName() + TokenTypesFileSuffix+" {");
  3686. println("#endif");
  3687. tabs++;
  3688. println("enum {");
  3689. tabs++;
  3690. // Generate a definition for each token type
  3691. Vector v = tm.getVocabulary();
  3692. // Do special tokens manually
  3693. println("EOF_ = " + Token.EOF_TYPE + ",");
  3694. // Move the other special token to the end, so we can solve
  3695. // the superfluous comma problem easily
  3696. for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
  3697. String s = (String)v.elementAt(i);
  3698. if (s != null) {
  3699. if ( s.startsWith("\"") ) {
  3700. // a string literal
  3701. StringLiteralSymbol sl = (StringLiteralSymbol)tm.getTokenSymbol(s);
  3702. if ( sl==null ) {
  3703. antlrTool.panic("String literal "+s+" not in symbol table");
  3704. }
  3705. else if ( sl.label != null ) {
  3706. println(sl.label + " = " + i + ",");
  3707. }
  3708. else {
  3709. String mangledName = mangleLiteral(s);
  3710. if (mangledName != null) {
  3711. // We were able to create a meaningful mangled token name
  3712. println(mangledName + " = " + i + ",");
  3713. // if no label specified, make the label equal to the mangled name
  3714. sl.label = mangledName;
  3715. }
  3716. else {
  3717. println("// " + s + " = " + i);
  3718. }
  3719. }
  3720. }
  3721. else if ( !s.startsWith("<") ) {
  3722. println(s + " = " + i + ",");
  3723. }
  3724. }
  3725. }
  3726. // Moved from above
  3727. println("NULL_TREE_LOOKAHEAD = " + Token.NULL_TREE_LOOKAHEAD);
  3728. // Close the enum
  3729. tabs--;
  3730. println("};");
  3731. // Close the interface
  3732. tabs--;
  3733. println("#ifdef __cplusplus");
  3734. println("};");
  3735. println("#endif");
  3736. if (nameSpace != null)
  3737. nameSpace.emitClosures(currentOutput);
  3738. // Generate a guard wrapper
  3739. println("#endif /*INC_"+tm.getName()+TokenTypesFileSuffix+"_hpp_*/");
  3740. // Close the tokens output file
  3741. currentOutput.close();
  3742. currentOutput = null;
  3743. exitIfError();
  3744. }
  3745. /** Process a string for an simple expression for use in xx/action.g
  3746. * it is used to cast simple tokens/references to the right type for
  3747. * the generated language. Basically called for every element in
  3748. * the vector to getASTCreateString(vector V)
  3749. * @param str A String.
  3750. */
  3751. public String processStringForASTConstructor( String str )
  3752. {
  3753. if( usingCustomAST &&
  3754. ((grammar instanceof TreeWalkerGrammar) ||
  3755. (grammar instanceof ParserGrammar)) &&
  3756. !(grammar.tokenManager.tokenDefined(str) ) )
  3757. {
  3758. // System.out.println("processStringForASTConstructor: "+str+" with cast");
  3759. return namespaceAntlr+"RefAST("+str+")";
  3760. }
  3761. else
  3762. {
  3763. // System.out.println("processStringForASTConstructor: "+str);
  3764. return str;
  3765. }
  3766. }
  3767. /** Get a string for an expression to generate creation of an AST subtree.
  3768. * @param v A Vector of String, where each element is an expression
  3769. * in the target language yielding an AST node.
  3770. */
  3771. public String getASTCreateString(Vector v) {
  3772. if (v.size() == 0) {
  3773. return "";
  3774. }
  3775. StringBuffer buf = new StringBuffer();
  3776. // the labeledElementASTType here can probably be a cast or nothing
  3777. // in the case of ! usingCustomAST
  3778. buf.append(labeledElementASTType+
  3779. "(astFactory->make((new "+namespaceAntlr+
  3780. "ASTArray("+v.size()+"))");
  3781. for (int i = 0; i < v.size(); i++) {
  3782. buf.append("->add("+ v.elementAt(i) + ")");
  3783. }
  3784. buf.append("))");
  3785. return buf.toString();
  3786. }
  3787. /** Get a string for an expression to generate creating of an AST node
  3788. * @param str The arguments to the AST constructor
  3789. */
  3790. public String getASTCreateString(GrammarAtom atom, String str) {
  3791. if ( atom!=null && atom.getASTNodeType() != null ) {
  3792. // this atom is using a heterogeneous AST type. (and maybe a local
  3793. // override we can't see at the TokenManager level)
  3794. // make note of the factory needed to generate it..
  3795. // later this is inserted into the initializeFactory method.
  3796. astTypes.ensureCapacity(atom.getType());
  3797. String type = (String)astTypes.elementAt(atom.getType());
  3798. if( type == null )
  3799. astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
  3800. else
  3801. {
  3802. // give a warning over action taken if the types are unequal
  3803. if( ! atom.getASTNodeType().equals(type) )
  3804. {
  3805. antlrTool.warning("Attempt to redefine AST type for "+atom.getText(),grammar.getFilename(),atom.getLine(),atom.getColumn());
  3806. antlrTool.warning(" from \""+type+"\" to \""+atom.getASTNodeType()+"\" sticking to \""+type+"\"",grammar.getFilename(),atom.getLine(),atom.getColumn());
  3807. }
  3808. else
  3809. astTypes.setElementAt(atom.getASTNodeType(),atom.getType());
  3810. }
  3811. // after above init the factory knows what to generate...
  3812. return "astFactory->create("+str+")";
  3813. }
  3814. else
  3815. {
  3816. // FIXME: This is *SO* ugly! but it will have to do for now...
  3817. // 2.7.2 will have better I hope
  3818. // this is due to the usage of getASTCreateString from inside
  3819. // actions/cpp/action.g
  3820. boolean is_constructor = false;
  3821. if( str.indexOf(',') != -1 )
  3822. is_constructor = grammar.tokenManager.tokenDefined(str.substring(0,str.indexOf(',')));
  3823. // System.out.println("getAstCreateString(as): "+str+" "+grammar.tokenManager.tokenDefined(str));
  3824. if( usingCustomAST &&
  3825. (grammar instanceof TreeWalkerGrammar) &&
  3826. !(grammar.tokenManager.tokenDefined(str) ) &&
  3827. ! is_constructor )
  3828. return "astFactory->create("+namespaceAntlr+"RefAST("+str+"))";
  3829. else
  3830. return "astFactory->create("+str+")";
  3831. }
  3832. }
  3833. /** Get a string for an expression to generate creating of an AST node
  3834. * @param str The arguments to the AST constructor
  3835. */
  3836. public String getASTCreateString(String str) {
  3837. // System.out.println("getAstCreateString(str): "+str+" "+grammar.tokenManager.tokenDefined(str));
  3838. if( usingCustomAST )
  3839. return labeledElementASTType+"(astFactory->create("+namespaceAntlr+"RefAST("+str+")))";
  3840. else
  3841. return "astFactory->create("+str+")";
  3842. }
  3843. protected String getLookaheadTestExpression(Lookahead[] look, int k) {
  3844. StringBuffer e = new StringBuffer(100);
  3845. boolean first = true;
  3846. e.append("(");
  3847. for (int i = 1; i <= k; i++) {
  3848. BitSet p = look[i].fset;
  3849. if (!first) {
  3850. e.append(") && (");
  3851. }
  3852. first = false;
  3853. // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
  3854. // There is no way to predict what that token would be. Just
  3855. // allow anything instead.
  3856. if (look[i].containsEpsilon()) {
  3857. e.append("true");
  3858. } else {
  3859. e.append(getLookaheadTestTerm(i, p));
  3860. }
  3861. }
  3862. e.append(")");
  3863. return e.toString();
  3864. }
  3865. /** Generate a lookahead test expression for an alternate. This
  3866. * will be a series of tests joined by '&&' and enclosed by '()',
  3867. * the number of such tests being determined by the depth of the lookahead.
  3868. */
  3869. protected String getLookaheadTestExpression(Alternative alt, int maxDepth) {
  3870. int depth = alt.lookaheadDepth;
  3871. if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
  3872. // if the decision is nondeterministic, do the best we can: LL(k)
  3873. // any predicates that are around will be generated later.
  3874. depth = grammar.maxk;
  3875. }
  3876. if ( maxDepth==0 ) {
  3877. // empty lookahead can result from alt with sem pred
  3878. // that can see end of token. E.g., A : {pred}? ('a')? ;
  3879. return "true";
  3880. }
  3881. /*
  3882. boolean first = true;
  3883. for (int i=1; i<=depth && i<=maxDepth; i++) {
  3884. BitSet p = alt.cache[i].fset;
  3885. if (!first) {
  3886. e.append(") && (");
  3887. }
  3888. first = false;
  3889. // Syn preds can yield <end-of-syn-pred> (epsilon) lookahead.
  3890. // There is no way to predict what that token would be. Just
  3891. // allow anything instead.
  3892. if ( alt.cache[i].containsEpsilon() ) {
  3893. e.append("true");
  3894. }
  3895. else {
  3896. e.append(getLookaheadTestTerm(i, p));
  3897. }
  3898. }
  3899. e.append(")");
  3900. */
  3901. return "(" + getLookaheadTestExpression(alt.cache,depth) + ")";
  3902. }
  3903. /**Generate a depth==1 lookahead test expression given the BitSet.
  3904. * This may be one of:
  3905. * 1) a series of 'x==X||' tests
  3906. * 2) a range test using >= && <= where possible,
  3907. * 3) a bitset membership test for complex comparisons
  3908. * @param k The lookahead level
  3909. * @param p The lookahead set for level k
  3910. */
  3911. protected String getLookaheadTestTerm(int k, BitSet p) {
  3912. // Determine the name of the item to be compared
  3913. String ts = lookaheadString(k);
  3914. // Generate a range expression if possible
  3915. int[] elems = p.toArray();
  3916. if (elementsAreRange(elems)) {
  3917. return getRangeExpression(k, elems);
  3918. }
  3919. // Generate a bitset membership test if possible
  3920. StringBuffer e;
  3921. int degree = p.degree();
  3922. if ( degree == 0 ) {
  3923. return "true";
  3924. }
  3925. if (degree >= bitsetTestThreshold) {
  3926. int bitsetIdx = markBitsetForGen(p);
  3927. return getBitsetName(bitsetIdx) + ".member(" + ts + ")";
  3928. }
  3929. // Otherwise, generate the long-winded series of "x==X||" tests
  3930. e = new StringBuffer();
  3931. for (int i = 0; i < elems.length; i++) {
  3932. // Get the compared-to item (token or character value)
  3933. String cs = getValueString(elems[i]);
  3934. // Generate the element comparison
  3935. if( i > 0 ) e.append(" || ");
  3936. e.append(ts);
  3937. e.append(" == ");
  3938. e.append(cs);
  3939. }
  3940. return e.toString();
  3941. }
  3942. /** Return an expression for testing a contiguous renage of elements
  3943. * @param k The lookahead level
  3944. * @param elems The elements representing the set, usually from BitSet.toArray().
  3945. * @return String containing test expression.
  3946. */
  3947. public String getRangeExpression(int k, int[] elems) {
  3948. if (!elementsAreRange(elems)) {
  3949. antlrTool.panic("getRangeExpression called with non-range");
  3950. }
  3951. int begin = elems[0];
  3952. int end = elems[elems.length-1];
  3953. return
  3954. "(" + lookaheadString(k) + " >= " + getValueString(begin) + " && " +
  3955. lookaheadString(k) + " <= " + getValueString(end) + ")";
  3956. }
  3957. /** getValueString: get a string representation of a token or char value
  3958. * @param value The token or char value
  3959. */
  3960. private String getValueString(int value) {
  3961. String cs;
  3962. if ( grammar instanceof LexerGrammar ) {
  3963. cs = charFormatter.literalChar(value);
  3964. }
  3965. else
  3966. {
  3967. TokenSymbol ts = grammar.tokenManager.getTokenSymbolAt(value);
  3968. if ( ts == null ) {
  3969. return ""+value; // return token type as string
  3970. // tool.panic("vocabulary for token type " + value + " is null");
  3971. }
  3972. String tId = ts.getId();
  3973. if ( ts instanceof StringLiteralSymbol ) {
  3974. // if string literal, use predefined label if any
  3975. // if no predefined, try to mangle into LITERAL_xxx.
  3976. // if can't mangle, use int value as last resort
  3977. StringLiteralSymbol sl = (StringLiteralSymbol)ts;
  3978. String label = sl.getLabel();
  3979. if ( label!=null ) {
  3980. cs = label;
  3981. }
  3982. else {
  3983. cs = mangleLiteral(tId);
  3984. if (cs == null) {
  3985. cs = String.valueOf(value);
  3986. }
  3987. }
  3988. }
  3989. else {
  3990. if ( tId.equals("EOF") )
  3991. cs = namespaceAntlr+"Token::EOF_TYPE";
  3992. else
  3993. cs = tId;
  3994. }
  3995. }
  3996. return cs;
  3997. }
  3998. /**Is the lookahead for this alt empty? */
  3999. protected boolean lookaheadIsEmpty(Alternative alt, int maxDepth) {
  4000. int depth = alt.lookaheadDepth;
  4001. if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
  4002. depth = grammar.maxk;
  4003. }
  4004. for (int i=1; i<=depth && i<=maxDepth; i++) {
  4005. BitSet p = alt.cache[i].fset;
  4006. if (p.degree() != 0) {
  4007. return false;
  4008. }
  4009. }
  4010. return true;
  4011. }
  4012. private String lookaheadString(int k) {
  4013. if (grammar instanceof TreeWalkerGrammar) {
  4014. return "_t->getType()";
  4015. }
  4016. return "LA(" + k + ")";
  4017. }
  4018. /** Mangle a string literal into a meaningful token name. This is
  4019. * only possible for literals that are all characters. The resulting
  4020. * mangled literal name is literalsPrefix with the text of the literal
  4021. * appended.
  4022. * @return A string representing the mangled literal, or null if not possible.
  4023. */
  4024. private String mangleLiteral(String s) {
  4025. String mangled = antlrTool.literalsPrefix;
  4026. for (int i = 1; i < s.length()-1; i++) {
  4027. if (!Character.isLetter(s.charAt(i)) &&
  4028. s.charAt(i) != '_') {
  4029. return null;
  4030. }
  4031. mangled += s.charAt(i);
  4032. }
  4033. if ( antlrTool.upperCaseMangledLiterals ) {
  4034. mangled = mangled.toUpperCase();
  4035. }
  4036. return mangled;
  4037. }
  4038. /** Map an identifier to it's corresponding tree-node variable.
  4039. * This is context-sensitive, depending on the rule and alternative
  4040. * being generated
  4041. * @param idParam The identifier name to map
  4042. * @return The mapped id (which may be the same as the input), or null if the mapping is invalid due to duplicates
  4043. */
  4044. public String mapTreeId(String idParam, ActionTransInfo transInfo) {
  4045. // if not in an action of a rule, nothing to map.
  4046. if ( currentRule==null ) return idParam;
  4047. // System.out.print("mapTreeId: "+idParam+" "+currentRule.getRuleName()+" ");
  4048. boolean in_var = false;
  4049. String id = idParam;
  4050. if (grammar instanceof TreeWalkerGrammar)
  4051. {
  4052. // RK: hmmm this seems odd. If buildAST is false it translates
  4053. // #rulename_in to 'rulename_in' else to 'rulename_AST_in' which indeed
  4054. // exists. disabling for now.. and hope it doesn't blow up somewhere.
  4055. if ( !grammar.buildAST )
  4056. {
  4057. in_var = true;
  4058. // System.out.println("in_var1");
  4059. }
  4060. // If the id ends with "_in", then map it to the input variable
  4061. // else
  4062. if (id.length() > 3 && id.lastIndexOf("_in") == id.length()-3)
  4063. {
  4064. // Strip off the "_in"
  4065. id = id.substring(0, id.length()-3);
  4066. in_var = true;
  4067. // System.out.println("in_var2");
  4068. }
  4069. }
  4070. // System.out.print(in_var+"\t");
  4071. // Check the rule labels. If id is a label, then the output
  4072. // variable is label_AST, and the input variable is plain label.
  4073. for (int i = 0; i < currentRule.labeledElements.size(); i++)
  4074. {
  4075. AlternativeElement elt = (AlternativeElement)currentRule.labeledElements.elementAt(i);
  4076. if (elt.getLabel().equals(id))
  4077. {
  4078. // if( in_var )
  4079. // System.out.println("returning (vec) "+(in_var ? id : id + "_AST"));
  4080. return in_var ? id : id + "_AST";
  4081. }
  4082. }
  4083. // Failing that, check the id-to-variable map for the alternative.
  4084. // If the id is in the map, then output variable is the name in the
  4085. // map, and input variable is name_in
  4086. String s = (String)treeVariableMap.get(id);
  4087. if (s != null)
  4088. {
  4089. if (s == NONUNIQUE)
  4090. {
  4091. // if( in_var )
  4092. // System.out.println("returning null (nonunique)");
  4093. // There is more than one element with this id
  4094. antlrTool.error("Ambiguous reference to AST element "+id+
  4095. " in rule "+currentRule.getRuleName());
  4096. return null;
  4097. }
  4098. else if (s.equals(currentRule.getRuleName()))
  4099. {
  4100. // a recursive call to the enclosing rule is
  4101. // ambiguous with the rule itself.
  4102. // if( in_var )
  4103. // System.out.println("returning null (rulename)");
  4104. antlrTool.error("Ambiguous reference to AST element "+id+
  4105. " in rule "+currentRule.getRuleName());
  4106. return null;
  4107. }
  4108. else
  4109. {
  4110. // if( in_var )
  4111. // System.out.println("returning "+(in_var?s+"_in":s));
  4112. return in_var ? s + "_in" : s;
  4113. }
  4114. }
  4115. // System.out.println("Last check: "+id+" == "+currentRule.getRuleName());
  4116. // Failing that, check the rule name itself. Output variable
  4117. // is rule_AST; input variable is rule_AST_in (treeparsers).
  4118. if( id.equals(currentRule.getRuleName()) )
  4119. {
  4120. String r = in_var ? id + "_AST_in" : id + "_AST";
  4121. if ( transInfo!=null ) {
  4122. if ( !in_var ) {
  4123. transInfo.refRuleRoot = r;
  4124. }
  4125. }
  4126. // if( in_var )
  4127. // System.out.println("returning (r) "+r);
  4128. return r;
  4129. }
  4130. else
  4131. {
  4132. // if( in_var )
  4133. // System.out.println("returning (last) "+id);
  4134. // id does not map to anything -- return itself.
  4135. return id;
  4136. }
  4137. }
  4138. /** Given an element and the name of an associated AST variable,
  4139. * create a mapping between the element "name" and the variable name.
  4140. */
  4141. private void mapTreeVariable(AlternativeElement e, String name)
  4142. {
  4143. // For tree elements, defer to the root
  4144. if (e instanceof TreeElement) {
  4145. mapTreeVariable( ((TreeElement)e).root, name);
  4146. return;
  4147. }
  4148. // Determine the name of the element, if any, for mapping purposes
  4149. String elName = null;
  4150. // Don't map labeled items
  4151. if (e.getLabel() == null) {
  4152. if (e instanceof TokenRefElement) {
  4153. // use the token id
  4154. elName = ((TokenRefElement)e).atomText;
  4155. }
  4156. else if (e instanceof RuleRefElement) {
  4157. // use the rule name
  4158. elName = ((RuleRefElement)e).targetRule;
  4159. }
  4160. }
  4161. // Add the element to the tree variable map if it has a name
  4162. if (elName != null) {
  4163. if (treeVariableMap.get(elName) != null) {
  4164. // Name is already in the map -- mark it as duplicate
  4165. treeVariableMap.remove(elName);
  4166. treeVariableMap.put(elName, NONUNIQUE);
  4167. }
  4168. else {
  4169. treeVariableMap.put(elName, name);
  4170. }
  4171. }
  4172. }
  4173. /** Lexically process tree-specifiers in the action.
  4174. * This will replace #id and #(...) with the appropriate
  4175. * function calls and/or variables.
  4176. */
  4177. protected String processActionForSpecialSymbols(String actionStr,
  4178. int line,
  4179. RuleBlock currentRule,
  4180. ActionTransInfo tInfo)
  4181. {
  4182. if ( actionStr==null || actionStr.length()==0 )
  4183. return null;
  4184. // The action trans info tells us (at the moment) whether an
  4185. // assignment was done to the rule's tree root.
  4186. if (grammar==null)
  4187. return actionStr;
  4188. if ((grammar.buildAST && actionStr.indexOf('#') != -1) ||
  4189. grammar instanceof TreeWalkerGrammar ||
  4190. ((grammar instanceof LexerGrammar ||
  4191. grammar instanceof ParserGrammar)
  4192. && actionStr.indexOf('$') != -1) )
  4193. {
  4194. // Create a lexer to read an action and return the translated version
  4195. antlr.actions.cpp.ActionLexer lexer =
  4196. new antlr.actions.cpp.ActionLexer(actionStr, currentRule, this, tInfo);
  4197. lexer.setLineOffset(line);
  4198. lexer.setFilename(grammar.getFilename());
  4199. lexer.setTool(antlrTool);
  4200. try {
  4201. lexer.mACTION(true);
  4202. actionStr = lexer.getTokenObject().getText();
  4203. // System.out.println("action translated: "+actionStr);
  4204. // System.out.println("trans info is "+tInfo);
  4205. }
  4206. catch (RecognitionException ex) {
  4207. lexer.reportError(ex);
  4208. return actionStr;
  4209. }
  4210. catch (TokenStreamException tex) {
  4211. antlrTool.panic("Error reading action:"+actionStr);
  4212. return actionStr;
  4213. }
  4214. catch (CharStreamException io) {
  4215. antlrTool.panic("Error reading action:"+actionStr);
  4216. return actionStr;
  4217. }
  4218. }
  4219. return actionStr;
  4220. }
  4221. private String fixNameSpaceOption( String ns )
  4222. {
  4223. ns = StringUtils.stripFrontBack(ns,"\"","\"");
  4224. if( ns.length() > 2 &&
  4225. !ns.substring(ns.length()-2, ns.length()).equals("::") )
  4226. ns += "::";
  4227. return ns;
  4228. }
  4229. private void setupGrammarParameters(Grammar g) {
  4230. if (g instanceof ParserGrammar ||
  4231. g instanceof LexerGrammar ||
  4232. g instanceof TreeWalkerGrammar
  4233. )
  4234. {
  4235. /* RK: options also have to be added to Grammar.java and for options
  4236. * on the file level entries have to be defined in
  4237. * DefineGrammarSymbols.java and passed around via 'globals' in
  4238. * antlrTool.java
  4239. */
  4240. if( antlrTool.nameSpace != null )
  4241. nameSpace = antlrTool.nameSpace;
  4242. if( antlrTool.namespaceStd != null )
  4243. namespaceStd = fixNameSpaceOption(antlrTool.namespaceStd);
  4244. if( antlrTool.namespaceAntlr != null )
  4245. namespaceAntlr = fixNameSpaceOption(antlrTool.namespaceAntlr);
  4246. genHashLines = antlrTool.genHashLines;
  4247. /* let grammar level options override filelevel ones...
  4248. */
  4249. if( g.hasOption("namespace") ) {
  4250. Token t = g.getOption("namespace");
  4251. if( t != null ) {
  4252. nameSpace = new NameSpace(t.getText());
  4253. }
  4254. }
  4255. if( g.hasOption("namespaceAntlr") ) {
  4256. Token t = g.getOption("namespaceAntlr");
  4257. if( t != null ) {
  4258. String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
  4259. if ( ns != null ) {
  4260. if( ns.length() > 2 &&
  4261. !ns.substring(ns.length()-2, ns.length()).equals("::") )
  4262. ns += "::";
  4263. namespaceAntlr = ns;
  4264. }
  4265. }
  4266. }
  4267. if( g.hasOption("namespaceStd") ) {
  4268. Token t = g.getOption("namespaceStd");
  4269. if( t != null ) {
  4270. String ns = StringUtils.stripFrontBack(t.getText(),"\"","\"");
  4271. if ( ns != null ) {
  4272. if( ns.length() > 2 &&
  4273. !ns.substring(ns.length()-2, ns.length()).equals("::") )
  4274. ns += "::";
  4275. namespaceStd = ns;
  4276. }
  4277. }
  4278. }
  4279. if( g.hasOption("genHashLines") ) {
  4280. Token t = g.getOption("genHashLines");
  4281. if( t != null ) {
  4282. String val = StringUtils.stripFrontBack(t.getText(),"\"","\"");
  4283. genHashLines = val.equals("true");
  4284. }
  4285. }
  4286. noConstructors = antlrTool.noConstructors; // get the default
  4287. if( g.hasOption("noConstructors") ) {
  4288. Token t = g.getOption("noConstructors");
  4289. if( (t != null) && !(t.getText().equals("true") || t.getText().equals("false")))
  4290. antlrTool.error("noConstructors option must be true or false", antlrTool.getGrammarFile(), t.getLine(), t.getColumn());
  4291. noConstructors = t.getText().equals("true");
  4292. }
  4293. }
  4294. if (g instanceof ParserGrammar) {
  4295. labeledElementASTType = namespaceAntlr+"RefAST";
  4296. labeledElementASTInit = namespaceAntlr+"nullAST";
  4297. if ( g.hasOption("ASTLabelType") ) {
  4298. Token tsuffix = g.getOption("ASTLabelType");
  4299. if ( tsuffix != null ) {
  4300. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  4301. if ( suffix != null ) {
  4302. usingCustomAST = true;
  4303. labeledElementASTType = suffix;
  4304. labeledElementASTInit = suffix+"("+namespaceAntlr+"nullAST)";
  4305. }
  4306. }
  4307. }
  4308. labeledElementType = namespaceAntlr+"RefToken ";
  4309. labeledElementInit = namespaceAntlr+"nullToken";
  4310. commonExtraArgs = "";
  4311. commonExtraParams = "";
  4312. commonLocalVars = "";
  4313. lt1Value = "LT(1)";
  4314. exceptionThrown = namespaceAntlr+"RecognitionException";
  4315. throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(LT(1), getFilename());";
  4316. }
  4317. else if (g instanceof LexerGrammar) {
  4318. labeledElementType = "char ";
  4319. labeledElementInit = "'\\0'";
  4320. commonExtraArgs = "";
  4321. commonExtraParams = "bool _createToken";
  4322. commonLocalVars = "int _ttype; "+namespaceAntlr+"RefToken _token; "+namespaceStd+"string::size_type _begin = text.length();";
  4323. lt1Value = "LA(1)";
  4324. exceptionThrown = namespaceAntlr+"RecognitionException";
  4325. throwNoViable = "throw "+namespaceAntlr+"NoViableAltForCharException(LA(1), getFilename(), getLine(), getColumn());";
  4326. }
  4327. else if (g instanceof TreeWalkerGrammar) {
  4328. labeledElementInit = namespaceAntlr+"nullAST";
  4329. labeledElementASTInit = namespaceAntlr+"nullAST";
  4330. labeledElementASTType = namespaceAntlr+"RefAST";
  4331. labeledElementType = namespaceAntlr+"RefAST";
  4332. commonExtraParams = namespaceAntlr+"RefAST _t";
  4333. throwNoViable = "throw "+namespaceAntlr+"NoViableAltException(_t);";
  4334. lt1Value = "_t";
  4335. if ( g.hasOption("ASTLabelType") ) {
  4336. Token tsuffix = g.getOption("ASTLabelType");
  4337. if ( tsuffix != null ) {
  4338. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  4339. if ( suffix != null ) {
  4340. usingCustomAST = true;
  4341. labeledElementASTType = suffix;
  4342. labeledElementType = suffix;
  4343. labeledElementInit = suffix+"("+namespaceAntlr+"nullAST)";
  4344. labeledElementASTInit = labeledElementInit;
  4345. commonExtraParams = suffix+" _t";
  4346. throwNoViable = "throw "+namespaceAntlr+"NoViableAltException("+namespaceAntlr+"RefAST(_t));";
  4347. lt1Value = "_t";
  4348. }
  4349. }
  4350. }
  4351. if ( !g.hasOption("ASTLabelType") ) {
  4352. g.setOption("ASTLabelType", new Token(ANTLRTokenTypes.STRING_LITERAL,namespaceAntlr+"RefAST"));
  4353. }
  4354. commonExtraArgs = "_t";
  4355. commonLocalVars = "";
  4356. exceptionThrown = namespaceAntlr+"RecognitionException";
  4357. }
  4358. else {
  4359. antlrTool.panic("Unknown grammar type");
  4360. }
  4361. }
  4362. }