PageRenderTime 56ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 1ms

/Dependencies/boo/lib/antlr-2.7.5/antlr/CSharpCodeGenerator.java

https://github.com/w4x/boolangstudio
Java | 4095 lines | 2862 code | 382 blank | 851 comment | 718 complexity | 03034d4690f63bfcd828da84b77dde68 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. package antlr;
  2. /* ANTLR Translator Generator
  3. * Project led by Terence Parr at http://www.jGuru.com
  4. * Software rights: http://www.antlr.org/license.html
  5. *
  6. * $Id:$
  7. */
  8. //
  9. // ANTLR C# Code Generator by Micheal Jordan
  10. // Kunle Odutola : kunle UNDERSCORE odutola AT hotmail DOT com
  11. // Anthony Oguntimehin
  12. //
  13. // With many thanks to Eric V. Smith from the ANTLR list.
  14. //
  15. // HISTORY:
  16. //
  17. // 17-May-2002 kunle Fixed bug in OctalToUnicode() - was processing non-Octal escape sequences
  18. // Also added namespace support based on Cpp version.
  19. // 07-Jun-2002 kunle Added Scott Ellis's _saveIndex creation optimizations
  20. // 09-Sep-2002 richardN Richard Ney's bug-fix for literals table construction.
  21. // [ Hashtable ctor needed instance of hash code provider not it's class name. ]
  22. // 17-Sep-2002 kunle & Added all Token ID definitions as data member of every Lexer/Parser/TreeParser
  23. // AOg [ A by-product of problem-solving phase of the hetero-AST changes below
  24. // but, it breaks nothing and restores "normal" ANTLR codegen behaviour. ]
  25. // 19-Oct-2002 kunle & Completed the work required to support heterogenous ASTs (many changes)
  26. // AOg &
  27. // michealj
  28. // 14-Nov-2002 michealj Added "initializeASTFactory()" to support flexible ASTFactory initialization.
  29. // [ Thanks to Ric Klaren - for suggesting it and implementing it for Cpp. ]
  30. // 18-Nov-2002 kunle Added fix to make xx_tokenSet_xx names CLS compliant.
  31. // 01-Dec-2002 richardN Patch to reduce "unreachable code" warnings
  32. // 01-Dec-2002 richardN Fix to generate correct TreeParser token-type classnames.
  33. // 12-Jan-2003 kunle & Generated Lexers, Parsers and TreeParsers now support ANTLR's tracing option.
  34. // michealj
  35. // 12-Jan-2003 kunle Fixed issue where initializeASTFactory() was generated when "buildAST=false"
  36. // 14-Jan-2003 AOg initializeASTFactory(AST factory) method was modifying the Parser's "astFactory"
  37. // member rather than it's own "factory" parameter. Fixed.
  38. // 18-Jan-2003 kunle & Fixed reported issues with ASTFactory create() calls for hetero ASTs
  39. // michealj - code generated for LEXER token with hetero-AST option specified does not compile
  40. // - code generated for imaginary tokens with hetero-AST option specified uses
  41. // default AST type
  42. // - code generated for per-TokenRef hetero-AST option specified does not compile
  43. // 18-Jan-2003 kunle initializeASTFactory(AST) method is now a static public member
  44. // 18-May-2003 kunle Changes to address outstanding reported issues::
  45. // - Fixed reported issues with support for case-sensitive literals
  46. // - antlr.SemanticException now imported for all Lexers.
  47. // [ This exception is thrown on predicate failure. ]
  48. // 12-Jan-2004 kunle Added fix for reported issue with un-compileable generated lexers
  49. //
  50. //
  51. import java.util.Enumeration;
  52. import java.util.Hashtable;
  53. import java.util.StringTokenizer;
  54. import antlr.collections.impl.BitSet;
  55. import antlr.collections.impl.Vector;
  56. import java.io.PrintWriter; //SAS: changed for proper text file io
  57. import java.io.IOException;
  58. import java.io.FileWriter;
  59. /** Generates MyParser.cs, MyLexer.cs and MyParserTokenTypes.cs */
  60. public class CSharpCodeGenerator extends CodeGenerator {
  61. // non-zero if inside syntactic predicate generation
  62. protected int syntacticPredLevel = 0;
  63. // Are we generating ASTs (for parsers and tree parsers) right now?
  64. protected boolean genAST = false;
  65. // Are we saving the text consumed (for lexers) right now?
  66. protected boolean saveText = false;
  67. // Grammar parameters set up to handle different grammar classes.
  68. // These are used to get instanceof tests out of code generation
  69. boolean usingCustomAST = false;
  70. String labeledElementType;
  71. String labeledElementASTType;
  72. String labeledElementInit;
  73. String commonExtraArgs;
  74. String commonExtraParams;
  75. String commonLocalVars;
  76. String lt1Value;
  77. String exceptionThrown;
  78. String throwNoViable;
  79. // Tracks the rule being generated. Used for mapTreeId
  80. RuleBlock currentRule;
  81. // Tracks the rule or labeled subrule being generated. Used for AST generation.
  82. String currentASTResult;
  83. /** Mapping between the ids used in the current alt, and the
  84. * names of variables used to represent their AST values.
  85. */
  86. Hashtable treeVariableMap = new Hashtable();
  87. /** Used to keep track of which AST variables have been defined in a rule
  88. * (except for the #rule_name and #rule_name_in var's
  89. */
  90. Hashtable declaredASTVariables = new Hashtable();
  91. /* Count of unnamed generated variables */
  92. int astVarNumber = 1;
  93. /** Special value used to mark duplicate in treeVariableMap */
  94. protected static final String NONUNIQUE = new String();
  95. public static final int caseSizeThreshold = 127; // ascii is max
  96. private Vector semPreds;
  97. // Used to keep track of which (heterogeneous AST types are used)
  98. // which need to be set in the ASTFactory of the generated parser
  99. private java.util.Vector astTypes;
  100. private static CSharpNameSpace nameSpace = null;
  101. // _saveIndex creation optimization -- don't create it unless we need to use it
  102. int saveIndexCreateLevel;
  103. int blockNestingLevel;
  104. /** Create a CSharp code-generator using the given Grammar.
  105. * The caller must still call setTool, setBehavior, and setAnalyzer
  106. * before generating code.
  107. */
  108. public CSharpCodeGenerator() {
  109. super();
  110. charFormatter = new CSharpCharFormatter();
  111. }
  112. /** Adds a semantic predicate string to the sem pred vector
  113. These strings will be used to build an array of sem pred names
  114. when building a debugging parser. This method should only be
  115. called when the debug option is specified
  116. */
  117. protected int addSemPred(String predicate) {
  118. semPreds.appendElement(predicate);
  119. return semPreds.size()-1;
  120. }
  121. public void exitIfError()
  122. {
  123. if (antlrTool.hasError())
  124. {
  125. antlrTool.fatalError("Exiting due to errors.");
  126. }
  127. }
  128. /**Generate the parser, lexer, treeparser, and token types in CSharp */
  129. public void gen() {
  130. // Do the code generation
  131. try {
  132. // Loop over all grammars
  133. Enumeration grammarIter = behavior.grammars.elements();
  134. while (grammarIter.hasMoreElements()) {
  135. Grammar g = (Grammar)grammarIter.nextElement();
  136. // Connect all the components to each other
  137. g.setGrammarAnalyzer(analyzer);
  138. g.setCodeGenerator(this);
  139. analyzer.setGrammar(g);
  140. // To get right overloading behavior across heterogeneous grammars
  141. setupGrammarParameters(g);
  142. g.generate();
  143. exitIfError();
  144. }
  145. // Loop over all token managers (some of which are lexers)
  146. Enumeration tmIter = behavior.tokenManagers.elements();
  147. while (tmIter.hasMoreElements()) {
  148. TokenManager tm = (TokenManager)tmIter.nextElement();
  149. if (!tm.isReadOnly()) {
  150. // Write the token manager tokens as CSharp
  151. // this must appear before genTokenInterchange so that
  152. // labels are set on string literals
  153. genTokenTypes(tm);
  154. // Write the token manager tokens as plain text
  155. genTokenInterchange(tm);
  156. }
  157. exitIfError();
  158. }
  159. }
  160. catch (IOException e) {
  161. antlrTool.reportException(e, null);
  162. }
  163. }
  164. /** Generate code for the given grammar element.
  165. * @param blk The {...} action to generate
  166. */
  167. public void gen(ActionElement action) {
  168. if ( DEBUG_CODE_GENERATOR ) System.out.println("genAction("+action+")");
  169. if ( action.isSemPred ) {
  170. genSemPred(action.actionText, action.line);
  171. }
  172. else {
  173. if ( grammar.hasSyntacticPredicate ) {
  174. println("if (0==inputState.guessing)");
  175. println("{");
  176. tabs++;
  177. }
  178. ActionTransInfo tInfo = new ActionTransInfo();
  179. String actionStr = processActionForSpecialSymbols(action.actionText,
  180. action.getLine(),
  181. currentRule, tInfo);
  182. if ( tInfo.refRuleRoot!=null ) {
  183. // Somebody referenced "#rule", make sure translated var is valid
  184. // assignment to #rule is left as a ref also, meaning that assignments
  185. // with no other refs like "#rule = foo();" still forces this code to be
  186. // generated (unnecessarily).
  187. println(tInfo.refRuleRoot + " = ("+labeledElementASTType+")currentAST.root;");
  188. }
  189. // dump the translated action
  190. printAction(actionStr);
  191. if ( tInfo.assignToRoot ) {
  192. // Somebody did a "#rule=", reset internal currentAST.root
  193. println("currentAST.root = "+tInfo.refRuleRoot+";");
  194. // reset the child pointer too to be last sibling in sibling list
  195. println("if ( (null != "+tInfo.refRuleRoot+") && (null != "+tInfo.refRuleRoot+".getFirstChild()) )");
  196. tabs++;
  197. println("currentAST.child = "+tInfo.refRuleRoot+".getFirstChild();");
  198. tabs--;
  199. println("else");
  200. tabs++;
  201. println("currentAST.child = "+tInfo.refRuleRoot+";");
  202. tabs--;
  203. println("currentAST.advanceChildToEnd();");
  204. }
  205. if ( grammar.hasSyntacticPredicate ) {
  206. tabs--;
  207. println("}");
  208. }
  209. }
  210. }
  211. /** Generate code for the given grammar element.
  212. * @param blk The "x|y|z|..." block to generate
  213. */
  214. public void gen(AlternativeBlock blk) {
  215. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen("+blk+")");
  216. println("{");
  217. tabs++;
  218. genBlockPreamble(blk);
  219. genBlockInitAction(blk);
  220. // Tell AST generation to build subrule result
  221. String saveCurrentASTResult = currentASTResult;
  222. if (blk.getLabel() != null) {
  223. currentASTResult = blk.getLabel();
  224. }
  225. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  226. CSharpBlockFinishingInfo howToFinish = genCommonBlock(blk, true);
  227. genBlockFinish(howToFinish, throwNoViable);
  228. tabs--;
  229. println("}");
  230. // Restore previous AST generation
  231. currentASTResult = saveCurrentASTResult;
  232. }
  233. /** Generate code for the given grammar element.
  234. * @param blk The block-end element to generate. Block-end
  235. * elements are synthesized by the grammar parser to represent
  236. * the end of a block.
  237. */
  238. public void gen(BlockEndElement end) {
  239. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRuleEnd("+end+")");
  240. }
  241. /** Generate code for the given grammar element.
  242. * @param blk The character literal reference to generate
  243. */
  244. public void gen(CharLiteralElement atom) {
  245. if ( DEBUG_CODE_GENERATOR ) System.out.println("genChar("+atom+")");
  246. if ( atom.getLabel()!=null ) {
  247. println(atom.getLabel() + " = " + lt1Value + ";");
  248. }
  249. boolean oldsaveText = saveText;
  250. saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
  251. genMatch(atom);
  252. saveText = oldsaveText;
  253. }
  254. /** Generate code for the given grammar element.
  255. * @param blk The character-range reference to generate
  256. */
  257. public void gen(CharRangeElement r) {
  258. if ( r.getLabel()!=null && syntacticPredLevel == 0) {
  259. println(r.getLabel() + " = " + lt1Value + ";");
  260. }
  261. boolean flag = ( grammar instanceof LexerGrammar &&
  262. (!saveText || (r.getAutoGenType() == GrammarElement.AUTO_GEN_BANG)) );
  263. if (flag)
  264. println("_saveIndex = text.Length;");
  265. println("matchRange("+OctalToUnicode(r.beginText)+","+OctalToUnicode(r.endText)+");");
  266. if (flag)
  267. println("text.Length = _saveIndex;");
  268. }
  269. /** Generate the lexer CSharp file */
  270. public void gen(LexerGrammar g) throws IOException {
  271. // If debugging, create a new sempred vector for this grammar
  272. if (g.debuggingOutput)
  273. semPreds = new Vector();
  274. setGrammar(g);
  275. if (!(grammar instanceof LexerGrammar)) {
  276. antlrTool.panic("Internal error generating lexer");
  277. }
  278. genBody(g);
  279. }
  280. /** Generate code for the given grammar element.
  281. * @param blk The (...)+ block to generate
  282. */
  283. public void gen(OneOrMoreBlock blk) {
  284. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen+("+blk+")");
  285. String label;
  286. String cnt;
  287. println("{ // ( ... )+");
  288. tabs++;
  289. blockNestingLevel++;
  290. genBlockPreamble(blk);
  291. if ( blk.getLabel() != null ) {
  292. cnt = "_cnt_"+blk.getLabel();
  293. }
  294. else {
  295. cnt = "_cnt" + blk.ID;
  296. }
  297. println("int "+cnt+"=0;");
  298. if ( blk.getLabel() != null ) {
  299. label = blk.getLabel();
  300. }
  301. else {
  302. label = "_loop" + blk.ID;
  303. }
  304. println("for (;;)");
  305. println("{");
  306. tabs++;
  307. blockNestingLevel++;
  308. // generate the init action for ()+ ()* inside the loop
  309. // this allows us to do usefull EOF checking...
  310. genBlockInitAction(blk);
  311. // Tell AST generation to build subrule result
  312. String saveCurrentASTResult = currentASTResult;
  313. if (blk.getLabel() != null) {
  314. currentASTResult = blk.getLabel();
  315. }
  316. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  317. // generate exit test if greedy set to false
  318. // and an alt is ambiguous with exit branch
  319. // or when lookahead derived purely from end-of-file
  320. // Lookahead analysis stops when end-of-file is hit,
  321. // returning set {epsilon}. Since {epsilon} is not
  322. // ambig with any real tokens, no error is reported
  323. // by deterministic() routines and we have to check
  324. // for the case where the lookahead depth didn't get
  325. // set to NONDETERMINISTIC (this only happens when the
  326. // FOLLOW contains real atoms + epsilon).
  327. boolean generateNonGreedyExitPath = false;
  328. int nonGreedyExitDepth = grammar.maxk;
  329. if ( !blk.greedy &&
  330. blk.exitLookaheadDepth<=grammar.maxk &&
  331. blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  332. {
  333. generateNonGreedyExitPath = true;
  334. nonGreedyExitDepth = blk.exitLookaheadDepth;
  335. }
  336. else if ( !blk.greedy &&
  337. blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  338. {
  339. generateNonGreedyExitPath = true;
  340. }
  341. // generate exit test if greedy set to false
  342. // and an alt is ambiguous with exit branch
  343. if ( generateNonGreedyExitPath ) {
  344. if ( DEBUG_CODE_GENERATOR ) {
  345. System.out.println("nongreedy (...)+ loop; exit depth is "+
  346. blk.exitLookaheadDepth);
  347. }
  348. String predictExit =
  349. getLookaheadTestExpression(blk.exitCache,
  350. nonGreedyExitDepth);
  351. println("// nongreedy exit test");
  352. println("if (("+cnt+" >= 1) && "+predictExit+") goto "+label+"_breakloop;");
  353. }
  354. CSharpBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  355. genBlockFinish(
  356. howToFinish,
  357. "if ("+cnt+" >= 1) { goto "+label+"_breakloop; } else { " + throwNoViable + "; }"
  358. );
  359. println(cnt+"++;");
  360. tabs--;
  361. if (blockNestingLevel-- == saveIndexCreateLevel)
  362. saveIndexCreateLevel = 0;
  363. println("}");
  364. _print(label + "_breakloop:");
  365. println(";");
  366. tabs--;
  367. if (blockNestingLevel-- == saveIndexCreateLevel)
  368. saveIndexCreateLevel = 0;
  369. println("} // ( ... )+");
  370. // Restore previous AST generation
  371. currentASTResult = saveCurrentASTResult;
  372. }
  373. /** Generate the parser CSharp file */
  374. public void gen(ParserGrammar g) throws IOException {
  375. // if debugging, set up a new vector to keep track of sempred
  376. // strings for this grammar
  377. if (g.debuggingOutput)
  378. semPreds = new Vector();
  379. setGrammar(g);
  380. if (!(grammar instanceof ParserGrammar)) {
  381. antlrTool.panic("Internal error generating parser");
  382. }
  383. genBody(g);
  384. }
  385. /** Generate code for the given grammar element.
  386. * @param blk The rule-reference to generate
  387. */
  388. public void gen(RuleRefElement rr)
  389. {
  390. if ( DEBUG_CODE_GENERATOR ) System.out.println("genRR("+rr+")");
  391. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(rr.targetRule);
  392. if (rs == null || !rs.isDefined())
  393. {
  394. // Is this redundant???
  395. antlrTool.error("Rule '" + rr.targetRule + "' is not defined", grammar.getFilename(), rr.getLine(), rr.getColumn());
  396. return;
  397. }
  398. if (!(rs instanceof RuleSymbol))
  399. {
  400. // Is this redundant???
  401. antlrTool.error("'" + rr.targetRule + "' does not name a grammar rule", grammar.getFilename(), rr.getLine(), rr.getColumn());
  402. return;
  403. }
  404. genErrorTryForElement(rr);
  405. // AST value for labeled rule refs in tree walker.
  406. // This is not AST construction; it is just the input tree node value.
  407. if ( grammar instanceof TreeWalkerGrammar &&
  408. rr.getLabel() != null &&
  409. syntacticPredLevel == 0 )
  410. {
  411. println(rr.getLabel() + " = _t==ASTNULL ? null : "+lt1Value+";");
  412. }
  413. // if in lexer and ! on rule ref or alt or rule, save buffer index to kill later
  414. if (grammar instanceof LexerGrammar && (!saveText || rr.getAutoGenType() == GrammarElement.AUTO_GEN_BANG))
  415. {
  416. declareSaveIndexVariableIfNeeded();
  417. println("_saveIndex = text.Length;");
  418. }
  419. // Process return value assignment if any
  420. printTabs();
  421. if (rr.idAssign != null)
  422. {
  423. // Warn if the rule has no return type
  424. if (rs.block.returnAction == null)
  425. {
  426. antlrTool.warning("Rule '" + rr.targetRule + "' has no return type", grammar.getFilename(), rr.getLine(), rr.getColumn());
  427. }
  428. _print(rr.idAssign + "=");
  429. } else {
  430. // Warn about return value if any, but not inside syntactic predicate
  431. if ( !(grammar instanceof LexerGrammar) && syntacticPredLevel == 0 && rs.block.returnAction != null)
  432. {
  433. antlrTool.warning("Rule '" + rr.targetRule + "' returns a value", grammar.getFilename(), rr.getLine(), rr.getColumn());
  434. }
  435. }
  436. // Call the rule
  437. GenRuleInvocation(rr);
  438. // if in lexer and ! on element or alt or rule, save buffer index to kill later
  439. if ( grammar instanceof LexerGrammar && (!saveText||rr.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  440. declareSaveIndexVariableIfNeeded();
  441. println("text.Length = _saveIndex;");
  442. }
  443. // if not in a syntactic predicate
  444. if (syntacticPredLevel == 0)
  445. {
  446. boolean doNoGuessTest = (
  447. grammar.hasSyntacticPredicate &&
  448. (
  449. grammar.buildAST && rr.getLabel() != null ||
  450. (genAST && rr.getAutoGenType() == GrammarElement.AUTO_GEN_NONE)
  451. )
  452. );
  453. if (doNoGuessTest) {
  454. println("if (0 == inputState.guessing)");
  455. println("{");
  456. tabs++;
  457. }
  458. if (grammar.buildAST && rr.getLabel() != null)
  459. {
  460. // always gen variable for rule return on labeled rules
  461. println(rr.getLabel() + "_AST = ("+labeledElementASTType+")returnAST;");
  462. }
  463. if (genAST)
  464. {
  465. switch (rr.getAutoGenType())
  466. {
  467. case GrammarElement.AUTO_GEN_NONE:
  468. if( usingCustomAST )
  469. println("astFactory.addASTChild(currentAST, (AST)returnAST);");
  470. else
  471. println("astFactory.addASTChild(currentAST, returnAST);");
  472. break;
  473. case GrammarElement.AUTO_GEN_CARET:
  474. antlrTool.error("Internal: encountered ^ after rule reference");
  475. break;
  476. default:
  477. break;
  478. }
  479. }
  480. // if a lexer and labeled, Token label defined at rule level, just set it here
  481. if ( grammar instanceof LexerGrammar && rr.getLabel() != null )
  482. {
  483. println(rr.getLabel()+" = returnToken_;");
  484. }
  485. if (doNoGuessTest)
  486. {
  487. tabs--;
  488. println("}");
  489. }
  490. }
  491. genErrorCatchForElement(rr);
  492. }
  493. /** Generate code for the given grammar element.
  494. * @param blk The string-literal reference to generate
  495. */
  496. public void gen(StringLiteralElement atom) {
  497. if ( DEBUG_CODE_GENERATOR ) System.out.println("genString("+atom+")");
  498. // Variable declarations for labeled elements
  499. if (atom.getLabel()!=null && syntacticPredLevel == 0) {
  500. println(atom.getLabel() + " = " + lt1Value + ";");
  501. }
  502. // AST
  503. genElementAST(atom);
  504. // is there a bang on the literal?
  505. boolean oldsaveText = saveText;
  506. saveText = saveText && atom.getAutoGenType()==GrammarElement.AUTO_GEN_NONE;
  507. // matching
  508. genMatch(atom);
  509. saveText = oldsaveText;
  510. // tack on tree cursor motion if doing a tree walker
  511. if (grammar instanceof TreeWalkerGrammar) {
  512. println("_t = _t.getNextSibling();");
  513. }
  514. }
  515. /** Generate code for the given grammar element.
  516. * @param blk The token-range reference to generate
  517. */
  518. public void gen(TokenRangeElement r) {
  519. genErrorTryForElement(r);
  520. if ( r.getLabel()!=null && syntacticPredLevel == 0) {
  521. println(r.getLabel() + " = " + lt1Value + ";");
  522. }
  523. // AST
  524. genElementAST(r);
  525. // match
  526. println("matchRange("+OctalToUnicode(r.beginText)+","+OctalToUnicode(r.endText)+");");
  527. genErrorCatchForElement(r);
  528. }
  529. /** Generate code for the given grammar element.
  530. * @param blk The token-reference to generate
  531. */
  532. public void gen(TokenRefElement atom) {
  533. if ( DEBUG_CODE_GENERATOR ) System.out.println("genTokenRef("+atom+")");
  534. if ( grammar instanceof LexerGrammar ) {
  535. antlrTool.panic("Token reference found in lexer");
  536. }
  537. genErrorTryForElement(atom);
  538. // Assign Token value to token label variable
  539. if ( atom.getLabel()!=null && syntacticPredLevel == 0) {
  540. println(atom.getLabel() + " = " + lt1Value + ";");
  541. }
  542. // AST
  543. genElementAST(atom);
  544. // matching
  545. genMatch(atom);
  546. genErrorCatchForElement(atom);
  547. // tack on tree cursor motion if doing a tree walker
  548. if (grammar instanceof TreeWalkerGrammar) {
  549. println("_t = _t.getNextSibling();");
  550. }
  551. }
  552. public void gen(TreeElement t) {
  553. // save AST cursor
  554. println("AST __t" + t.ID + " = _t;");
  555. // If there is a label on the root, then assign that to the variable
  556. if (t.root.getLabel() != null) {
  557. println(t.root.getLabel() + " = (ASTNULL == _t) ? null : ("+labeledElementASTType +")_t;");
  558. }
  559. // check for invalid modifiers ! and ^ on tree element roots
  560. if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_BANG ) {
  561. antlrTool.error("Suffixing a root node with '!' is not implemented",
  562. grammar.getFilename(), t.getLine(), t.getColumn());
  563. t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
  564. }
  565. if ( t.root.getAutoGenType() == GrammarElement.AUTO_GEN_CARET ) {
  566. antlrTool.warning("Suffixing a root node with '^' is redundant; already a root",
  567. grammar.getFilename(), t.getLine(), t.getColumn());
  568. t.root.setAutoGenType(GrammarElement.AUTO_GEN_NONE);
  569. }
  570. // Generate AST variables
  571. genElementAST(t.root);
  572. if (grammar.buildAST) {
  573. // Save the AST construction state
  574. println("ASTPair __currentAST" + t.ID + " = currentAST.copy();");
  575. // Make the next item added a child of the TreeElement root
  576. println("currentAST.root = currentAST.child;");
  577. println("currentAST.child = null;");
  578. }
  579. // match root
  580. if ( t.root instanceof WildcardElement ) {
  581. println("if (null == _t) throw new MismatchedTokenException();");
  582. }
  583. else {
  584. genMatch(t.root);
  585. }
  586. // move to list of children
  587. println("_t = _t.getFirstChild();");
  588. // walk list of children, generating code for each
  589. for (int i=0; i<t.getAlternatives().size(); i++) {
  590. Alternative a = t.getAlternativeAt(i);
  591. AlternativeElement e = a.head;
  592. while ( e != null ) {
  593. e.generate();
  594. e = e.next;
  595. }
  596. }
  597. if (grammar.buildAST) {
  598. // restore the AST construction state to that just after the
  599. // tree root was added
  600. println("ASTPair.PutInstance(currentAST);");
  601. println("currentAST = __currentAST" + t.ID + ";");
  602. }
  603. // restore AST cursor
  604. println("_t = __t" + t.ID + ";");
  605. // move cursor to sibling of tree just parsed
  606. println("_t = _t.getNextSibling();");
  607. }
  608. /** Generate the tree-parser CSharp file */
  609. public void gen(TreeWalkerGrammar g) throws IOException {
  610. // SAS: debugging stuff removed for now...
  611. setGrammar(g);
  612. if (!(grammar instanceof TreeWalkerGrammar)) {
  613. antlrTool.panic("Internal error generating tree-walker");
  614. }
  615. genBody(g);
  616. }
  617. /** Generate code for the given grammar element.
  618. * @param wc The wildcard element to generate
  619. */
  620. public void gen(WildcardElement wc) {
  621. // Variable assignment for labeled elements
  622. if (wc.getLabel()!=null && syntacticPredLevel == 0) {
  623. println(wc.getLabel() + " = " + lt1Value + ";");
  624. }
  625. // AST
  626. genElementAST(wc);
  627. // Match anything but EOF
  628. if (grammar instanceof TreeWalkerGrammar) {
  629. println("if (null == _t) throw new MismatchedTokenException();");
  630. }
  631. else if (grammar instanceof LexerGrammar) {
  632. if ( grammar instanceof LexerGrammar &&
  633. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  634. declareSaveIndexVariableIfNeeded();
  635. println("_saveIndex = text.Length;");
  636. }
  637. println("matchNot(EOF/*_CHAR*/);");
  638. if ( grammar instanceof LexerGrammar &&
  639. (!saveText||wc.getAutoGenType()==GrammarElement.AUTO_GEN_BANG) ) {
  640. declareSaveIndexVariableIfNeeded();
  641. println("text.Length = _saveIndex;"); // kill text atom put in buffer
  642. }
  643. }
  644. else {
  645. println("matchNot(" + getValueString(Token.EOF_TYPE) + ");");
  646. }
  647. // tack on tree cursor motion if doing a tree walker
  648. if (grammar instanceof TreeWalkerGrammar) {
  649. println("_t = _t.getNextSibling();");
  650. }
  651. }
  652. /** Generate code for the given grammar element.
  653. * @param blk The (...)* block to generate
  654. */
  655. public void gen(ZeroOrMoreBlock blk) {
  656. if ( DEBUG_CODE_GENERATOR ) System.out.println("gen*("+blk+")");
  657. println("{ // ( ... )*");
  658. tabs++;
  659. blockNestingLevel++;
  660. genBlockPreamble(blk);
  661. String label;
  662. if ( blk.getLabel() != null ) {
  663. label = blk.getLabel();
  664. }
  665. else {
  666. label = "_loop" + blk.ID;
  667. }
  668. println("for (;;)");
  669. println("{");
  670. tabs++;
  671. blockNestingLevel++;
  672. // generate the init action for ()+ ()* inside the loop
  673. // this allows us to do usefull EOF checking...
  674. genBlockInitAction(blk);
  675. // Tell AST generation to build subrule result
  676. String saveCurrentASTResult = currentASTResult;
  677. if (blk.getLabel() != null) {
  678. currentASTResult = blk.getLabel();
  679. }
  680. boolean ok = grammar.theLLkAnalyzer.deterministic(blk);
  681. // generate exit test if greedy set to false
  682. // and an alt is ambiguous with exit branch
  683. // or when lookahead derived purely from end-of-file
  684. // Lookahead analysis stops when end-of-file is hit,
  685. // returning set {epsilon}. Since {epsilon} is not
  686. // ambig with any real tokens, no error is reported
  687. // by deterministic() routines and we have to check
  688. // for the case where the lookahead depth didn't get
  689. // set to NONDETERMINISTIC (this only happens when the
  690. // FOLLOW contains real atoms + epsilon).
  691. boolean generateNonGreedyExitPath = false;
  692. int nonGreedyExitDepth = grammar.maxk;
  693. if ( !blk.greedy &&
  694. blk.exitLookaheadDepth<=grammar.maxk &&
  695. blk.exitCache[blk.exitLookaheadDepth].containsEpsilon() )
  696. {
  697. generateNonGreedyExitPath = true;
  698. nonGreedyExitDepth = blk.exitLookaheadDepth;
  699. }
  700. else if ( !blk.greedy &&
  701. blk.exitLookaheadDepth==LLkGrammarAnalyzer.NONDETERMINISTIC )
  702. {
  703. generateNonGreedyExitPath = true;
  704. }
  705. if ( generateNonGreedyExitPath ) {
  706. if ( DEBUG_CODE_GENERATOR ) {
  707. System.out.println("nongreedy (...)* loop; exit depth is "+
  708. blk.exitLookaheadDepth);
  709. }
  710. String predictExit =
  711. getLookaheadTestExpression(blk.exitCache,
  712. nonGreedyExitDepth);
  713. println("// nongreedy exit test");
  714. println("if ("+predictExit+") goto "+label+"_breakloop;");
  715. }
  716. CSharpBlockFinishingInfo howToFinish = genCommonBlock(blk, false);
  717. genBlockFinish(howToFinish, "goto " + label + "_breakloop;");
  718. tabs--;
  719. if (blockNestingLevel-- == saveIndexCreateLevel)
  720. saveIndexCreateLevel = 0;
  721. println("}");
  722. _print(label+"_breakloop:");
  723. println(";");
  724. tabs--;
  725. if (blockNestingLevel-- == saveIndexCreateLevel)
  726. saveIndexCreateLevel = 0;
  727. println("} // ( ... )*");
  728. // Restore previous AST generation
  729. currentASTResult = saveCurrentASTResult;
  730. }
  731. /** Generate an alternative.
  732. * @param alt The alternative to generate
  733. * @param blk The block to which the alternative belongs
  734. */
  735. protected void genAlt(Alternative alt, AlternativeBlock blk)
  736. {
  737. // Save the AST generation state, and set it to that of the alt
  738. boolean savegenAST = genAST;
  739. genAST = genAST && alt.getAutoGen();
  740. boolean oldsaveTest = saveText;
  741. saveText = saveText && alt.getAutoGen();
  742. // Reset the variable name map for the alternative
  743. Hashtable saveMap = treeVariableMap;
  744. treeVariableMap = new Hashtable();
  745. // Generate try block around the alt for error handling
  746. if (alt.exceptionSpec != null) {
  747. println("try // for error handling");
  748. println("{");
  749. tabs++;
  750. }
  751. AlternativeElement elem = alt.head;
  752. while ( !(elem instanceof BlockEndElement) ) {
  753. elem.generate(); // alt can begin with anything. Ask target to gen.
  754. elem = elem.next;
  755. }
  756. if ( genAST)
  757. {
  758. if (blk instanceof RuleBlock)
  759. {
  760. // Set the AST return value for the rule
  761. RuleBlock rblk = (RuleBlock)blk;
  762. if( usingCustomAST )
  763. {
  764. println(rblk.getRuleName() + "_AST = ("+labeledElementASTType+")currentAST.root;");
  765. }
  766. else
  767. {
  768. println(rblk.getRuleName() + "_AST = currentAST.root;");
  769. }
  770. }
  771. else if (blk.getLabel() != null) {
  772. // ### future: also set AST value for labeled subrules.
  773. // println(blk.getLabel() + "_AST = ("+labeledElementASTType+")currentAST.root;");
  774. antlrTool.warning("Labeled subrules not yet supported", grammar.getFilename(), blk.getLine(), blk.getColumn());
  775. }
  776. }
  777. if (alt.exceptionSpec != null)
  778. {
  779. // close try block
  780. tabs--;
  781. println("}");
  782. genErrorHandler(alt.exceptionSpec);
  783. }
  784. genAST = savegenAST;
  785. saveText = oldsaveTest;
  786. treeVariableMap = saveMap;
  787. }
  788. /** Generate all the bitsets to be used in the parser or lexer
  789. * Generate the raw bitset data like "long _tokenSet1_data[] = {...};"
  790. * and the BitSet object declarations like "BitSet _tokenSet1 = new BitSet(_tokenSet1_data);"
  791. * Note that most languages do not support object initialization inside a
  792. * class definition, so other code-generators may have to separate the
  793. * bitset declarations from the initializations (e.g., put the initializations
  794. * in the generated constructor instead).
  795. * @param bitsetList The list of bitsets to generate.
  796. * @param maxVocabulary Ensure that each generated bitset can contain at least this value.
  797. */
  798. protected void genBitsets( Vector bitsetList, int maxVocabulary ) {
  799. println("");
  800. for (int i = 0; i < bitsetList.size(); i++)
  801. {
  802. BitSet p = (BitSet)bitsetList.elementAt(i);
  803. // Ensure that generated BitSet is large enough for vocabulary
  804. p.growToInclude(maxVocabulary);
  805. genBitSet(p, i);
  806. }
  807. }
  808. /** Do something simple like:
  809. * private static final long[] mk_tokenSet_0() {
  810. * long[] data = { -2305839160922996736L, 63L, 16777216L, 0L, 0L, 0L };
  811. * return data;
  812. * }
  813. * public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
  814. *
  815. * Or, for large bitsets, optimize init so ranges are collapsed into loops.
  816. * This is most useful for lexers using unicode.
  817. */
  818. private void genBitSet(BitSet p, int id) {
  819. // initialization data
  820. println("private static long[] mk_" + getBitsetName(id) + "()");
  821. println("{");
  822. tabs++;
  823. int n = p.lengthInLongWords();
  824. if ( n<BITSET_OPTIMIZE_INIT_THRESHOLD ) {
  825. println("long[] data = { " + p.toStringOfWords() + "};");
  826. }
  827. else {
  828. // will init manually, allocate space then set values
  829. println("long[] data = new long["+n+"];");
  830. long[] elems = p.toPackedArray();
  831. for (int i = 0; i < elems.length;) {
  832. if ( (i+1)==elems.length || elems[i]!=elems[i+1] ) {
  833. // last number or no run of numbers, just dump assignment
  834. println("data["+i+"]="+elems[i]+"L;");
  835. i++;
  836. }
  837. else
  838. {
  839. // scan to find end of run
  840. int j;
  841. for (j = i + 1; j < elems.length && elems[j]==elems[i]; j++)
  842. {
  843. ;
  844. }
  845. // j-1 is last member of run
  846. println("for (int i = "+i+"; i<="+(j-1)+"; i++) { data[i]="+
  847. elems[i]+"L; }");
  848. i = j;
  849. }
  850. }
  851. }
  852. println("return data;");
  853. tabs--;
  854. println("}");
  855. // BitSet object
  856. println("public static readonly BitSet " + getBitsetName(id) + " = new BitSet(" +
  857. "mk_" + getBitsetName(id) + "()" + ");");
  858. }
  859. /** Given the index of a bitset in the bitset list, generate a unique name.
  860. * Specific code-generators may want to override this
  861. * if the language does not allow '_' or numerals in identifiers.
  862. * @param index The index of the bitset in the bitset list.
  863. */
  864. protected String getBitsetName(int index) {
  865. return "tokenSet_" + index + "_";
  866. }
  867. /** Generate the finish of a block, using a combination of the info
  868. * returned from genCommonBlock() and the action to perform when
  869. * no alts were taken
  870. * @param howToFinish The return of genCommonBlock()
  871. * @param noViableAction What to generate when no alt is taken
  872. */
  873. private void genBlockFinish(CSharpBlockFinishingInfo howToFinish, String noViableAction)
  874. {
  875. if (howToFinish.needAnErrorClause &&
  876. (howToFinish.generatedAnIf || howToFinish.generatedSwitch))
  877. {
  878. if ( howToFinish.generatedAnIf ) {
  879. println("else");
  880. println("{");
  881. }
  882. else {
  883. println("{");
  884. }
  885. tabs++;
  886. println(noViableAction);
  887. tabs--;
  888. println("}");
  889. }
  890. if ( howToFinish.postscript!=null ) {
  891. if (howToFinish.needAnErrorClause && howToFinish.generatedSwitch &&
  892. !howToFinish.generatedAnIf && noViableAction != null)
  893. {
  894. // Check to make sure that noViableAction is only a throw statement
  895. if (noViableAction.indexOf("throw") == 0 || noViableAction.indexOf("goto") == 0) {
  896. // Remove the break statement since it isn't reachable with a throw exception
  897. int endOfBreak = howToFinish.postscript.indexOf("break;") + 6;
  898. String newPostScript = howToFinish.postscript.substring(endOfBreak);
  899. println(newPostScript);
  900. }
  901. else {
  902. println(howToFinish.postscript);
  903. }
  904. }
  905. else {
  906. println(howToFinish.postscript);
  907. }
  908. }
  909. }
  910. /** Generate the init action for a block, which may be a RuleBlock or a
  911. * plain AlternativeBLock.
  912. * @blk The block for which the preamble is to be generated.
  913. */
  914. protected void genBlockInitAction(AlternativeBlock blk)
  915. {
  916. // dump out init action
  917. if (blk.initAction != null) {
  918. printAction(processActionForSpecialSymbols(blk.initAction, blk.getLine(), currentRule, null));
  919. }
  920. }
  921. /** Generate the header for a block, which may be a RuleBlock or a
  922. * plain AlternativeBLock. This generates any variable declarations
  923. * and syntactic-predicate-testing variables.
  924. * @blk The block for which the preamble is to be generated.
  925. */
  926. protected void genBlockPreamble(AlternativeBlock blk) {
  927. // define labels for rule blocks.
  928. if ( blk instanceof RuleBlock ) {
  929. RuleBlock rblk = (RuleBlock)blk;
  930. if ( rblk.labeledElements!=null ) {
  931. for (int i=0; i<rblk.labeledElements.size(); i++) {
  932. AlternativeElement a = (AlternativeElement)rblk.labeledElements.elementAt(i);
  933. //System.out.println("looking at labeled element: "+a);
  934. //Variables for labeled rule refs and
  935. //subrules are different than variables for
  936. //grammar atoms. This test is a little tricky
  937. //because we want to get all rule refs and ebnf,
  938. //but not rule blocks or syntactic predicates
  939. if (
  940. a instanceof RuleRefElement ||
  941. a instanceof AlternativeBlock &&
  942. !(a instanceof RuleBlock) &&
  943. !(a instanceof SynPredBlock)
  944. ) {
  945. if (
  946. !(a instanceof RuleRefElement) &&
  947. ((AlternativeBlock)a).not &&
  948. analyzer.subruleCanBeInverted(((AlternativeBlock)a), grammar instanceof LexerGrammar)
  949. ) {
  950. // Special case for inverted subrules that
  951. // will be inlined. Treat these like
  952. // token or char literal references
  953. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  954. if (grammar.buildAST) {
  955. genASTDeclaration(a);
  956. }
  957. }
  958. else {
  959. if (grammar.buildAST) {
  960. // Always gen AST variables for
  961. // labeled elements, even if the
  962. // element itself is marked with !
  963. genASTDeclaration(a);
  964. }
  965. if ( grammar instanceof LexerGrammar ) {
  966. println("IToken "+a.getLabel()+" = null;");
  967. }
  968. if (grammar instanceof TreeWalkerGrammar) {
  969. // always generate rule-ref variables
  970. // for tree walker
  971. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  972. }
  973. }
  974. }
  975. else {
  976. // It is a token or literal reference. Generate the
  977. // correct variable type for this grammar
  978. println(labeledElementType + " " + a.getLabel() + " = " + labeledElementInit + ";");
  979. // In addition, generate *_AST variables if building ASTs
  980. if (grammar.buildAST) {
  981. //println(labeledElementASTType+" " + a.getLabel() + "_AST = null;");
  982. if (a instanceof GrammarAtom &&
  983. ((GrammarAtom)a).getASTNodeType()!=null ) {
  984. GrammarAtom ga = (GrammarAtom)a;
  985. genASTDeclaration(a, ga.getASTNodeType());
  986. }
  987. else {
  988. genASTDeclaration(a);
  989. }
  990. }
  991. }
  992. }
  993. }
  994. }
  995. }
  996. public void genBody(LexerGrammar g) throws IOException
  997. {
  998. // SAS: moved output creation to method so a subclass can change
  999. // how the output is generated (for VAJ interface)
  1000. setupOutput(grammar.getClassName());
  1001. genAST = false; // no way to gen trees.
  1002. saveText = true; // save consumed characters.
  1003. tabs=0;
  1004. // Generate header common to all CSharp output files
  1005. genHeader();
  1006. // Do not use printAction because we assume tabs==0
  1007. println(behavior.getHeaderAction(""));
  1008. // Generate the CSharp namespace declaration (if specified)
  1009. if (nameSpace != null)
  1010. nameSpace.emitDeclarations(currentOutput);
  1011. tabs++;
  1012. // Generate header specific to lexer CSharp file
  1013. println("// Generate header specific to lexer CSharp file");
  1014. println("using System;");
  1015. println("using Stream = System.IO.Stream;");
  1016. println("using TextReader = System.IO.TextReader;");
  1017. println("using Hashtable = System.Collections.Hashtable;");
  1018. println("using Comparer = System.Collections.Comparer;");
  1019. if ( !(g.caseSensitiveLiterals) )
  1020. {
  1021. println("using CaseInsensitiveHashCodeProvider = System.Collections.CaseInsensitiveHashCodeProvider;");
  1022. println("using CaseInsensitiveComparer = System.Collections.CaseInsensitiveComparer;");
  1023. }
  1024. println("");
  1025. println("using TokenStreamException = antlr.TokenStreamException;");
  1026. println("using TokenStreamIOException = antlr.TokenStreamIOException;");
  1027. println("using TokenStreamRecognitionException = antlr.TokenStreamRecognitionException;");
  1028. println("using CharStreamException = antlr.CharStreamException;");
  1029. println("using CharStreamIOException = antlr.CharStreamIOException;");
  1030. println("using ANTLRException = antlr.ANTLRException;");
  1031. println("using CharScanner = antlr.CharScanner;");
  1032. println("using InputBuffer = antlr.InputBuffer;");
  1033. println("using ByteBuffer = antlr.ByteBuffer;");
  1034. println("using CharBuffer = antlr.CharBuffer;");
  1035. println("using Token = antlr.Token;");
  1036. println("using IToken = antlr.IToken;");
  1037. println("using CommonToken = antlr.CommonToken;");
  1038. println("using SemanticException = antlr.SemanticException;");
  1039. println("using RecognitionException = antlr.RecognitionException;");
  1040. println("using NoViableAltForCharException = antlr.NoViableAltForCharException;");
  1041. println("using MismatchedCharException = antlr.MismatchedCharException;");
  1042. println("using TokenStream = antlr.TokenStream;");
  1043. println("using LexerSharedInputState = antlr.LexerSharedInputState;");
  1044. println("using BitSet = antlr.collections.impl.BitSet;");
  1045. // Generate user-defined lexer file preamble
  1046. println(grammar.preambleAction.getText());
  1047. // Generate lexer class definition
  1048. String sup=null;
  1049. if ( grammar.superClass!=null ) {
  1050. sup = grammar.superClass;
  1051. }
  1052. else {
  1053. sup = "antlr." + grammar.getSuperClass();
  1054. }
  1055. // print javadoc comment if any
  1056. if ( grammar.comment!=null )
  1057. {
  1058. _println(grammar.comment);
  1059. }
  1060. Token tprefix = (Token)grammar.options.get("classHeaderPrefix");
  1061. if (tprefix == null) {
  1062. print("public ");
  1063. }
  1064. else {
  1065. String p = StringUtils.stripFrontBack(tprefix.getText(), "\"", "\"");
  1066. if (p == null) {
  1067. print("public ");
  1068. }
  1069. else {
  1070. print(p+" ");
  1071. }
  1072. }
  1073. print("class " + grammar.getClassName() + " : "+sup);
  1074. println(", TokenStream");
  1075. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  1076. if ( tsuffix != null )
  1077. {
  1078. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  1079. if ( suffix != null )
  1080. {
  1081. print(", "+suffix); // must be an interface name for CSharp
  1082. }
  1083. }
  1084. println(" {");
  1085. tabs++;
  1086. // Generate 'const' definitions for Token IDs
  1087. genTokenDefinitions(grammar.tokenManager);
  1088. // Generate user-defined lexer class members
  1089. print(
  1090. processActionForSpecialSymbols(grammar.classMemberAction.getText(), grammar.classMemberAction.getLine(), currentRule, null)
  1091. );
  1092. //
  1093. // Generate the constructor from InputStream, which in turn
  1094. // calls the ByteBuffer constructor
  1095. //
  1096. println("public " + grammar.getClassName() + "(Stream ins) : this(new ByteBuffer(ins))");
  1097. println("{");
  1098. println("}");
  1099. println("");
  1100. //
  1101. // Generate the constructor from Reader, which in turn
  1102. // calls the CharBuffer constructor
  1103. //
  1104. println("public " + grammar.getClassName() + "(TextReader r) : this(new CharBuffer(r))");
  1105. println("{");
  1106. println("}");
  1107. println("");
  1108. print("public " + grammar.getClassName() + "(InputBuffer ib)");
  1109. // if debugging, wrap the input buffer in a debugger
  1110. if (grammar.debuggingOutput)
  1111. println(" : this(new LexerSharedInputState(new antlr.debug.DebuggingInputBuffer(ib)))");
  1112. else
  1113. println(" : this(new LexerSharedInputState(ib))");
  1114. println("{");
  1115. println("}");
  1116. println("");
  1117. //
  1118. // Generate the constructor from InputBuffer (char or byte)
  1119. //
  1120. println("public " + grammar.getClassName() + "(LexerSharedInputState state) : base(state)");
  1121. println("{");
  1122. tabs++;
  1123. println("initialize();");
  1124. tabs--;
  1125. println("}");
  1126. // Generate the initialize function
  1127. println("private void initialize()");
  1128. println("{");
  1129. tabs++;
  1130. // if debugging, set up array variables and call user-overridable
  1131. // debugging setup method
  1132. if ( grammar.debuggingOutput ) {
  1133. println("ruleNames = _ruleNames;");
  1134. println("semPredNames = _semPredNames;");
  1135. println("setupDebugging();");
  1136. }
  1137. // Generate the setting of various generated options.
  1138. // These need to be before the literals since ANTLRHashString depends on
  1139. // the casesensitive stuff.
  1140. println("caseSensitiveLiterals = " + g.caseSensitiveLiterals + ";");
  1141. println("setCaseSensitive(" + g.caseSensitive + ");");
  1142. // Generate the initialization of a hashtable
  1143. // containing the string literals used in the lexer
  1144. // The literals variable itself is in CharScanner
  1145. if (g.caseSensitiveLiterals)
  1146. println("literals = new Hashtable(100, (float) 0.4, null, Comparer.Default);");
  1147. else
  1148. println("literals = new Hashtable(100, (float) 0.4, CaseInsensitiveHashCodeProvider.Default, CaseInsensitiveComparer.Default);");
  1149. Enumeration keys = grammar.tokenManager.getTokenSymbolKeys();
  1150. while ( keys.hasMoreElements() ) {
  1151. String key = (String)keys.nextElement();
  1152. if ( key.charAt(0) != '"' ) {
  1153. continue;
  1154. }
  1155. TokenSymbol sym = grammar.tokenManager.getTokenSymbol(key);
  1156. if ( sym instanceof StringLiteralSymbol ) {
  1157. StringLiteralSymbol s = (StringLiteralSymbol)sym;
  1158. println("literals.Add(" + s.getId() + ", " + s.getTokenType() + ");");
  1159. }
  1160. }
  1161. Enumeration ids;
  1162. tabs--;
  1163. println("}");
  1164. // generate the rule name array for debugging
  1165. if (grammar.debuggingOutput) {
  1166. println("private static readonly string[] _ruleNames = new string[] {");
  1167. ids = grammar.rules.elements();
  1168. int ruleNum=0;
  1169. while ( ids.hasMoreElements() ) {
  1170. GrammarSymbol sym = (GrammarSymbol) ids.nextElement();
  1171. if ( sym instanceof RuleSymbol)
  1172. println(" \""+((RuleSymbol)sym).getId()+"\",");
  1173. }
  1174. println("};");
  1175. }
  1176. // Generate nextToken() rule.
  1177. // nextToken() is a synthetic lexer rule that is the implicit OR of all
  1178. // user-defined lexer rules.
  1179. genNextToken();
  1180. // Generate code for each rule in the lexer
  1181. ids = grammar.rules.elements();
  1182. int ruleNum=0;
  1183. while ( ids.hasMoreElements() ) {
  1184. RuleSymbol sym = (RuleSymbol) ids.nextElement();
  1185. // Don't generate the synthetic rules
  1186. if (!sym.getId().equals("mnextToken")) {
  1187. genRule(sym, false, ruleNum++, grammar.tokenManager);
  1188. }
  1189. exitIfError();
  1190. }
  1191. // Generate the semantic predicate map for debugging
  1192. if (grammar.debuggingOutput)
  1193. genSemPredMap();
  1194. // Generate the bitsets used throughout the lexer
  1195. genBitsets(bitsetsUsed, ((LexerGrammar)grammar).charVocabulary.size());
  1196. println("");
  1197. tabs--;
  1198. println("}");
  1199. tabs--;
  1200. // Generate the CSharp namespace closures (if required)
  1201. if (nameSpace != null)
  1202. nameSpace.emitClosures(currentOutput);
  1203. // Close the lexer output stream
  1204. currentOutput.close();
  1205. currentOutput = null;
  1206. }
  1207. public void genInitFactory( Grammar g ) {
  1208. if( g.buildAST )
  1209. {
  1210. // Generate the method to initialize an ASTFactory when we're
  1211. // building AST's
  1212. println("static public void initializeASTFactory( ASTFactory factory )");
  1213. println("{");
  1214. tabs++;
  1215. println("factory.setMaxNodeType("+g.tokenManager.maxTokenType()+");");
  1216. // Walk the token vocabulary and generate code to register every TokenID->ASTNodeType
  1217. // mapping specified in the tokens {...} section with the ASTFactory.
  1218. Vector v = g.tokenManager.getVocabulary();
  1219. for (int i = 0; i < v.size(); i++) {
  1220. String s = (String)v.elementAt(i);
  1221. if (s != null) {
  1222. TokenSymbol ts = g.tokenManager.getTokenSymbol(s);
  1223. if (ts != null && ts.getASTNodeType() != null) {
  1224. println("factory.setTokenTypeASTNodeType(" + s + ", \"" + ts.getASTNodeType() + "\");");
  1225. }
  1226. }
  1227. }
  1228. tabs--;
  1229. println("}");
  1230. }
  1231. }
  1232. public void genBody(ParserGrammar g) throws IOException
  1233. {
  1234. // Open the output stream for the parser and set the currentOutput
  1235. // SAS: moved file setup so subclass could do it (for VAJ interface)
  1236. setupOutput(grammar.getClassName());
  1237. genAST = grammar.buildAST;
  1238. tabs = 0;
  1239. // Generate the header common to all output files.
  1240. genHeader();
  1241. // Do not use printAction because we assume tabs==0
  1242. println(behavior.getHeaderAction(""));
  1243. // Generate the CSharp namespace declaration (if specified)
  1244. if (nameSpace != null)
  1245. nameSpace.emitDeclarations(currentOutput);
  1246. tabs++;
  1247. // Generate header for the parser
  1248. println("// Generate the header common to all output files.");
  1249. println("using System;");
  1250. println("");
  1251. println("using TokenBuffer = antlr.TokenBuffer;");
  1252. println("using TokenStreamException = antlr.TokenStreamException;");
  1253. println("using TokenStreamIOException = antlr.TokenStreamIOException;");
  1254. println("using ANTLRException = antlr.ANTLRException;");
  1255. String qualifiedClassName = grammar.getSuperClass();
  1256. String[] unqualifiedClassName = split(qualifiedClassName, ".");
  1257. println("using " + unqualifiedClassName[unqualifiedClassName.length-1] + " = antlr." + qualifiedClassName + ";");
  1258. println("using Token = antlr.Token;");
  1259. println("using IToken = antlr.IToken;");
  1260. println("using TokenStream = antlr.TokenStream;");
  1261. println("using RecognitionException = antlr.RecognitionException;");
  1262. println("using NoViableAltException = antlr.NoViableAltException;");
  1263. println("using MismatchedTokenException = antlr.MismatchedTokenException;");
  1264. println("using SemanticException = antlr.SemanticException;");
  1265. println("using ParserSharedInputState = antlr.ParserSharedInputState;");
  1266. println("using BitSet = antlr.collections.impl.BitSet;");
  1267. if ( genAST ) {
  1268. println("using AST = antlr.collections.AST;");
  1269. println("using ASTPair = antlr.ASTPair;");
  1270. println("using ASTFactory = antlr.ASTFactory;");
  1271. println("using ASTArray = antlr.collections.impl.ASTArray;");
  1272. }
  1273. // Output the user-defined parser preamble
  1274. println(grammar.preambleAction.getText());
  1275. // Generate parser class definition
  1276. String sup=null;
  1277. if ( grammar.superClass != null )
  1278. sup = grammar.superClass;
  1279. else
  1280. sup = "antlr." + grammar.getSuperClass();
  1281. // print javadoc comment if any
  1282. if ( grammar.comment!=null ) {
  1283. _println(grammar.comment);
  1284. }
  1285. Token tprefix = (Token)grammar.options.get("classHeaderPrefix");
  1286. if (tprefix == null) {
  1287. print("public ");
  1288. }
  1289. else {
  1290. String p = StringUtils.stripFrontBack(tprefix.getText(), "\"", "\"");
  1291. if (p == null) {
  1292. print("public ");
  1293. }
  1294. else {
  1295. print(p+" ");
  1296. }
  1297. }
  1298. println("class " + grammar.getClassName() + " : "+sup);
  1299. Token tsuffix = (Token)grammar.options.get("classHeaderSuffix");
  1300. if ( tsuffix != null ) {
  1301. String suffix = StringUtils.stripFrontBack(tsuffix.getText(),"\"","\"");
  1302. if ( suffix != null )
  1303. print(" , "+suffix); // must be an interface name for CSharp
  1304. }
  1305. println("{");
  1306. tabs++;
  1307. // Generate 'const' definitions for Token IDs
  1308. genTokenDefinitions(grammar.tokenManager);
  1309. // set up an array of all the rule names so the debugger can
  1310. // keep track of them only by number -- less to store in tree...
  1311. if (grammar.debuggingOutput) {
  1312. println("private static readonly string[] _ruleNames = new strin…

Large files files are truncated, but you can click here to view the full file