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

编译器/解释器

开发平台:

Others

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