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

编译器/解释器

开发平台:

Others

  1. package antlr;
  2. /* ANTLR Translator Generator
  3.  * Project led by Terence Parr at http://www.jGuru.com
  4.  * Software rights: http://www.antlr.org/RIGHTS.html
  5.  *
  6.  * $Id: //depot/code/org.antlr/release/antlr-2.7.0/antlr/MakeGrammar.java#1 $
  7.  */
  8. import antlr.collections.Stack;
  9. import antlr.collections.impl.LList;
  10. import antlr.collections.impl.Vector;
  11. public class MakeGrammar extends DefineGrammarSymbols {
  12. protected Stack blocks = new LList(); // track subrules--Stack<BlockContext>
  13. protected RuleRefElement lastRuleRef;
  14. protected RuleEndElement ruleEnd;   // used if not nested
  15. protected RuleBlock ruleBlock; // points to block of current rule.
  16. protected int nested = 0; // nesting inside a subrule
  17. protected boolean grammarError = false;
  18. ExceptionSpec currentExceptionSpec = null;
  19. public MakeGrammar(Tool tool_, String[] args_, LLkAnalyzer analyzer_) {
  20. super(tool_, args_, analyzer_);
  21. }
  22. /** Abort the processing of a grammar (due to syntax errors) */
  23. public void abortGrammar() {
  24. String s = "unknown grammar";
  25. if ( grammar!=null ) {
  26. s = grammar.getClassName();
  27. }
  28. tool.error("aborting grammar '" + s + "' due to errors");
  29. super.abortGrammar();
  30. }
  31. protected void addElementToCurrentAlt(AlternativeElement e) {
  32. e.enclosingRuleName = ruleBlock.ruleName;
  33. context().addAlternativeElement(e);
  34. }
  35. public void beginAlt(boolean doAutoGen_) {
  36. super.beginAlt(doAutoGen_);
  37. Alternative alt = new Alternative();
  38. alt.setAutoGen(doAutoGen_);
  39. context().block.addAlternative(alt);
  40. }
  41. public void beginChildList() {
  42. super.beginChildList();
  43. context().block.addAlternative(new Alternative());
  44. }
  45. /** Add an exception group to a rule (currently a no-op) */
  46. public void beginExceptionGroup() {
  47. super.beginExceptionGroup();
  48. if (!(context().block instanceof RuleBlock))
  49. {
  50. tool.panic("beginExceptionGroup called outside of rule block");
  51. }
  52. }
  53. /** Add an exception spec to an exception group or rule block */
  54. public void beginExceptionSpec(Token label) {
  55. // Hack the label string a bit to remove leading/trailing space.
  56. if (label != null) {
  57. label.setText( Tool.stripFront( Tool.stripBack(label.getText(), " nrt"), " nrt") );
  58. }
  59. super.beginExceptionSpec(label);
  60. // Don't check for currentExceptionSpec!=null because syntax errors
  61. // may leave it set to something.
  62. currentExceptionSpec = new ExceptionSpec(label);
  63. }
  64. public void beginSubRule(Token label, int line, boolean not) {
  65. super.beginSubRule(label,line, not);
  66. // we don't know what kind of subrule it is yet.
  67. // push a dummy one that will allow us to collect the
  68. // alternatives.  Later, we'll switch to real object.
  69. blocks.push(new BlockContext());
  70. context().block = new AlternativeBlock(grammar, line, not);
  71. context().altNum = 0; // reset alternative number
  72. nested++;
  73. // create a final node to which the last elememt of each
  74. // alternative will point.
  75. context().blockEnd = new BlockEndElement(grammar);
  76. // make sure end node points to start of block
  77. context().blockEnd.block = context().block;
  78. labelElement(context().block, label);
  79. }
  80. public void beginTree(int line) throws SemanticException {
  81. if (!(grammar instanceof TreeWalkerGrammar)) {
  82. tool.error("Trees only allowed in TreeParser", grammar.getFilename(), line);
  83. throw new SemanticException("Trees only allowed in TreeParser");
  84. }
  85. super.beginTree(line);
  86. blocks.push(new TreeBlockContext());
  87. context().block = new TreeElement(grammar, line);
  88. context().altNum = 0; // reset alternative number
  89. }
  90. public BlockContext context() {
  91. if ( blocks.height()==0 ) {
  92. return null;
  93. }
  94. else {
  95. return (BlockContext)blocks.top();
  96. }
  97. }
  98. /**Used to build nextToken() for the lexer.
  99.  * This builds a rule which has every "public" rule in the given Vector of
  100.  * rules as it's alternate.  Each rule ref generates a Token object.
  101.  * @param g  The Grammar that is being processed
  102.  * @param lexRules A vector of lexer rules that will be used to create an alternate block.
  103.  * @param rname The name of the resulting rule.
  104.  */
  105. public static RuleBlock createNextTokenRule(Grammar g, Vector lexRules, String rname) {
  106. // create actual rule data structure
  107. RuleBlock rb = new RuleBlock(g, rname);
  108. rb.setDefaultErrorHandler( g.getDefaultErrorHandler() );
  109. RuleEndElement ruleEnd = new RuleEndElement(g);
  110. rb.setEndElement(ruleEnd);
  111. ruleEnd.block = rb;
  112. // Add an alternative for each element of the rules vector.
  113. for (int i=0; i<lexRules.size(); i++) {
  114. RuleSymbol r = (RuleSymbol)lexRules.elementAt(i);
  115. if (!r.isDefined()) {
  116. g.tool.error("Lexer rule " + r.id.substring(1) + " is not defined");
  117. }
  118. else {
  119. if ( r.access.equals("public") ) {
  120. // create a rule ref to lexer rule
  121. // the Token is a RULE_REF not a TOKEN_REF since the
  122. // conversion to mRulename has already taken place
  123. RuleRefElement rr =
  124. new RuleRefElement(g,
  125.    new CommonToken(ANTLRTokenTypes.RULE_REF, r.getId()),
  126.    GrammarElement.AUTO_GEN_NONE);
  127. //labelElement(rr, new Token("_rettoken"));
  128. // rr.setIdAssign("_ttype");
  129. rr.setLabel("theRetToken");
  130. rr.enclosingRuleName = "nextToken";
  131. rr.next = ruleEnd;
  132. Alternative alt = new Alternative(rr);
  133. alt.setAutoGen(true); // keep text of elements
  134. rb.addAlternative(alt);
  135. // Add a reference to the rule used for the alt
  136. r.addReference(rr);
  137. }
  138. }
  139. }
  140. rb.setAutoGen(true); // keep text of elements
  141. rb.prepareForAnalysis();
  142. //System.out.println(rb);
  143. return rb;
  144. }
  145. /** Return block as if they had typed: "( rule )?" */
  146. private AlternativeBlock createOptionalRuleRef(String rule, int line) {
  147. // Make the subrule
  148. AlternativeBlock blk = new AlternativeBlock(grammar, line, false);
  149. // Make sure rule is defined
  150.   String mrule = CodeGenerator.lexerRuleName(rule); // can only be a lexer rule!
  151. if ( !grammar.isDefined(mrule) ) {
  152. grammar.define(new RuleSymbol(mrule));
  153. }
  154. // Make the rule ref element
  155.   Token t = new CommonToken(ANTLRTokenTypes.TOKEN_REF, rule);
  156.   t.setLine(line);
  157.   RuleRefElement rref =
  158. new RuleRefElement(grammar, t, GrammarElement.AUTO_GEN_NONE);
  159. rref.enclosingRuleName = ruleBlock.ruleName;
  160. // Make the end of block element
  161. BlockEndElement end = new BlockEndElement(grammar);
  162. end.block = blk; // end block points back to start of blk
  163. // Make an alternative, putting the rule ref into it
  164. Alternative alt = new Alternative(rref);
  165. alt.addElement(end); // last element in alt points to end of block
  166. // Add the alternative to this block
  167. blk.addAlternative(alt);
  168. // create an empty (optional) alt and add to blk
  169. Alternative optAlt = new Alternative();
  170. optAlt.addElement(end); // points immediately to end of block
  171. blk.addAlternative(optAlt);
  172. blk.prepareForAnalysis();
  173. return blk;
  174. }
  175. public void defineRuleName(Token r,
  176.    String access,
  177.    boolean ruleAutoGen,
  178.    String docComment)
  179. throws SemanticException
  180. {
  181. // if ( Character.isUpperCase(r.getText().charAt(0)) ) { 
  182.   if ( r.type == ANTLRTokenTypes.TOKEN_REF ) { 
  183. if (!(grammar instanceof LexerGrammar)) {
  184. tool.error("Lexical rule "+r.getText()+
  185.    " defined outside of lexer",
  186.    grammar.getFilename(), r.getLine());
  187. r.setText(r.getText().toLowerCase());
  188. }
  189. }
  190. else {
  191. if (grammar instanceof LexerGrammar) {
  192. tool.error("Non-lexical rule "+r.getText()+
  193.    " defined inside of lexer",
  194.    grammar.getFilename(), r.getLine());
  195. r.setText(r.getText().toUpperCase());
  196. }
  197. }
  198. super.defineRuleName(r, access, ruleAutoGen, docComment);
  199. String id = r.getText();
  200. // if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
  201.   if ( r.type == ANTLRTokenTypes.TOKEN_REF ) { // lexer rule?
  202. id = CodeGenerator.lexerRuleName(id);
  203. }
  204. RuleSymbol rs = (RuleSymbol) grammar.getSymbol(id);
  205. RuleBlock rb = new RuleBlock(grammar, r.getText(), r.getLine(), ruleAutoGen);
  206. // Lexer rules do not generate default error handling
  207. rb.setDefaultErrorHandler(grammar.getDefaultErrorHandler());
  208. ruleBlock = rb;
  209. blocks.push(new BlockContext()); // enter new context
  210. context().block = rb;
  211. rs.setBlock(rb);
  212. ruleEnd = new RuleEndElement(grammar);
  213. rb.setEndElement(ruleEnd);
  214. nested = 0;
  215. }
  216. public void endAlt() {
  217. super.endAlt();
  218. if ( nested==0 ) { // all rule-level alts link to ruleEnd node
  219. addElementToCurrentAlt(ruleEnd);
  220. }
  221. else {
  222. addElementToCurrentAlt(context().blockEnd);
  223. }
  224. context().altNum++;
  225. }
  226. public void endChildList() {
  227. super.endChildList();
  228. // create a final node to which the last elememt of the single
  229. // alternative will point.  Done for compatibility with analyzer.
  230. // Does NOT point to any block like alternative blocks because the
  231. // TreeElement is not a block.  This is used only as a placeholder.
  232. BlockEndElement be = new BlockEndElement(grammar);
  233. be.block = context().block;
  234. addElementToCurrentAlt(be);
  235. }
  236. public void endExceptionGroup() {
  237. super.endExceptionGroup();
  238. }
  239. public void endExceptionSpec() {
  240. super.endExceptionSpec();
  241. if (currentExceptionSpec == null)
  242. {
  243. tool.panic("exception processing internal error -- no active exception spec");
  244. }
  245. if (context().block instanceof RuleBlock)
  246. {
  247. // Named rule
  248. ((RuleBlock)context().block).addExceptionSpec(currentExceptionSpec);
  249. } else {
  250. // It must be a plain-old alternative block
  251. if (context().currentAlt().exceptionSpec != null) {
  252. tool.error("Alternative already has an exception specification", grammar.getFilename(), context().block.getLine());
  253. }
  254. else {
  255. context().currentAlt().exceptionSpec = currentExceptionSpec;
  256. }
  257. }
  258. currentExceptionSpec = null;
  259. }
  260. /** Called at the end of processing a grammar */
  261. public void endGrammar() {
  262. if (grammarError) {
  263. abortGrammar();
  264. }
  265. else {
  266. super.endGrammar();
  267. }
  268. }
  269. public void endRule(String rule) {
  270. super.endRule(rule);
  271. BlockContext ctx = (BlockContext) blocks.pop(); // remove scope
  272. // record the start of this block in the ending node
  273. ruleEnd.block = ctx.block;
  274. ruleEnd.block.prepareForAnalysis();
  275. //System.out.println(ctx.block);
  276. }
  277. public void endSubRule() {
  278. super.endSubRule();
  279. nested--;
  280. // remove subrule context from scope stack
  281. BlockContext ctx = (BlockContext)blocks.pop();
  282. AlternativeBlock block = ctx.block;
  283. // If the subrule is marked with ~, check that it is
  284. // a valid candidate for analysis
  285. if (
  286. block.not &&
  287. !(block instanceof SynPredBlock) &&
  288. !(block instanceof ZeroOrMoreBlock) &&
  289. !(block instanceof OneOrMoreBlock)
  290. )
  291. {
  292. if (!analyzer.subruleCanBeInverted(block, grammar instanceof LexerGrammar)) {
  293. String newline = System.getProperty("line.separator");
  294. tool.error(
  295. "This subrule cannot be inverted.  Only subrules of the form:"+newline +
  296. "    (T1|T2|T3...) or" + newline +
  297. "    ('c1'|'c2'|'c3'...)" + newline +
  298. "may be inverted (ranges are also allowed).",
  299. grammar.getFilename(),
  300. block.getLine()
  301. );
  302. }
  303. }
  304. // add the subrule as element if not a syn pred
  305. if ( block instanceof SynPredBlock ) {
  306. // record a reference to the recently-recognized syn pred in the
  307. // enclosing block.
  308. SynPredBlock synpred = (SynPredBlock)block;
  309. context().block.hasASynPred = true;
  310. context().currentAlt().synPred = synpred;
  311. grammar.hasSyntacticPredicate = true;
  312. synpred.removeTrackingOfRuleRefs(grammar);
  313. }
  314. else {
  315. addElementToCurrentAlt(block);
  316. }
  317. ctx.blockEnd.block.prepareForAnalysis();
  318. }
  319. public void endTree() {
  320. super.endTree();
  321. BlockContext ctx = (BlockContext) blocks.pop();
  322. addElementToCurrentAlt(ctx.block); // add new TreeElement to enclosing alt.
  323. }
  324. /** Remember that a major error occured in the grammar */
  325. public void hasError() {
  326. grammarError = true;
  327. }
  328. private void labelElement(AlternativeElement el, Token label) {
  329. if ( label != null ) {
  330. // Does this label already exist?
  331. for (int i = 0; i < ruleBlock.labeledElements.size(); i++) {
  332. AlternativeElement altEl = (AlternativeElement)ruleBlock.labeledElements.elementAt(i);
  333. String l = altEl.getLabel();
  334. if (l != null && l.equals(label.getText())) {
  335. tool.error("Label '" + label.getText() + "' has already been defined", grammar.getFilename(), label.getLine());
  336. return;
  337. }
  338. }
  339. // add this node to the list of labeled elements
  340. el.setLabel(label.getText());
  341. ruleBlock.labeledElements.appendElement(el);
  342. }
  343. }
  344. public void noAutoGenSubRule() {
  345. context().block.setAutoGen(false);
  346. }
  347. public void oneOrMoreSubRule() {
  348. if (context().block.not) {
  349. tool.error("'~' cannot be applied to (...)* subrule", grammar.getFilename(), context().block.getLine());
  350. }
  351. // create the right kind of object now that we know what that is
  352. // and switch the list of alternatives.  Adjust the stack of blocks.
  353. // copy any init action also.
  354. OneOrMoreBlock b = new OneOrMoreBlock(grammar);
  355. setBlock(b,context().block);
  356. BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
  357. blocks.push(new BlockContext());
  358. context().block = b;
  359. context().blockEnd = old.blockEnd;
  360. context().blockEnd.block = b;
  361. }
  362. public void optionalSubRule() {
  363. if (context().block.not) {
  364. tool.error("'~' cannot be applied to (...)? subrule", grammar.getFilename(), context().block.getLine());
  365. }
  366. // convert (X)? -> (X|) so that we can ignore optional blocks altogether!
  367. // It already thinks that we have a simple subrule, just add option block.
  368. beginAlt(false);
  369. endAlt();
  370. }
  371. public void refAction(Token action) {
  372. super.refAction(action);
  373. context().block.hasAnAction = true;
  374. addElementToCurrentAlt(new ActionElement(grammar,action));
  375. }
  376. // Only called for rule blocks
  377. public void refArgAction(Token action) {
  378. ((RuleBlock)context().block).argAction = action.getText();
  379. }
  380. public void refCharLiteral(Token lit, Token label, boolean inverted, int autoGenType, boolean lastInRule) {
  381. if (!(grammar instanceof LexerGrammar)) {
  382. tool.error("Character literal only valid in lexer", grammar.getFilename(), lit.getLine());
  383. return;
  384. }
  385. super.refCharLiteral(lit, label, inverted, autoGenType, lastInRule);
  386. CharLiteralElement cl = new CharLiteralElement((LexerGrammar)grammar, lit, inverted, autoGenType);
  387. // Generate a warning for non-lowercase ASCII when case-insensitive
  388. if (
  389. !((LexerGrammar)grammar).caseSensitive && cl.getType() < 128 && 
  390. Character.toLowerCase((char)cl.getType()) != (char)cl.getType()
  391. ) {
  392. tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine());
  393. }
  394. addElementToCurrentAlt(cl);
  395. labelElement(cl, label);
  396. // if ignore option is set, must add an optional call to the specified rule.
  397. String ignore = ruleBlock.getIgnoreRule();
  398. if ( !lastInRule && ignore!=null ) {
  399. addElementToCurrentAlt(createOptionalRuleRef(ignore, lit.getLine()));
  400. }
  401. }
  402. public void refCharRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
  403. if (!(grammar instanceof LexerGrammar)) {
  404. tool.error("Character range only valid in lexer", grammar.getFilename(), t1.getLine());
  405. return;
  406. }
  407. int rangeMin = ANTLRLexer.tokenTypeForCharLiteral(t1.getText());
  408. int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(t2.getText());
  409. if (rangeMax < rangeMin) {
  410. tool.error("Malformed range.", grammar.getFilename(), t1.getLine());
  411. return;
  412. }
  413. // Generate a warning for non-lowercase ASCII when case-insensitive
  414. if (!((LexerGrammar)grammar).caseSensitive) {
  415. if (rangeMin < 128 && Character.toLowerCase((char)rangeMin) != (char)rangeMin) {
  416. tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t1.getLine());
  417. }
  418. if (rangeMax < 128 && Character.toLowerCase((char)rangeMax) != (char)rangeMax) {
  419. tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t2.getLine());
  420. }
  421. }
  422. super.refCharRange(t1, t2, label, autoGenType, lastInRule);
  423. CharRangeElement cr = new CharRangeElement((LexerGrammar)grammar, t1, t2, autoGenType);
  424. addElementToCurrentAlt(cr);
  425. labelElement(cr, label);
  426. // if ignore option is set, must add an optional call to the specified rule.
  427. String ignore = ruleBlock.getIgnoreRule();
  428. if ( !lastInRule && ignore!=null ) {
  429. addElementToCurrentAlt(createOptionalRuleRef(ignore, t1.getLine()));
  430. }
  431. }
  432. public void refTokensSpecElementOption(Token tok,
  433.    Token option,
  434.    Token value) {
  435. /*
  436. System.out.println("setting tokens spec option for "+tok.getText());
  437. System.out.println(option.getText()+","+value.getText());
  438. */
  439. TokenSymbol ts = (TokenSymbol)
  440. grammar.tokenManager.getTokenSymbol(tok.getText());
  441. if ( ts==null ) {
  442. tool.panic("cannot find "+tok.getText()+"in tokens {...}");
  443. }
  444. if ( option.getText().equals("AST") ) {
  445. ts.setASTNodeType(value.getText());
  446. }
  447. else {
  448. grammar.tool.error("invalid tokens {...} element option:"+
  449.    option.getText(),
  450.    grammar.getFilename(),
  451.    option.getLine());
  452. }
  453. }
  454. public void refElementOption(Token option, Token value) {
  455. /*
  456. System.out.println("setting option for "+context().currentElement());
  457. System.out.println(option.getText()+","+value.getText());
  458. */
  459. AlternativeElement e = context().currentElement();
  460. if ( e instanceof StringLiteralElement ||
  461.      e instanceof TokenRefElement ||
  462.      e instanceof WildcardElement )
  463.     {
  464. ((GrammarAtom)e).setOption(option, value);
  465. }
  466. else {
  467. tool.error("cannot use element option ("+option.getText()+
  468.    ") for this kind of element",
  469.    grammar.getFilename(), option.getLine());
  470. }
  471. }
  472. /** Add an exception handler to an exception spec */
  473. public void refExceptionHandler(Token exTypeAndName, String action) {
  474. super.refExceptionHandler(exTypeAndName, action);
  475. if (currentExceptionSpec == null)
  476. {
  477. tool.panic("exception handler processing internal error");
  478. }
  479. currentExceptionSpec.addHandler(new ExceptionHandler(exTypeAndName, action));
  480. }
  481. public void refInitAction(Token action) {
  482. super.refAction(action);
  483. context().block.setInitAction(action.getText());
  484. }
  485. public void refMemberAction(Token act) {
  486. grammar.classMemberAction = act.getText();
  487. }
  488. public void refPreambleAction(Token act) {
  489. super.refPreambleAction(act);
  490. }
  491. // Only called for rule blocks
  492. public void refReturnAction(Token returnAction) {
  493. if (grammar instanceof LexerGrammar) {
  494. String name = CodeGenerator.lexerRuleName(((RuleBlock)context().block).getRuleName());
  495. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(name);
  496. if (rs.access.equals("public")) {
  497. tool.warning("public Lexical rules cannot specify return type", grammar.getFilename(), returnAction.getLine());
  498. return;
  499. }
  500. }
  501. ((RuleBlock)context().block).returnAction = returnAction.getText();
  502. }
  503. public void refRule(Token idAssign,
  504. Token r,
  505. Token label,
  506. Token args,
  507. int autoGenType)
  508. {
  509. // Disallow parser rule references in the lexer
  510. if (grammar instanceof LexerGrammar) {
  511. // if (!Character.isUpperCase(r.getText().charAt(0))) {
  512.   if ( r.type != ANTLRTokenTypes.TOKEN_REF ) {
  513. tool.error("Parser rule " + r.getText() + " referenced in lexer");
  514. return;
  515. }
  516. if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
  517. tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), r.getLine());
  518. }
  519. }
  520. super.refRule(idAssign, r, label, args, autoGenType);
  521. lastRuleRef = new RuleRefElement(grammar, r, autoGenType);
  522. if (args != null)
  523. {
  524. lastRuleRef.setArgs(args.getText());
  525. }
  526. if (idAssign != null)
  527. {
  528. lastRuleRef.setIdAssign(idAssign.getText());
  529. }
  530. addElementToCurrentAlt(lastRuleRef);
  531. String id = r.getText();
  532. // if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
  533.   if ( r.type == ANTLRTokenTypes.TOKEN_REF ) { // lexer rule?
  534. id = CodeGenerator.lexerRuleName(id);
  535. }
  536. // update symbol table so it knows what nodes reference the rule.
  537. RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
  538. rs.addReference(lastRuleRef);
  539. labelElement(lastRuleRef, label);
  540. }
  541. public void refSemPred(Token pred) {
  542. //System.out.println("refSemPred "+pred.getText());
  543. super.refSemPred(pred);
  544. //System.out.println("context().block: "+context().block);
  545. if ( context().currentAlt().atStart() ) {
  546. context().currentAlt().semPred = pred.getText();
  547. }
  548. else {
  549. ActionElement a = new ActionElement(grammar,pred);
  550. a.isSemPred = true;
  551. addElementToCurrentAlt(a);
  552. }
  553. //System.out.println("DONE refSemPred "+pred.getText());
  554. }
  555. public void refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule) {
  556. super.refStringLiteral(lit, label, autoGenType, lastInRule);
  557. if (grammar instanceof TreeWalkerGrammar && autoGenType == GrammarElement.AUTO_GEN_CARET) {
  558. tool.error("^ not allowed in here for tree-walker", grammar.getFilename(), lit.getLine());
  559. }
  560. StringLiteralElement sl = new StringLiteralElement(grammar, lit, autoGenType);
  561. // If case-insensitive, then check each char of the stirng literal
  562. if (grammar instanceof LexerGrammar && !((LexerGrammar)grammar).caseSensitive) {
  563. for (int i = 1; i < lit.getText().length()-1; i++) {
  564. char c = lit.getText().charAt(i);
  565. if (c < 128 && Character.toLowerCase(c) != c) {
  566. tool.warning("Characters of string literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine());
  567. break;
  568. }
  569. }
  570. }
  571. addElementToCurrentAlt(sl);
  572. labelElement(sl, label);
  573. // if ignore option is set, must add an optional call to the specified rule.
  574. String ignore = ruleBlock.getIgnoreRule();
  575. if ( !lastInRule && ignore!=null ) {
  576. addElementToCurrentAlt(createOptionalRuleRef(ignore, lit.getLine()));
  577. }
  578. }
  579. public void refToken(Token idAssign, Token t, Token label, Token args,
  580. boolean inverted, int autoGenType, boolean lastInRule) {
  581. if (grammar instanceof LexerGrammar) {
  582. // In lexer, token references are really rule references
  583. if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
  584. tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), t.getLine());
  585. }
  586. if (inverted) {
  587. tool.error("~TOKEN is not allowed in lexer", grammar.getFilename(), t.getLine());
  588. }
  589. refRule(idAssign, t, label, args, autoGenType);
  590. // if ignore option is set, must add an optional call to the specified token rule.
  591. String ignore = ruleBlock.getIgnoreRule();
  592. if ( !lastInRule && ignore!=null ) {
  593. addElementToCurrentAlt(createOptionalRuleRef(ignore, t.getLine()));
  594. }
  595. } else {
  596. // Cannot have token ref args or assignment outside of lexer
  597. if (idAssign!= null)
  598. {
  599. tool.error("Assignment from token reference only allowed in lexer", grammar.getFilename(), idAssign.getLine());
  600. }
  601. if (args != null)
  602. {
  603. tool.error("Token reference arguments only allowed in lexer", grammar.getFilename(), args.getLine());
  604. }
  605. super.refToken(idAssign, t, label, args, inverted, autoGenType, lastInRule);
  606. TokenRefElement te = new TokenRefElement(grammar, t, inverted, autoGenType);
  607. addElementToCurrentAlt(te);
  608. labelElement(te, label);
  609. }
  610. }
  611. public void refTokenRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
  612. if (grammar instanceof LexerGrammar) {
  613. tool.error("Token range not allowed in lexer", grammar.getFilename(), t1.getLine());
  614. return;
  615. }
  616. super.refTokenRange(t1, t2, label, autoGenType, lastInRule);
  617. TokenRangeElement tr = new TokenRangeElement(grammar, t1, t2, autoGenType);
  618. if (tr.end < tr.begin) {
  619. tool.error("Malformed range.", grammar.getFilename(), t1.getLine());
  620. return;
  621. }
  622. addElementToCurrentAlt(tr);
  623. labelElement(tr, label);
  624. }
  625. public void refTreeSpecifier(Token treeSpec) {
  626. context().currentAlt().treeSpecifier = treeSpec;
  627. }
  628. public void refWildcard(Token t, Token label, int autoGenType) {
  629. super.refWildcard(t, label, autoGenType);
  630. WildcardElement wc = new WildcardElement(grammar, t, autoGenType);
  631. addElementToCurrentAlt(wc);
  632. labelElement(wc, label);
  633. }
  634. /** Get ready to process a new grammar */
  635. public void reset() {
  636. super.reset();
  637. blocks = new LList();
  638. lastRuleRef = null;
  639. ruleEnd = null;
  640. ruleBlock = null;
  641. nested = 0;
  642. currentExceptionSpec = null;
  643. grammarError = false;
  644. }
  645. public void setArgOfRuleRef(Token argAction) {
  646. super.setArgOfRuleRef(argAction);
  647. lastRuleRef.setArgs(argAction.getText());
  648. }
  649. public static void setBlock(AlternativeBlock b, AlternativeBlock src) {
  650. b.setAlternatives(src.getAlternatives());
  651. b.initAction = src.initAction;
  652. //b.lookaheadDepth = src.lookaheadDepth;
  653. b.label = src.label;
  654. b.hasASynPred = src.hasASynPred;
  655. b.hasAnAction = src.hasAnAction;
  656. b.warnWhenFollowAmbig = src.warnWhenFollowAmbig;
  657. b.generateAmbigWarnings = src.generateAmbigWarnings;
  658. b.line = src.line;
  659. b.greedy = src.greedy;
  660. b.greedySet = src.greedySet;
  661. }
  662. public void setRuleOption(Token key, Token value) {
  663. //((RuleBlock)context().block).setOption(key, value);
  664. ruleBlock.setOption(key, value);
  665. }
  666. public void setSubruleOption(Token key, Token value) {
  667. ((AlternativeBlock)context().block).setOption(key, value);
  668. }
  669. public void synPred() {
  670. if (context().block.not) {
  671. tool.error("'~' cannot be applied to syntactc predicate", grammar.getFilename(), context().block.getLine());
  672. }
  673. // create the right kind of object now that we know what that is
  674. // and switch the list of alternatives.  Adjust the stack of blocks.
  675. // copy any init action also.
  676. SynPredBlock b = new SynPredBlock(grammar);
  677. setBlock(b,context().block);
  678. BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
  679. blocks.push(new BlockContext());
  680. context().block = b;
  681. context().blockEnd = old.blockEnd;
  682. context().blockEnd.block = b;
  683. }
  684. public void zeroOrMoreSubRule() {
  685. if (context().block.not) {
  686. tool.error("'~' cannot be applied to (...)+ subrule", grammar.getFilename(), context().block.getLine());
  687. }
  688. // create the right kind of object now that we know what that is
  689. // and switch the list of alternatives.  Adjust the stack of blocks.
  690. // copy any init action also.
  691. ZeroOrMoreBlock b = new ZeroOrMoreBlock(grammar);
  692. setBlock(b,context().block);
  693. BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
  694. blocks.push(new BlockContext());
  695. context().block = b;
  696. context().blockEnd = old.blockEnd;
  697. context().blockEnd.block = b;
  698. }
  699. }