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

编译器/解释器

开发平台:

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/DiagnosticCodeGenerator.java#1 $
  7.  */
  8. import java.util.Enumeration;
  9. import antlr.collections.impl.BitSet;
  10. import antlr.collections.impl.Vector;
  11. import java.io.PrintWriter; //SAS: changed for proper text file io
  12. import java.io.IOException;
  13. import java.io.FileWriter;
  14. /**Generate MyParser.txt, MyLexer.txt and MyParserTokenTypes.txt */
  15. public class DiagnosticCodeGenerator extends CodeGenerator {
  16. /** non-zero if inside syntactic predicate generation */
  17. protected int syntacticPredLevel = 0;
  18. /** true during lexer generation, false during parser generation */
  19. protected boolean doingLexRules = false;
  20. /** Create a Diagnostic code-generator using the given Grammar
  21.  * The caller must still call setTool, setBehavior, and setAnalyzer
  22.  * before generating code.
  23.  */
  24. public DiagnosticCodeGenerator() {
  25. super();
  26. charFormatter = new JavaCharFormatter();
  27. }
  28. /**Generate the parser, lexer, and token types documentation */
  29. public void gen() {
  30. // Do the code generation
  31. try {
  32. // Loop over all grammars
  33. Enumeration grammarIter = behavior.grammars.elements();
  34. while (grammarIter.hasMoreElements()) {
  35. Grammar g = (Grammar)grammarIter.nextElement();
  36. // Connect all the components to each other
  37. g.setGrammarAnalyzer(analyzer);
  38. g.setCodeGenerator(this);
  39. analyzer.setGrammar(g);
  40. // To get right overloading behavior across hetrogeneous grammars
  41. g.generate();
  42. if (tool.hasError) {
  43. System.out.println("Exiting due to errors.");
  44. System.exit(1);
  45. }
  46. }
  47. // Loop over all token managers (some of which are lexers)
  48. Enumeration tmIter = behavior.tokenManagers.elements();
  49. while (tmIter.hasMoreElements()) {
  50. TokenManager tm = (TokenManager)tmIter.nextElement();
  51. if (!tm.isReadOnly()) {
  52. // Write the token manager tokens as Java
  53. genTokenTypes(tm);
  54. }
  55. }
  56. }
  57. catch (IOException e) {
  58. System.out.println(e.getMessage());
  59. }
  60. }
  61. /** Generate code for the given grammar element.
  62.  * @param blk The {...} action to generate
  63.  */
  64. public void gen(ActionElement action) {
  65. if (action.isSemPred) {
  66. // handled elsewhere
  67. }
  68. else {
  69. print("ACTION: ");
  70. _printAction(action.actionText);
  71. }
  72. }
  73. /** Generate code for the given grammar element.
  74.  * @param blk The "x|y|z|..." block to generate
  75.  */
  76. public void gen(AlternativeBlock blk) {
  77. println("Start of alternative block.");
  78. tabs++;
  79. genBlockPreamble(blk);
  80. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  81. if (!ok) {
  82. println("Warning: This alternative block is non-deterministic");
  83. }
  84. genCommonBlock(blk);
  85. tabs--;
  86. }
  87. /** Generate code for the given grammar element.
  88.  * @param blk The block-end element to generate.  Block-end
  89.  * elements are synthesized by the grammar parser to represent
  90.  * the end of a block.
  91.  */
  92. public void gen(BlockEndElement end) {
  93. // no-op
  94. }
  95. /** Generate code for the given grammar element.
  96.  * @param blk The character literal reference to generate
  97.  */
  98. public void gen(CharLiteralElement atom) {
  99. print("Match character ");
  100. if (atom.not) {
  101. _print("NOT ");
  102. }
  103. _print(atom.atomText);
  104. if (atom.label != null) {
  105. _print(", label=" + atom.label);
  106. }
  107. _println("");
  108. }
  109. /** Generate code for the given grammar element.
  110.  * @param blk The character-range reference to generate
  111.  */
  112. public void gen(CharRangeElement r) {
  113. print("Match character range: " + r.beginText + ".." + r.endText);
  114. if ( r.label!=null ) {
  115. _print(", label = " + r.label);
  116. }
  117. _println("");
  118. }
  119. /** Generate the lexer TXT file */
  120. public void gen(LexerGrammar g) throws IOException {
  121. setGrammar(g);
  122. System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
  123. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName() + TokenTypesFileExt);
  124. //SAS: changed for proper text file io
  125. tabs=0;
  126. doingLexRules = true;
  127. // Generate header common to all TXT output files
  128. genHeader();
  129. // Output the user-defined lexer premamble
  130. println("");
  131. println("*** Lexer Preamble Action.");
  132. println("This action will appear before the declaration of your lexer class:");
  133. tabs++;
  134. println(grammar.preambleAction);
  135. tabs--;
  136. println("*** End of Lexer Preamble Action");
  137. // Generate lexer class definition
  138. println("");
  139. println("*** Your lexer class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
  140. // Generate user-defined parser class members
  141. println("");
  142. println("*** User-defined lexer  class members:");
  143. println("These are the member declarations that you defined for your class:");
  144. tabs++;
  145. printAction(grammar.classMemberAction);
  146. tabs--;
  147. println("*** End of user-defined lexer class members");
  148. // Generate string literals
  149. println("");
  150. println("*** String literals used in the parser");
  151. println("The following string literals were used in the parser.");
  152. println("An actual code generator would arrange to place these literals");
  153. println("into a table in the generated lexer, so that actions in the");
  154. println("generated lexer could match token text against the literals.");
  155. println("String literals used in the lexer are not listed here, as they");
  156. println("are incorporated into the mainstream lexer processing.");
  157. tabs++;
  158. // Enumerate all of the symbols and look for string literal symbols
  159. Enumeration ids = grammar.getSymbols();
  160. while ( ids.hasMoreElements() ) {
  161. GrammarSymbol sym = (GrammarSymbol)ids.nextElement();
  162. // Only processing string literals -- reject other symbol entries
  163. if ( sym instanceof StringLiteralSymbol ) {
  164. StringLiteralSymbol s = (StringLiteralSymbol)sym;
  165. println(s.getId() + " = " + s.getTokenType());
  166. }
  167. }
  168. tabs--;
  169. println("*** End of string literals used by the parser");
  170. // Generate nextToken() rule.
  171. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  172. // user-defined lexer rules.
  173. genNextToken();
  174. // Generate code for each rule in the lexer
  175. println("");
  176. println("*** User-defined Lexer rules:");
  177. tabs++;
  178. ids = grammar.rules.elements();
  179. while ( ids.hasMoreElements() ) {
  180. RuleSymbol rs = (RuleSymbol)ids.nextElement();
  181. if (!rs.id.equals("mnextToken")) {
  182. genRule(rs);
  183. }
  184. }
  185. tabs--;
  186. println("");
  187. println("*** End User-defined Lexer rules:");
  188. // Close the lexer output file
  189. currentOutput.close();
  190. currentOutput = null;
  191. doingLexRules = false;
  192. }
  193. /** Generate code for the given grammar element.
  194.  * @param blk The (...)+ block to generate
  195.  */
  196. public void gen(OneOrMoreBlock blk) {
  197. println("Start ONE-OR-MORE (...)+ block:");
  198. tabs++;
  199. genBlockPreamble(blk);
  200. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  201. if (!ok) {
  202. println("Warning: This one-or-more block is non-deterministic");
  203. }
  204. genCommonBlock(blk);
  205. tabs--;
  206. println("End ONE-OR-MORE block.");
  207. }
  208. /** Generate the parser TXT file */
  209. public void gen(ParserGrammar g) throws IOException {
  210. setGrammar(g);
  211. // Open the output stream for the parser and set the currentOutput
  212. System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
  213. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName()+TokenTypesFileExt);
  214. //SAS: changed for proper text file io
  215. tabs = 0;
  216. // Generate the header common to all output files.
  217. genHeader();
  218. // Output the user-defined parser premamble
  219. println("");
  220. println("*** Parser Preamble Action.");
  221. println("This action will appear before the declaration of your parser class:");
  222. tabs++;
  223. println(grammar.preambleAction);
  224. tabs--;
  225. println("*** End of Parser Preamble Action");
  226. // Generate parser class definition
  227. println("");
  228. println("*** Your parser class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
  229. // Generate user-defined parser class members
  230. println("");
  231. println("*** User-defined parser class members:");
  232. println("These are the member declarations that you defined for your class:");
  233. tabs++;
  234. printAction(grammar.classMemberAction);
  235. tabs--;
  236. println("*** End of user-defined parser class members");
  237. // Generate code for each rule in the grammar
  238. println("");
  239. println("*** Parser rules:");
  240. tabs++;
  241. // Enumerate the parser rules
  242. Enumeration rules = grammar.rules.elements();
  243. while ( rules.hasMoreElements() ) {
  244. println("");
  245. // Get the rules from the list and downcast it to proper type
  246. GrammarSymbol sym = (GrammarSymbol) rules.nextElement();
  247. // Only process parser rules
  248. if ( sym instanceof RuleSymbol) {
  249. genRule((RuleSymbol)sym);
  250. }
  251. }
  252. tabs--;
  253. println("");
  254. println("*** End of parser rules");
  255. println("");
  256. println("*** End of parser");
  257. // Close the parser output stream
  258. currentOutput.close();
  259. currentOutput = null;
  260. }
  261. /** Generate code for the given grammar element.
  262.  * @param blk The rule-reference to generate
  263.  */
  264. public void gen(RuleRefElement rr) {
  265. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  266. // Generate the actual rule description
  267. print("Rule Reference: " + rr.targetRule);
  268. if (rr.idAssign != null) {
  269. _print(", assigned to '" + rr.idAssign + "'");
  270. }
  271. if (rr.args != null) {
  272. _print(", arguments = " + rr.args);
  273. }
  274. _println("");
  275. // Perform diagnostics
  276. if (rs == null || !rs.isDefined())
  277. {
  278. println("Rule '" + rr.targetRule + "' is referenced, but that rule is not defined.");
  279. println("tPerhaps the rule is misspelled, or you forgot to define it.");
  280. return;
  281. }
  282. if (!(rs instanceof RuleSymbol))
  283. {
  284. // Should this ever happen??
  285. println("Rule '" + rr.targetRule + "' is referenced, but that is not a grammar rule.");
  286. return;
  287. }
  288. if (rr.idAssign != null)
  289. {
  290. // Warn if the rule has no return type
  291. if (rs.block.returnAction == null)
  292. {
  293. println("Error: You assigned from Rule '" + rr.targetRule + "', but that rule has no return type.");
  294. }
  295. } else {
  296. // Warn about return value if any, but not inside syntactic predicate
  297. if (!(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
  298. {
  299. println("Warning: Rule '" + rr.targetRule + "' returns a value");
  300. }
  301. }
  302. if (rr.args != null && rs.block.argAction == null) {
  303. println("Error: Rule '" + rr.targetRule + "' accepts no arguments.");
  304. }
  305. }
  306. /** Generate code for the given grammar element.
  307.  * @param blk The string-literal reference to generate
  308.  */
  309. public void gen(StringLiteralElement atom) {
  310. print("Match string literal ");
  311. _print(atom.atomText);
  312. if (atom.label != null) {
  313. _print(", label=" + atom.label);
  314. }
  315. _println("");
  316. }
  317. /** Generate code for the given grammar element.
  318.  * @param blk The token-range reference to generate
  319.  */
  320. public void gen(TokenRangeElement r) {
  321. print("Match token range: " + r.beginText + ".." + r.endText);
  322. if ( r.label!=null ) {
  323. _print(", label = " + r.label);
  324. }
  325. _println("");
  326. }
  327. /** Generate code for the given grammar element.
  328.  * @param blk The token-reference to generate
  329.  */
  330. public void gen(TokenRefElement atom) {
  331. print("Match token ");
  332. if (atom.not) {
  333. _print("NOT ");
  334. }
  335. _print(atom.atomText);
  336. if (atom.label != null) {
  337. _print(", label=" + atom.label);
  338. }
  339. _println("");
  340. }
  341. public void gen(TreeElement t) {
  342. print("Tree reference: "+t);
  343. }
  344. /** Generate the tree-walker TXT file */
  345. public  void gen(TreeWalkerGrammar g) throws IOException {
  346. setGrammar(g);
  347. // Open the output stream for the parser and set the currentOutput
  348. System.out.println("Generating " + grammar.getClassName() + TokenTypesFileExt);
  349. currentOutput = antlr.Tool.openOutputFile(grammar.getClassName()+TokenTypesFileExt);
  350. //SAS: changed for proper text file io
  351. tabs = 0;
  352. // Generate the header common to all output files.
  353. genHeader();
  354. // Output the user-defined parser premamble
  355. println("");
  356. println("*** Tree-walker Preamble Action.");
  357. println("This action will appear before the declaration of your tree-walker class:");
  358. tabs++;
  359. println(grammar.preambleAction);
  360. tabs--;
  361. println("*** End of tree-walker Preamble Action");
  362. // Generate tree-walker class definition
  363. println("");
  364. println("*** Your tree-walker class is called '" + grammar.getClassName() + "' and is a subclass of '" + grammar.getSuperClass() + "'.");
  365. // Generate user-defined tree-walker class members
  366. println("");
  367. println("*** User-defined tree-walker class members:");
  368. println("These are the member declarations that you defined for your class:");
  369. tabs++;
  370. printAction(grammar.classMemberAction);
  371. tabs--;
  372. println("*** End of user-defined tree-walker class members");
  373. // Generate code for each rule in the grammar
  374. println("");
  375. println("*** tree-walker rules:");
  376. tabs++;
  377. // Enumerate the tree-walker rules
  378. Enumeration rules = grammar.rules.elements();
  379. while ( rules.hasMoreElements() ) {
  380. println("");
  381. // Get the rules from the list and downcast it to proper type
  382. GrammarSymbol sym = (GrammarSymbol) rules.nextElement();
  383. // Only process tree-walker rules
  384. if ( sym instanceof RuleSymbol) {
  385. genRule((RuleSymbol)sym);
  386. }
  387. }
  388. tabs--;
  389. println("");
  390. println("*** End of tree-walker rules");
  391. println("");
  392. println("*** End of tree-walker");
  393. // Close the tree-walker output stream
  394. currentOutput.close();
  395. currentOutput = null;
  396. }
  397. /** Generate a wildcard element */
  398. public void gen(WildcardElement wc) {
  399. print("Match wildcard");
  400. if ( wc.getLabel()!=null ) {
  401. _print(", label = " + wc.getLabel());
  402. }
  403. _println("");
  404. }
  405. /** Generate code for the given grammar element.
  406.  * @param blk The (...)* block to generate
  407.  */
  408. public void gen(ZeroOrMoreBlock blk) {
  409. println("Start ZERO-OR-MORE (...)+ block:");
  410. tabs++;
  411. genBlockPreamble(blk);
  412. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  413. if (!ok) {
  414. println("Warning: This zero-or-more block is non-deterministic");
  415. }
  416. genCommonBlock(blk);
  417. tabs--;
  418. println("End ZERO-OR-MORE block.");
  419. }
  420. protected void genAlt(Alternative alt) {
  421. for (
  422. AlternativeElement elem = alt.head;
  423. !(elem instanceof BlockEndElement);
  424. elem = elem.next
  425. )
  426. {
  427. elem.generate();
  428. }
  429. if (alt.getTreeSpecifier() != null) 
  430. {
  431. println("AST will be built as: " + alt.getTreeSpecifier().getText());
  432. }
  433. }
  434. /** Generate the header for a block, which may be a RuleBlock or a
  435.  * plain AlternativeBLock.  This generates any variable declarations,
  436.  * init-actions, and syntactic-predicate-testing variables.
  437.  * @blk The block for which the preamble is to be generated.
  438.  */
  439. protected void genBlockPreamble(AlternativeBlock blk) {
  440. // dump out init action
  441. if ( blk.initAction!=null ) {
  442. printAction("Init action: " + blk.initAction);
  443. }
  444. }
  445. /**Generate common code for a block of alternatives; return a postscript
  446.  * that needs to be generated at the end of the block.  Other routines
  447.  * may append else-clauses and such for error checking before the postfix
  448.  * is generated.
  449.  */
  450. public void genCommonBlock(AlternativeBlock blk) {
  451. boolean singleAlt = (blk.alternatives.size() == 1);
  452. println("Start of an alternative block.");
  453. tabs++;
  454. println("The lookahead set for this block is:");
  455. tabs++;
  456. genLookaheadSetForBlock(blk);
  457. tabs--;
  458. if (singleAlt) {
  459. println("This block has a single alternative");
  460. if (blk.getAlternativeAt(0).synPred != null)
  461. {
  462. // Generate a warning if there is one alt and it has a synPred
  463. println("Warning: you specified a syntactic predicate for this alternative,");
  464. println("and it is the only alternative of a block and will be ignored.");
  465. }
  466. }
  467. else {
  468. println("This block has multiple alternatives:");
  469. tabs++;
  470. }
  471. for (int i=0; i<blk.alternatives.size(); i++) {
  472. Alternative alt = blk.getAlternativeAt(i);
  473. AlternativeElement elem = alt.head;
  474. // Print lookahead set for alternate
  475. println("");
  476. if (i != 0) {
  477. print("Otherwise, ");
  478. } else {
  479. print("");
  480. }
  481. _println("Alternate(" + (i+1) + ") will be taken IF:");
  482. println("The lookahead set: ");
  483. tabs++;
  484. genLookaheadSetForAlt(alt);
  485. tabs--;
  486. if ( alt.semPred != null || alt.synPred != null ) {
  487. print("is matched, AND ");
  488. } else {
  489. println("is matched.");
  490. }
  491. // Dump semantic predicates
  492. if ( alt.semPred != null ) {
  493. _println("the semantic predicate:");
  494. tabs++;
  495. println(alt.semPred);
  496. if ( alt.synPred != null ) {
  497. print("is true, AND ");
  498. } else {
  499. println("is true.");
  500. }
  501. }
  502. // Dump syntactic predicate
  503. if ( alt.synPred != null ) {
  504. _println("the syntactic predicate:");
  505. tabs++;
  506. genSynPred( alt.synPred );
  507. tabs--;
  508. println("is matched.");
  509. }
  510. // Dump the alternative
  511. genAlt(alt);
  512. }
  513. println("");
  514. println("OTHERWISE, a NoViableAlt exception will be thrown");
  515. println("");
  516. if (!singleAlt) {
  517. tabs--;
  518. println("End of alternatives");
  519. }
  520. tabs--;
  521. println("End of alternative block.");
  522. }
  523. /** Generate a textual representation of the follow set
  524.  * for a block.
  525.  * @param blk  The rule block of interest
  526.  */
  527. public void genFollowSetForRuleBlock(RuleBlock blk)
  528. {
  529. Lookahead follow = grammar.theLLkAnalyzer.FOLLOW(1, blk.endNode);
  530. printSet(grammar.maxk, 1, follow);
  531. }
  532. /** Generate a header that is common to all TXT files */
  533. protected void genHeader() 
  534. {
  535. println("ANTLR-generated file resulting from grammar " + tool.grammarFile);
  536. println("Diagnostic output");
  537. println("");
  538. println("Terence Parr, MageLang Institute");
  539. println("with John Lilley, Empathy Software");
  540. println("ANTLR Version "+Tool.version+"; 1996,1997");
  541. println("");
  542. println("*** Header Action.");
  543. println("This action will appear at the top of all generated files.");
  544. tabs++;
  545. printAction((String)behavior.headerActions.get(""));
  546. tabs--;
  547. println("*** End of Header Action");
  548. println("");
  549. }
  550. /**Generate the lookahead set for an alternate. */
  551. protected void genLookaheadSetForAlt(Alternative alt) {
  552. if ( doingLexRules && alt.cache[1].containsEpsilon() ) {
  553. println("MATCHES ALL");
  554. return;
  555. }
  556. int depth = alt.lookaheadDepth;
  557. if ( depth == GrammarAnalyzer.NONDETERMINISTIC ) {
  558. // if the decision is nondeterministic, do the best we can: LL(k)
  559. // any predicates that are around will be generated later.
  560. depth = grammar.maxk;
  561. }
  562. for (int i = 1; i <= depth; i++)
  563. {
  564. Lookahead lookahead = alt.cache[i];
  565. printSet(depth, i, lookahead);
  566. }
  567. }
  568. /** Generate a textual representation of the lookahead set
  569.  * for a block.
  570.  * @param blk  The block of interest
  571.  */
  572. public void genLookaheadSetForBlock(AlternativeBlock blk)
  573. {
  574. // Find the maximal lookahead depth over all alternatives
  575. int depth = 0;
  576. for (int i=0; i<blk.alternatives.size(); i++) {
  577. Alternative alt = blk.getAlternativeAt(i);
  578. if (alt.lookaheadDepth == GrammarAnalyzer.NONDETERMINISTIC) {
  579. depth = grammar.maxk;
  580. break;
  581. else if (depth < alt.lookaheadDepth) {
  582. depth = alt.lookaheadDepth;
  583. }
  584. }
  585. for (int i = 1; i <= depth; i++)
  586. {
  587. Lookahead lookahead = grammar.theLLkAnalyzer.look(i, blk);
  588. printSet(depth, i, lookahead);
  589. }
  590. }
  591. /** Generate the nextToken rule.
  592.  * nextToken is a synthetic lexer rule that is the implicit OR of all
  593.  * user-defined lexer rules.
  594.  */
  595. public void genNextToken() {
  596. println("");
  597. println("*** Lexer nextToken rule:");
  598. println("The lexer nextToken rule is synthesized from all of the user-defined");
  599. println("lexer rules.  It logically consists of one big alternative block with");
  600. println("each user-defined rule being an alternative.");
  601. println("");
  602. // Create the synthesized rule block for nextToken consisting
  603. // of an alternate block containing all the user-defined lexer rules.
  604. RuleBlock blk = MakeGrammar.createNextTokenRule(grammar, grammar.rules, "nextToken");
  605. // Define the nextToken rule symbol
  606. RuleSymbol nextTokenRs = new RuleSymbol("mnextToken");
  607. nextTokenRs.setDefined();
  608. nextTokenRs.setBlock(blk);
  609. nextTokenRs.access = "private";
  610. grammar.define(nextTokenRs);
  611. // Analyze the synthesized block
  612. if (!grammar.theLLkAnalyzer.deterministic(blk))
  613. {
  614. println("The grammar analyzer has determined that the synthesized");
  615. println("nextToken rule is non-deterministic (i.e., it has ambiguities)");
  616. println("This means that there is some overlap of the character");
  617. println("lookahead for two or more of your lexer rules.");
  618. }
  619. genCommonBlock(blk);
  620. println("*** End of nextToken lexer rule.");
  621. }
  622. /** Generate code for a named rule block
  623.  * @param s The RuleSymbol describing the rule to generate
  624. */
  625. public void genRule(RuleSymbol s) {
  626. println("");
  627. String ruleType = (doingLexRules ? "Lexer" : "Parser");
  628. println("*** " + ruleType + " Rule: " + s.getId());
  629. if (!s.isDefined() ) {
  630. println("This rule is undefined.");
  631. println("This means that the rule was referenced somewhere in the grammar,");
  632. println("but a definition for the rule was not encountered.");
  633. println("It is also possible that syntax errors during the parse of");
  634. println("your grammar file prevented correct processing of the rule.");
  635. println("*** End " + ruleType + " Rule: " + s.getId());
  636. return;
  637. }
  638. tabs++;
  639. if (s.access.length() != 0) {
  640. println("Access: " + s.access);
  641. }
  642. // Get rule return type and arguments
  643. RuleBlock rblk = s.getBlock();
  644. // Gen method return value(s)
  645. if (rblk.returnAction != null) {
  646. println("Return value(s): " + rblk.returnAction);
  647. if ( doingLexRules ) {
  648. println("Error: you specified return value(s) for a lexical rule.");
  649. println("tLexical rules have an implicit return type of 'int'.");
  650. }
  651. } else {
  652. if ( doingLexRules ) {
  653. println("Return value: lexical rule returns an implicit token type");
  654. } else {
  655. println("Return value: none");
  656. }
  657. }
  658. // Gen arguments
  659. if (rblk.argAction != null) 
  660. {
  661. println("Arguments: " + rblk.argAction);
  662. }
  663. // Dump any init-action
  664. genBlockPreamble(rblk);
  665. // Analyze the rule
  666. boolean ok = grammar.theLLkAnalyzer.deterministic(rblk);
  667. if (!ok) {
  668. println("Error: This rule is non-deterministic");
  669. }
  670. // Dump the alternates of the rule
  671. genCommonBlock(rblk);
  672. // Search for an unlabeled exception specification attached to the rule
  673. ExceptionSpec unlabeledUserSpec = rblk.findExceptionSpec("");
  674. // Generate user-defined or default catch phrases
  675. if (unlabeledUserSpec != null) {
  676. println("You specified error-handler(s) for this rule:");
  677. tabs++;
  678. for (int i = 0; i < unlabeledUserSpec.handlers.size(); i++)
  679. {
  680. if (i != 0) {
  681. println("");
  682. }
  683. ExceptionHandler handler = (ExceptionHandler)unlabeledUserSpec.handlers.elementAt(i);
  684. println("Error-handler(" + (i+1) + ") catches [" + handler.exceptionTypeAndName.getText() + "] and executes:");
  685. printAction(handler.action);
  686. }
  687. tabs--;
  688. println("End error-handlers.");
  689. }
  690. else if (!doingLexRules) {
  691. println("Default error-handling will be generated, which catches all");
  692. println("parser exceptions and consumes tokens until the follow-set is seen.");
  693. }
  694. // Dump the follow set
  695. // Doesn't seem to work for lexical rules...
  696. if (!doingLexRules) {
  697. println("The follow set for this rule is:");
  698. tabs++;
  699. genFollowSetForRuleBlock(rblk);
  700. tabs--;
  701. }
  702. tabs--;
  703. println("*** End " + ruleType + " Rule: " + s.getId());
  704. }
  705. /** Generate the syntactic predicate.  This basically generates
  706.  * the alternative block, buts tracks if we are inside a synPred
  707.  * @param blk  The syntactic predicate block
  708.  */
  709. protected void genSynPred(SynPredBlock blk) {
  710. syntacticPredLevel++;
  711. gen((AlternativeBlock)blk);
  712. syntacticPredLevel--;
  713. }
  714. /** Generate the token types TXT file */
  715. protected void genTokenTypes(TokenManager tm) throws IOException {
  716. // Open the token output TXT file and set the currentOutput stream
  717. System.out.println("Generating " + tm.getName() + TokenTypesFileSuffix+TokenTypesFileExt);
  718. currentOutput = antlr.Tool.openOutputFile(tm.getName() + TokenTypesFileSuffix+TokenTypesFileExt);
  719. //SAS: changed for proper text file io
  720. tabs = 0;
  721. // Generate the header common to all diagnostic files
  722. genHeader();
  723. // Generate a string for each token.  This creates a static
  724. // array of Strings indexed by token type.
  725. println("");
  726. println("*** Tokens used by the parser");
  727. println("This is a list of the token numeric values and the corresponding");
  728. println("token identifiers.  Some tokens are literals, and because of that");
  729. println("they have no identifiers.  Literals are double-quoted.");
  730. tabs++;
  731. // Enumerate all the valid token types
  732. Vector v = tm.getVocabulary();
  733. for (int i = Token.MIN_USER_TYPE; i < v.size(); i++) {
  734. String s = (String)v.elementAt(i);
  735. if (s != null) {
  736. println(s + " = " + i);
  737. }
  738. }
  739. // Close the interface
  740. tabs--;
  741. println("*** End of tokens used by the parser");
  742. // Close the tokens output file
  743. currentOutput.close();
  744. currentOutput = null;
  745. }
  746. /** Get a string for an expression to generate creation of an AST subtree.
  747.   * @param v A Vector of String, where each element is an expression in the target language yielding an AST node.
  748.   */
  749. public String getASTCreateString(Vector v) {
  750. return "***Create an AST from a vector here***"+System.getProperty("line.separator");
  751. }
  752. /** Get a string for an expression to generate creating of an AST node
  753.   * @param str The arguments to the AST constructor
  754.   */
  755. public String getASTCreateString(GrammarAtom atom, String str) {
  756. return "[" + str + "]";
  757. }
  758. /** Map an identifier to it's corresponding tree-node variable.
  759.   * This is context-sensitive, depending on the rule and alternative
  760.   * being generated
  761.   * @param id The identifier name to map
  762.   * @param forInput true if the input tree node variable is to be returned, otherwise the output variable is returned.
  763.   */
  764. public String mapTreeId(String id, ActionTransInfo tInfo) {
  765. return id;
  766. }
  767. /** Format a lookahead or follow set.
  768.  * @param depth The depth of the entire lookahead/follow
  769.  * @param k The lookahead level to print
  770.  * @param lookahead  The lookahead/follow set to print
  771.  */
  772. public void printSet(int depth, int k, Lookahead lookahead) {
  773. int numCols = 5;
  774. int[] elems = lookahead.fset.toArray();
  775. if (depth != 1) {
  776. print("k==" + k + ": {");
  777. } else {
  778. print("{ ");
  779. }
  780. if (elems.length > numCols) {
  781. _println("");
  782. tabs++;
  783. print("");
  784. }
  785. int column = 0;
  786. for (int i = 0; i < elems.length; i++)
  787. {
  788. column++;
  789. if (column > numCols) {
  790. _println("");
  791. print("");
  792. column = 0;
  793. }
  794. if (doingLexRules) {
  795. _print(charFormatter.literalChar(elems[i]));
  796. } else {
  797. _print((String)grammar.tokenManager.getVocabulary().elementAt(elems[i]));
  798. }
  799. if (i != elems.length-1) {
  800. _print(", ");
  801. }
  802. }
  803. if (elems.length > numCols) {
  804. _println("");
  805. tabs--;
  806. print("");
  807. }
  808. _println(" }");
  809. }
  810. }