1 package antlr; 2 3 9 10 import antlr.collections.Stack; 11 import antlr.collections.impl.LList; 12 import antlr.collections.impl.Vector; 13 14 public class MakeGrammar extends DefineGrammarSymbols { 15 16 protected Stack blocks = new LList(); protected RuleRefElement lastRuleRef; 18 19 protected RuleEndElement ruleEnd; protected RuleBlock ruleBlock; protected int nested = 0; protected boolean grammarError = false; 23 24 ExceptionSpec currentExceptionSpec = null; 25 26 public MakeGrammar(Tool tool_, String [] args_, LLkAnalyzer analyzer_) { 27 super(tool_, args_, analyzer_); 28 } 29 30 31 public void abortGrammar() { 32 String s = "unknown grammar"; 33 if (grammar != null) { 34 s = grammar.getClassName(); 35 } 36 tool.error("aborting grammar '" + s + "' due to errors"); 37 super.abortGrammar(); 38 } 39 40 protected void addElementToCurrentAlt(AlternativeElement e) { 41 e.enclosingRuleName = ruleBlock.ruleName; 42 context().addAlternativeElement(e); 43 } 44 45 public void beginAlt(boolean doAutoGen_) { 46 super.beginAlt(doAutoGen_); 47 Alternative alt = new Alternative(); 48 alt.setAutoGen(doAutoGen_); 49 context().block.addAlternative(alt); 50 } 51 52 public void beginChildList() { 53 super.beginChildList(); 54 context().block.addAlternative(new Alternative()); 55 } 56 57 58 public void beginExceptionGroup() { 59 super.beginExceptionGroup(); 60 if (!(context().block instanceof RuleBlock)) { 61 tool.panic("beginExceptionGroup called outside of rule block"); 62 } 63 } 64 65 66 public void beginExceptionSpec(Token label) { 67 if (label != null) { 69 label.setText(StringUtils.stripFront(StringUtils.stripBack(label.getText(), " \n\r\t"), " \n\r\t")); 70 } 71 super.beginExceptionSpec(label); 72 currentExceptionSpec = new ExceptionSpec(label); 75 } 76 77 public void beginSubRule(Token label, Token start, boolean not) { 78 super.beginSubRule(label, start, not); 79 blocks.push(new BlockContext()); 83 context().block = new AlternativeBlock(grammar, start, not); 84 context().altNum = 0; nested++; 86 context().blockEnd = new BlockEndElement(grammar); 89 context().blockEnd.block = context().block; 91 labelElement(context().block, label); 92 } 93 94 public void beginTree(Token tok) throws SemanticException { 95 if (!(grammar instanceof TreeWalkerGrammar)) { 96 tool.error("Trees only allowed in TreeParser", grammar.getFilename(), tok.getLine(), tok.getColumn()); 97 throw new SemanticException("Trees only allowed in TreeParser"); 98 } 99 super.beginTree(tok); 100 blocks.push(new TreeBlockContext()); 101 context().block = new TreeElement(grammar, tok); 102 context().altNum = 0; } 104 105 public BlockContext context() { 106 if (blocks.height() == 0) { 107 return null; 108 } 109 else { 110 return (BlockContext)blocks.top(); 111 } 112 } 113 114 121 public static RuleBlock createNextTokenRule(Grammar g, Vector lexRules, String rname) { 122 RuleBlock rb = new RuleBlock(g, rname); 124 rb.setDefaultErrorHandler(g.getDefaultErrorHandler()); 125 RuleEndElement ruleEnd = new RuleEndElement(g); 126 rb.setEndElement(ruleEnd); 127 ruleEnd.block = rb; 128 for (int i = 0; i < lexRules.size(); i++) { 130 RuleSymbol r = (RuleSymbol)lexRules.elementAt(i); 131 if (!r.isDefined()) { 132 g.antlrTool.error("Lexer rule " + r.id.substring(1) + " is not defined"); 133 } 134 else { 135 if (r.access.equals("public")) { 136 RuleRefElement rr = 140 new RuleRefElement(g, 141 new CommonToken(ANTLRTokenTypes.RULE_REF, r.getId()), 142 GrammarElement.AUTO_GEN_NONE); 143 rr.setLabel("theRetToken"); 146 rr.enclosingRuleName = "nextToken"; 147 rr.next = ruleEnd; 148 Alternative alt = new Alternative(rr); 149 alt.setAutoGen(true); rb.addAlternative(alt); 151 r.addReference(rr); 153 } 154 } 155 } 156 157 rb.setAutoGen(true); rb.prepareForAnalysis(); 159 return rb; 161 } 162 163 164 private AlternativeBlock createOptionalRuleRef(String rule, Token start) { 165 AlternativeBlock blk = new AlternativeBlock(grammar, start, false); 167 168 String mrule = CodeGenerator.encodeLexerRuleName(rule); if (!grammar.isDefined(mrule)) { 171 grammar.define(new RuleSymbol(mrule)); 172 } 173 174 Token t = new CommonToken(ANTLRTokenTypes.TOKEN_REF, rule); 177 t.setLine(start.getLine()); 178 t.setLine(start.getColumn()); 179 RuleRefElement rref = 180 new RuleRefElement(grammar, t, GrammarElement.AUTO_GEN_NONE); 181 182 rref.enclosingRuleName = ruleBlock.ruleName; 183 184 BlockEndElement end = new BlockEndElement(grammar); 186 end.block = blk; 188 Alternative alt = new Alternative(rref); 190 alt.addElement(end); 192 blk.addAlternative(alt); 194 195 Alternative optAlt = new Alternative(); 197 optAlt.addElement(end); 199 blk.addAlternative(optAlt); 200 201 blk.prepareForAnalysis(); 202 return blk; 203 } 204 205 public void defineRuleName(Token r, 206 String access, 207 boolean ruleAutoGen, 208 String docComment) 209 throws SemanticException { 210 if (r.type == ANTLRTokenTypes.TOKEN_REF) { 212 if (!(grammar instanceof LexerGrammar)) { 213 tool.error("Lexical rule " + r.getText() + 214 " defined outside of lexer", 215 grammar.getFilename(), r.getLine(), r.getColumn()); 216 r.setText(r.getText().toLowerCase()); 217 } 218 } 219 else { 220 if (grammar instanceof LexerGrammar) { 221 tool.error("Lexical rule names must be upper case, '" + r.getText() + 222 "' is not", 223 grammar.getFilename(), r.getLine(), r.getColumn()); 224 r.setText(r.getText().toUpperCase()); 225 } 226 } 227 228 super.defineRuleName(r, access, ruleAutoGen, docComment); 229 String id = r.getText(); 230 if (r.type == ANTLRTokenTypes.TOKEN_REF) { id = CodeGenerator.encodeLexerRuleName(id); 233 } 234 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id); 235 RuleBlock rb = new RuleBlock(grammar, r.getText(), r.getLine(), ruleAutoGen); 236 237 rb.setDefaultErrorHandler(grammar.getDefaultErrorHandler()); 239 240 ruleBlock = rb; 241 blocks.push(new BlockContext()); context().block = rb; 243 rs.setBlock(rb); 244 ruleEnd = new RuleEndElement(grammar); 245 rb.setEndElement(ruleEnd); 246 nested = 0; 247 } 248 249 public void endAlt() { 250 super.endAlt(); 251 if (nested == 0) { addElementToCurrentAlt(ruleEnd); 253 } 254 else { 255 addElementToCurrentAlt(context().blockEnd); 256 } 257 context().altNum++; 258 } 259 260 public void endChildList() { 261 super.endChildList(); 262 BlockEndElement be = new BlockEndElement(grammar); 267 be.block = context().block; 268 addElementToCurrentAlt(be); 269 } 270 271 public void endExceptionGroup() { 272 super.endExceptionGroup(); 273 } 274 275 public void endExceptionSpec() { 276 super.endExceptionSpec(); 277 if (currentExceptionSpec == null) { 278 tool.panic("exception processing internal error -- no active exception spec"); 279 } 280 if (context().block instanceof RuleBlock) { 281 ((RuleBlock)context().block).addExceptionSpec(currentExceptionSpec); 283 } 284 else { 285 if (context().currentAlt().exceptionSpec != null) { 287 tool.error("Alternative already has an exception specification", grammar.getFilename(), context().block.getLine(), context().block.getColumn()); 288 } 289 else { 290 context().currentAlt().exceptionSpec = currentExceptionSpec; 291 } 292 } 293 currentExceptionSpec = null; 294 } 295 296 297 public void endGrammar() { 298 if (grammarError) { 299 abortGrammar(); 300 } 301 else { 302 super.endGrammar(); 303 } 304 } 305 306 public void endRule(String rule) { 307 super.endRule(rule); 308 BlockContext ctx = (BlockContext)blocks.pop(); ruleEnd.block = ctx.block; 311 ruleEnd.block.prepareForAnalysis(); 312 } 314 315 public void endSubRule() { 316 super.endSubRule(); 317 nested--; 318 BlockContext ctx = (BlockContext)blocks.pop(); 320 AlternativeBlock block = ctx.block; 321 322 if ( 325 block.not && 326 !(block instanceof SynPredBlock) && 327 !(block instanceof ZeroOrMoreBlock) && 328 !(block instanceof OneOrMoreBlock) 329 ) { 330 if (!analyzer.subruleCanBeInverted(block, grammar instanceof LexerGrammar)) { 331 String newline = System.getProperty("line.separator"); 332 tool.error( 333 "This subrule cannot be inverted. Only subrules of the form:" + newline + 334 " (T1|T2|T3...) or" + newline + 335 " ('c1'|'c2'|'c3'...)" + newline + 336 "may be inverted (ranges are also allowed).", 337 grammar.getFilename(), 338 block.getLine(), block.getColumn() 339 ); 340 } 341 } 342 343 if (block instanceof SynPredBlock) { 345 SynPredBlock synpred = (SynPredBlock)block; 348 context().block.hasASynPred = true; 349 context().currentAlt().synPred = synpred; 350 grammar.hasSyntacticPredicate = true; 351 synpred.removeTrackingOfRuleRefs(grammar); 352 } 353 else { 354 addElementToCurrentAlt(block); 355 } 356 ctx.blockEnd.block.prepareForAnalysis(); 357 } 358 359 public void endTree() { 360 super.endTree(); 361 BlockContext ctx = (BlockContext)blocks.pop(); 362 addElementToCurrentAlt(ctx.block); } 364 365 366 public void hasError() { 367 grammarError = true; 368 } 369 370 private void labelElement(AlternativeElement el, Token label) { 371 if (label != null) { 372 for (int i = 0; i < ruleBlock.labeledElements.size(); i++) { 374 AlternativeElement altEl = (AlternativeElement)ruleBlock.labeledElements.elementAt(i); 375 String l = altEl.getLabel(); 376 if (l != null && l.equals(label.getText())) { 377 tool.error("Label '" + label.getText() + "' has already been defined", grammar.getFilename(), label.getLine(), label.getColumn()); 378 return; 379 } 380 } 381 el.setLabel(label.getText()); 383 ruleBlock.labeledElements.appendElement(el); 384 } 385 } 386 387 public void noAutoGenSubRule() { 388 context().block.setAutoGen(false); 389 } 390 391 public void oneOrMoreSubRule() { 392 if (context().block.not) { 393 tool.error("'~' cannot be applied to (...)* subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn()); 394 } 395 OneOrMoreBlock b = new OneOrMoreBlock(grammar); 399 setBlock(b, context().block); 400 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext()); 402 context().block = b; 403 context().blockEnd = old.blockEnd; 404 context().blockEnd.block = b; 405 } 406 407 public void optionalSubRule() { 408 if (context().block.not) { 409 tool.error("'~' cannot be applied to (...)? subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn()); 410 } 411 beginAlt(false); 414 endAlt(); 415 } 416 417 public void refAction(Token action) { 418 super.refAction(action); 419 context().block.hasAnAction = true; 420 addElementToCurrentAlt(new ActionElement(grammar, action)); 421 } 422 423 public void setUserExceptions(String thr) { 424 ((RuleBlock)context().block).throwsSpec = thr; 425 } 426 427 public void refArgAction(Token action) { 429 ((RuleBlock)context().block).argAction = action.getText(); 430 } 431 432 public void refCharLiteral(Token lit, Token label, boolean inverted, int autoGenType, boolean lastInRule) { 433 if (!(grammar instanceof LexerGrammar)) { 434 tool.error("Character literal only valid in lexer", grammar.getFilename(), lit.getLine(), lit.getColumn()); 435 return; 436 } 437 super.refCharLiteral(lit, label, inverted, autoGenType, lastInRule); 438 CharLiteralElement cl = new CharLiteralElement((LexerGrammar)grammar, lit, inverted, autoGenType); 439 440 if ( 442 !((LexerGrammar)grammar).caseSensitive && cl.getType() < 128 && 443 Character.toLowerCase((char)cl.getType()) != (char)cl.getType() 444 ) { 445 tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn()); 446 } 447 448 addElementToCurrentAlt(cl); 449 labelElement(cl, label); 450 451 String ignore = ruleBlock.getIgnoreRule(); 453 if (!lastInRule && ignore != null) { 454 addElementToCurrentAlt(createOptionalRuleRef(ignore, lit)); 455 } 456 } 457 458 public void refCharRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) { 459 if (!(grammar instanceof LexerGrammar)) { 460 tool.error("Character range only valid in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn()); 461 return; 462 } 463 int rangeMin = ANTLRLexer.tokenTypeForCharLiteral(t1.getText()); 464 int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(t2.getText()); 465 if (rangeMax < rangeMin) { 466 tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn()); 467 return; 468 } 469 470 if (!((LexerGrammar)grammar).caseSensitive) { 472 if (rangeMin < 128 && Character.toLowerCase((char)rangeMin) != (char)rangeMin) { 473 tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t1.getLine(), t1.getColumn()); 474 } 475 if (rangeMax < 128 && Character.toLowerCase((char)rangeMax) != (char)rangeMax) { 476 tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t2.getLine(), t2.getColumn()); 477 } 478 } 479 480 super.refCharRange(t1, t2, label, autoGenType, lastInRule); 481 CharRangeElement cr = new CharRangeElement((LexerGrammar)grammar, t1, t2, autoGenType); 482 addElementToCurrentAlt(cr); 483 labelElement(cr, label); 484 485 String ignore = ruleBlock.getIgnoreRule(); 487 if (!lastInRule && ignore != null) { 488 addElementToCurrentAlt(createOptionalRuleRef(ignore, t1)); 489 } 490 } 491 492 public void refTokensSpecElementOption(Token tok, 493 Token option, 494 Token value) { 495 499 TokenSymbol ts = (TokenSymbol) 500 grammar.tokenManager.getTokenSymbol(tok.getText()); 501 if (ts == null) { 502 tool.panic("cannot find " + tok.getText() + "in tokens {...}"); 503 } 504 if (option.getText().equals("AST")) { 505 ts.setASTNodeType(value.getText()); 506 } 507 else { 508 grammar.antlrTool.error("invalid tokens {...} element option:" + 509 option.getText(), 510 grammar.getFilename(), 511 option.getLine(), option.getColumn()); 512 } 513 } 514 515 public void refElementOption(Token option, Token value) { 516 520 AlternativeElement e = context().currentElement(); 521 if (e instanceof StringLiteralElement || 522 e instanceof TokenRefElement || 523 e instanceof WildcardElement) { 524 ((GrammarAtom)e).setOption(option, value); 525 } 526 else { 527 tool.error("cannot use element option (" + option.getText() + 528 ") for this kind of element", 529 grammar.getFilename(), option.getLine(), option.getColumn()); 530 } 531 } 532 533 534 public void refExceptionHandler(Token exTypeAndName, Token action) { 535 super.refExceptionHandler(exTypeAndName, action); 536 if (currentExceptionSpec == null) { 537 tool.panic("exception handler processing internal error"); 538 } 539 currentExceptionSpec.addHandler(new ExceptionHandler(exTypeAndName, action)); 540 } 541 542 public void refInitAction(Token action) { 543 super.refAction(action); 544 context().block.setInitAction(action.getText()); 545 } 546 547 public void refMemberAction(Token act) { 548 grammar.classMemberAction = act; 549 } 550 551 public void refPreambleAction(Token act) { 552 super.refPreambleAction(act); 553 } 554 555 public void refReturnAction(Token returnAction) { 557 if (grammar instanceof LexerGrammar) { 558 String name = CodeGenerator.encodeLexerRuleName(((RuleBlock)context().block).getRuleName()); 559 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(name); 560 if (rs.access.equals("public")) { 561 tool.warning("public Lexical rules cannot specify return type", grammar.getFilename(), returnAction.getLine(), returnAction.getColumn()); 562 return; 563 } 564 } 565 ((RuleBlock)context().block).returnAction = returnAction.getText(); 566 } 567 568 public void refRule(Token idAssign, 569 Token r, 570 Token label, 571 Token args, 572 int autoGenType) { 573 if (grammar instanceof LexerGrammar) { 575 if (r.type != ANTLRTokenTypes.TOKEN_REF) { 577 tool.error("Parser rule " + r.getText() + " referenced in lexer"); 578 return; 579 } 580 if (autoGenType == GrammarElement.AUTO_GEN_CARET) { 581 tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), r.getLine(), r.getColumn()); 582 } 583 } 584 585 super.refRule(idAssign, r, label, args, autoGenType); 586 lastRuleRef = new RuleRefElement(grammar, r, autoGenType); 587 if (args != null) { 588 lastRuleRef.setArgs(args.getText()); 589 } 590 if (idAssign != null) { 591 lastRuleRef.setIdAssign(idAssign.getText()); 592 } 593 addElementToCurrentAlt(lastRuleRef); 594 595 String id = r.getText(); 596 if (r.type == ANTLRTokenTypes.TOKEN_REF) { id = CodeGenerator.encodeLexerRuleName(id); 599 } 600 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id); 602 rs.addReference(lastRuleRef); 603 labelElement(lastRuleRef, label); 604 } 605 606 public void refSemPred(Token pred) { 607 super.refSemPred(pred); 609 if (context().currentAlt().atStart()) { 611 context().currentAlt().semPred = pred.getText(); 612 } 613 else { 614 ActionElement a = new ActionElement(grammar, pred); 615 a.isSemPred = true; 616 addElementToCurrentAlt(a); 617 } 618 } 620 621 public void refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule) { 622 super.refStringLiteral(lit, label, autoGenType, lastInRule); 623 if (grammar instanceof TreeWalkerGrammar && autoGenType == GrammarElement.AUTO_GEN_CARET) { 624 tool.error("^ not allowed in here for tree-walker", grammar.getFilename(), lit.getLine(), lit.getColumn()); 625 } 626 StringLiteralElement sl = new StringLiteralElement(grammar, lit, autoGenType); 627 628 if (grammar instanceof LexerGrammar && !((LexerGrammar)grammar).caseSensitive) { 630 for (int i = 1; i < lit.getText().length() - 1; i++) { 631 char c = lit.getText().charAt(i); 632 if (c < 128 && Character.toLowerCase(c) != c) { 633 tool.warning("Characters of string literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn()); 634 break; 635 } 636 } 637 } 638 639 addElementToCurrentAlt(sl); 640 labelElement(sl, label); 641 642 String ignore = ruleBlock.getIgnoreRule(); 644 if (!lastInRule && ignore != null) { 645 addElementToCurrentAlt(createOptionalRuleRef(ignore, lit)); 646 } 647 } 648 649 public void refToken(Token idAssign, Token t, Token label, Token args, 650 boolean inverted, int autoGenType, boolean lastInRule) { 651 if (grammar instanceof LexerGrammar) { 652 if (autoGenType == GrammarElement.AUTO_GEN_CARET) { 654 tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn()); 655 } 656 if (inverted) { 657 tool.error("~TOKEN is not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn()); 658 } 659 refRule(idAssign, t, label, args, autoGenType); 660 661 String ignore = ruleBlock.getIgnoreRule(); 663 if (!lastInRule && ignore != null) { 664 addElementToCurrentAlt(createOptionalRuleRef(ignore, t)); 665 } 666 } 667 else { 668 if (idAssign != null) { 670 tool.error("Assignment from token reference only allowed in lexer", grammar.getFilename(), idAssign.getLine(), idAssign.getColumn()); 671 } 672 if (args != null) { 673 tool.error("Token reference arguments only allowed in lexer", grammar.getFilename(), args.getLine(), args.getColumn()); 674 } 675 super.refToken(idAssign, t, label, args, inverted, autoGenType, lastInRule); 676 TokenRefElement te = new TokenRefElement(grammar, t, inverted, autoGenType); 677 addElementToCurrentAlt(te); 678 labelElement(te, label); 679 } 680 } 681 682 public void refTokenRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) { 683 if (grammar instanceof LexerGrammar) { 684 tool.error("Token range not allowed in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn()); 685 return; 686 } 687 super.refTokenRange(t1, t2, label, autoGenType, lastInRule); 688 TokenRangeElement tr = new TokenRangeElement(grammar, t1, t2, autoGenType); 689 if (tr.end < tr.begin) { 690 tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn()); 691 return; 692 } 693 addElementToCurrentAlt(tr); 694 labelElement(tr, label); 695 } 696 697 public void refTreeSpecifier(Token treeSpec) { 698 context().currentAlt().treeSpecifier = treeSpec; 699 } 700 701 public void refWildcard(Token t, Token label, int autoGenType) { 702 super.refWildcard(t, label, autoGenType); 703 WildcardElement wc = new WildcardElement(grammar, t, autoGenType); 704 addElementToCurrentAlt(wc); 705 labelElement(wc, label); 706 } 707 708 709 public void reset() { 710 super.reset(); 711 blocks = new LList(); 712 lastRuleRef = null; 713 ruleEnd = null; 714 ruleBlock = null; 715 nested = 0; 716 currentExceptionSpec = null; 717 grammarError = false; 718 } 719 720 public void setArgOfRuleRef(Token argAction) { 721 super.setArgOfRuleRef(argAction); 722 lastRuleRef.setArgs(argAction.getText()); 723 } 724 725 public static void setBlock(AlternativeBlock b, AlternativeBlock src) { 726 b.setAlternatives(src.getAlternatives()); 727 b.initAction = src.initAction; 728 b.label = src.label; 730 b.hasASynPred = src.hasASynPred; 731 b.hasAnAction = src.hasAnAction; 732 b.warnWhenFollowAmbig = src.warnWhenFollowAmbig; 733 b.generateAmbigWarnings = src.generateAmbigWarnings; 734 b.line = src.line; 735 b.greedy = src.greedy; 736 b.greedySet = src.greedySet; 737 } 738 739 public void setRuleOption(Token key, Token value) { 740 ruleBlock.setOption(key, value); 742 } 743 744 public void setSubruleOption(Token key, Token value) { 745 ((AlternativeBlock)context().block).setOption(key, value); 746 } 747 748 public void synPred() { 749 if (context().block.not) { 750 tool.error("'~' cannot be applied to syntactic predicate", grammar.getFilename(), context().block.getLine(), context().block.getColumn()); 751 } 752 SynPredBlock b = new SynPredBlock(grammar); 756 setBlock(b, context().block); 757 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext()); 759 context().block = b; 760 context().blockEnd = old.blockEnd; 761 context().blockEnd.block = b; 762 } 763 764 public void zeroOrMoreSubRule() { 765 if (context().block.not) { 766 tool.error("'~' cannot be applied to (...)+ subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn()); 767 } 768 ZeroOrMoreBlock b = new ZeroOrMoreBlock(grammar); 772 setBlock(b, context().block); 773 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext()); 775 context().block = b; 776 context().blockEnd = old.blockEnd; 777 context().blockEnd.block = b; 778 } 779 } 780 | Popular Tags |