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

编译器/解释器

开发平台:

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