1 package antlr;
2
3 * <b>SOFTWARE RIGHTS</b>
5 * <p>
6 * ANTLR 2.5.0 MageLang Institute, 1998
7 * <p>
8 * We reserve no legal rights to the ANTLR--it is fully in the
9 * public domain. An individual or company may do whatever
10 * they wish with source code distributed with ANTLR or the
11 * code generated by ANTLR, including the incorporation of
12 * ANTLR, or its output, into commerical software.
13 * <p>
14 * We encourage users to develop software with ANTLR. However,
15 * we do ask that credit is given to us for developing
16 * ANTLR. By "credit", we mean that if you use ANTLR or
17 * incorporate any source code into one of your programs
18 * (commercial product, research project, or otherwise) that
19 * you acknowledge this fact somewhere in the documentation,
20 * research report, etc... If you like ANTLR and have
21 * developed a nice tool with the output, please mention that
22 * you developed it using ANTLR. In addition, we ask that the
23 * headers remain intact in our source code. As long as these
24 * guidelines are kept, we expect to continue enhancing this
25 * system and expect to make other tools available as they are
26 * completed.
27 * <p>
28 * The ANTLR gang:
29 * @version ANTLR 2.5.0 MageLang Institute, 1998
30 * @author Terence Parr, <a href=http://www.MageLang.com>MageLang Institute</a>
31 * @author <br>John Lilley, <a href=http://www.Empathy.com>Empathy Software</a>
32 */
33 import antlr.collections.Stack;
34 import antlr.collections.impl.LList;
35 import antlr.collections.impl.Vector;
36
37 public class MakeGrammar extends DefineGrammarSymbols {
38
39 protected Stack blocks = new LList(); protected RuleRefElement lastRuleRef;
41
42 protected RuleEndElement ruleEnd; protected RuleBlock ruleBlock; protected int nested = 0; protected boolean grammarError = false;
46
47 ExceptionSpec currentExceptionSpec = null;
48
49
50 public MakeGrammar(Tool tool_, String[] args_, LLkAnalyzer analyzer_) {
51 super(tool_, args_, analyzer_);
52 }
53
54 public void abortGrammar() {
55 String s = "unknown grammar";
56 if ( grammar!=null ) {
57 s = grammar.getClassName();
58 }
59 tool.error("aborting grammar '" + s + "' due to errors");
60 super.abortGrammar();
61 }
62 protected void addElementToCurrentAlt(AlternativeElement e) {
63 e.enclosingRuleName = ruleBlock.ruleName;
64 context().addAlternativeElement(e);
65 }
66 public void beginAlt(boolean doAutoGen_) {
67 super.beginAlt(doAutoGen_);
68 Alternative alt = new Alternative();
69 alt.setAutoGen(doAutoGen_);
70 context().block.addAlternative(alt);
71 }
72 public void beginChildList() {
73 super.beginChildList();
74 context().block.addAlternative(new Alternative());
75 }
76
77 public void beginExceptionGroup() {
78 super.beginExceptionGroup();
79 if (!(context().block instanceof RuleBlock))
80 {
81 tool.panic("beginExceptionGroup called outside of rule block");
82 }
83 }
84
85 public void beginExceptionSpec(Token label) {
86 if (label != null) {
88 label.setText( Tool.stripFront( Tool.stripBack(label.getText(), " \n\r\t"), " \n\r\t") );
89 }
90 super.beginExceptionSpec(label);
91 currentExceptionSpec = new ExceptionSpec(label);
94 }
95 public void beginSubRule(Token label, int line, boolean not) {
96 super.beginSubRule(label,line, not);
97 blocks.push(new BlockContext());
101 context().block = new AlternativeBlock(grammar, line, not);
102 context().altNum = 0; nested++;
104 context().blockEnd = new BlockEndElement(grammar);
107 context().blockEnd.block = context().block;
109 labelElement(context().block, label);
110 }
111 public void beginTree(int line) throws SemanticException {
112 if (!(grammar instanceof TreeWalkerGrammar)) {
113 tool.error("Trees only allowed in TreeParser", line);
114 throw new SemanticException("Trees only allowed in TreeParser");
115 }
116 super.beginTree(line);
117 blocks.push(new TreeBlockContext());
118 context().block = new TreeElement(grammar, line);
119 context().altNum = 0; }
121 public BlockContext context() {
122 if ( blocks.height()==0 ) {
123 return null;
124 }
125 else {
126 return (BlockContext)blocks.top();
127 }
128 }
129 * This builds a rule which has every "public" rule in the given Vector of
131 * rules as it's alternate. Each rule ref generates a Token object
132 * returned in _returnToken;
133 * @param g The Grammar that is being processed
134 * @param lexRules A vector of lexer rules that will be used to create an alternate block.
135 * @param rname The name of the resulting rule.
136 */
137 public static RuleBlock createNextTokenRule(Grammar g, Vector lexRules, String rname) {
138 RuleBlock rb = new RuleBlock(g, rname);
140 RuleEndElement ruleEnd = new RuleEndElement(g);
141 rb.setEndElement(ruleEnd);
142 ruleEnd.block = rb;
143 for (int i=0; i<lexRules.size(); i++) {
145 RuleSymbol r = (RuleSymbol)lexRules.elementAt(i);
146 if (!r.isDefined()) {
147 g.tool.error("Lexer rule " + r.id.substring(1) + " is not defined");
148 }
149 else {
150 if ( r.access.equals("public") ) {
151 RuleRefElement rr = new RuleRefElement(g, new CommonToken(r.getId()), GrammarElement.AUTO_GEN_NONE);
152 rr.setLabel("_rettoken");
155 rr.enclosingRuleName = "nextToken";
156 String aStr = "_token = _rettoken;";
158 ActionElement a = new ActionElement(g, new CommonToken(aStr));
159 rr.next = a;
160 a.next = ruleEnd;
161 */
162 rr.next = ruleEnd;
163 Alternative alt = new Alternative(rr);
164 alt.setAutoGen(true); rb.addAlternative(alt);
166 r.addReference(rr);
168 }
169 }
170 }
171
172 rb.setAutoGen(true);
174 // Create a reference to EOF
176 RuleRefElement rr = new RuleRefElement(g, new CommonToken("EOF"), GrammarElement.AUTO_GEN_NONE);
177 rr.setIdAssign("_ttype");
178 rr.next = ruleEnd;
179 rb.addAlternative(new Alternative(rr));
180 // Add a reference to the rule used for the alt
181 // r.addReference(rr);
182 */
183
184 rb.prepareForAnalysis();
185 return rb;
187 }
188
189 private AlternativeBlock createOptionalRuleRef(String rule, int line) {
190 AlternativeBlock blk = new AlternativeBlock(grammar, line, false);
192
193 if ( Character.isUpperCase(rule.charAt(0)) ) { rule = CodeGenerator.lexerRuleName(rule);
196 }
197 if ( !grammar.isDefined(rule) ) {
198 grammar.define(new RuleSymbol(rule));
199 }
200
201 RuleRefElement rref = new RuleRefElement(grammar, rule, line, GrammarElement.AUTO_GEN_NONE);
203 rref.enclosingRuleName = ruleBlock.ruleName;
204
205 BlockEndElement end = new BlockEndElement(grammar);
207 end.block = blk;
209 Alternative alt = new Alternative(rref);
211 alt.addElement(end);
213 blk.addAlternative(alt);
215
216 Alternative optAlt = new Alternative();
218 optAlt.addElement(end);
220 blk.addAlternative(optAlt);
221
222 blk.prepareForAnalysis();
223 return blk;
224 }
225 public void defineRuleName(Token r, String access, boolean ruleAutoGen, String docComment) throws SemanticException {
226 if ( Character.isUpperCase(r.getText().charAt(0)) ) {
227 if (!(grammar instanceof LexerGrammar)) {
228 tool.error("Lexical rule defined outside of lexer", r.getLine());
229 throw new SemanticException("Lexical rule defined outside of lexer");
230 }
231 }
232
233 super.defineRuleName(r, access, ruleAutoGen, docComment);
234 String id = r.getText();
235 if ( Character.isUpperCase(id.charAt(0)) ) { id = CodeGenerator.lexerRuleName(id);
237 }
238 RuleSymbol rs = (RuleSymbol) grammar.getSymbol(id);
239 RuleBlock rb = new RuleBlock(grammar, r.getText(), r.getLine(), ruleAutoGen);
240
241 rb.setDefaultErrorHandler(grammar.getDefaultErrorHandler());
243
244 ruleBlock = rb;
245 blocks.push(new BlockContext()); context().block = rb;
247 rs.setBlock(rb);
248 ruleEnd = new RuleEndElement(grammar);
249 rb.setEndElement(ruleEnd);
250 nested = 0;
251 }
252 public void endAlt() {
253 super.endAlt();
254 if ( nested==0 ) { addElementToCurrentAlt(ruleEnd);
256 }
257 else {
258 addElementToCurrentAlt(context().blockEnd);
259 }
260 context().altNum++;
261 }
262 public void endChildList() {
263 super.endChildList();
264 BlockEndElement be = new BlockEndElement(grammar);
269 be.block = context().block;
270 addElementToCurrentAlt(be);
271 }
272 public void endExceptionGroup() {
273 super.endExceptionGroup();
274 }
275 public void endExceptionSpec() {
276 super.endExceptionSpec();
277 if (currentExceptionSpec == null)
278 {
279 tool.panic("exception processing internal error -- no active exception spec");
280 }
281 if (context().block instanceof RuleBlock)
282 {
283 ((RuleBlock)context().block).addExceptionSpec(currentExceptionSpec);
285 } else {
286 if (context().currentAlt().exceptionSpec != null) {
288 tool.error("Alternative already has an exception specification", context().block.getLine());
289 }
290 else {
291 context().currentAlt().exceptionSpec = currentExceptionSpec;
292 }
293 }
294 currentExceptionSpec = null;
295 }
296
297 public void endGrammar() {
298 if (grammarError) {
299 abortGrammar();
300 }
301 else {
302 super.endGrammar();
303 }
304 }
305 public void endRule(String rule) {
306 super.endRule(rule);
307 BlockContext ctx = (BlockContext) blocks.pop(); ruleEnd.block = ctx.block;
310 ruleEnd.block.prepareForAnalysis();
311 }
313 public void endSubRule() {
314 super.endSubRule();
315 nested--;
316 BlockContext ctx = (BlockContext)blocks.pop();
318 AlternativeBlock block = ctx.block;
319
320 if (
323 block.not &&
324 !(block instanceof SynPredBlock) &&
325 !(block instanceof ZeroOrMoreBlock) &&
326 !(block instanceof OneOrMoreBlock)
327 )
328 {
329 if (!analyzer.subruleCanBeInverted(block, grammar instanceof LexerGrammar)) {
330 String newline = System.getProperty("line.separator");
331 tool.error(
332 "This subrule cannot be inverted. Only subrules of the form:"+newline +
333 " (T1|T2|T3...) or" + newline +
334 " ('c1'|'c2'|'c3'...)" + newline +
335 "may be inverted (ranges are also allowed).",
336 block.getLine()
337 );
338 }
339 }
340
341 if ( block instanceof SynPredBlock ) {
343 SynPredBlock synpred = (SynPredBlock)block;
346 context().block.hasASynPred = true;
347 context().currentAlt().synPred = synpred;
348 grammar.hasSyntacticPredicate = true;
349 synpred.removeTrackingOfRuleRefs(grammar);
350 }
351 else {
352 addElementToCurrentAlt(block);
353 }
354 ctx.blockEnd.block.prepareForAnalysis();
355 }
356 public void endTree() {
357 super.endTree();
358 BlockContext ctx = (BlockContext) blocks.pop();
359 addElementToCurrentAlt(ctx.block); }
361
362 public void hasError() {
363 grammarError = true;
364 }
365 private void labelElement(AlternativeElement el, Token label) {
366 if ( label != null ) {
367 for (int i = 0; i < ruleBlock.labeledElements.size(); i++) {
369 AlternativeElement altEl = (AlternativeElement)ruleBlock.labeledElements.elementAt(i);
370 String l = altEl.getLabel();
371 if (l != null && l.equals(label.getText())) {
372 tool.error("Label '" + label.getText() + "' has already been defined", label.getLine());
373 return;
374 }
375 }
376 el.setLabel(label.getText());
378 ruleBlock.labeledElements.appendElement(el);
379 }
380 }
381 public void noAutoGenSubRule() {
382 context().block.setAutoGen(false);
383 }
384 public void oneOrMoreSubRule() {
385 if (context().block.not) {
386 tool.error("'~' cannot be applied to (...)* subrule", context().block.getLine());
387 }
388 OneOrMoreBlock b = new OneOrMoreBlock(grammar);
392 setBlock(b,context().block);
393 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext());
395 context().block = b;
396 context().blockEnd = old.blockEnd;
397 context().blockEnd.block = b;
398 }
399 public void optionalSubRule() {
400 if (context().block.not) {
401 tool.error("'~' cannot be applied to (...)? subrule", context().block.getLine());
402 }
403 beginAlt(false);
406 endAlt();
407 }
408 public void refAction(Token action) {
409 super.refAction(action);
410 context().block.hasAnAction = true;
411 addElementToCurrentAlt(new ActionElement(grammar,action));
412 }
413 public void refArgAction(Token action) {
415 ((RuleBlock)context().block).argAction = action.getText();
416 }
417 public void refCharLiteral(Token lit, Token label, boolean inverted, int autoGenType, boolean lastInRule) {
418 if (!(grammar instanceof LexerGrammar)) {
419 tool.error("Character literal only valid in lexer", lit.getLine());
420 return;
421 }
422 super.refCharLiteral(lit, label, inverted, autoGenType, lastInRule);
423 CharLiteralElement cl = new CharLiteralElement((LexerGrammar)grammar, lit, inverted, autoGenType);
424
425 if (
427 !((LexerGrammar)grammar).caseSensitive && cl.tokenType < 128 &&
428 Character.toLowerCase((char)cl.tokenType) != (char)cl.tokenType
429 ) {
430 tool.warning("Character literal must be lowercase when caseSensitive=false", lit.getLine());
431 }
432
433 addElementToCurrentAlt(cl);
434 labelElement(cl, label);
435
436 String ignore = ruleBlock.getIgnoreRule();
438 if ( !lastInRule && ignore!=null ) {
439 addElementToCurrentAlt(createOptionalRuleRef(ignore, lit.getLine()));
440 }
441 }
442 public void refCharRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
443 if (!(grammar instanceof LexerGrammar)) {
444 tool.error("Character range only valid in lexer", t1.getLine());
445 return;
446 }
447 int rangeMin = ANTLRLexer.tokenTypeForCharLiteral(t1.getText());
448 int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(t2.getText());
449 if (rangeMax < rangeMin) {
450 tool.error("Malformed range.", t1.getLine());
451 return;
452 }
453
454 if (!((LexerGrammar)grammar).caseSensitive) {
456 if (rangeMin < 128 && Character.toLowerCase((char)rangeMin) != (char)rangeMin) {
457 tool.warning("Character literal must be lowercase when caseSensitive=false", t1.getLine());
458 }
459 if (rangeMax < 128 && Character.toLowerCase((char)rangeMax) != (char)rangeMax) {
460 tool.warning("Character literal must be lowercase when caseSensitive=false", t2.getLine());
461 }
462 }
463
464 super.refCharRange(t1, t2, label, autoGenType, lastInRule);
465 CharRangeElement cr = new CharRangeElement((LexerGrammar)grammar, t1, t2, autoGenType);
466 addElementToCurrentAlt(cr);
467 labelElement(cr, label);
468
469 String ignore = ruleBlock.getIgnoreRule();
471 if ( !lastInRule && ignore!=null ) {
472 addElementToCurrentAlt(createOptionalRuleRef(ignore, t1.getLine()));
473 }
474 }
475
476 public void refExceptionHandler(Token exTypeAndName, String action) {
477 super.refExceptionHandler(exTypeAndName, action);
478 if (currentExceptionSpec == null)
479 {
480 tool.panic("exception handler processing internal error");
481 }
482 currentExceptionSpec.addHandler(new ExceptionHandler(exTypeAndName, action));
483 }
484 public void refInitAction(Token action) {
485 super.refAction(action);
486 context().block.setInitAction(action.getText());
487 }
488 public void refMemberAction(Token act) {
489 grammar.classMemberAction = act.getText();
490 }
491 public void refPreambleAction(Token act) {
492 super.refPreambleAction(act);
493 }
494 public void refReturnAction(Token returnAction) {
496 if (grammar instanceof LexerGrammar) {
497 String name = CodeGenerator.lexerRuleName(((RuleBlock)context().block).getRuleName());
498 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(name);
499 if (rs.access.equals("public")) {
500 tool.warning("public Lexical rules cannot specify return type", returnAction.getLine());
501 return;
502 }
503 }
504 ((RuleBlock)context().block).returnAction = returnAction.getText();
505 }
506 public void refRule(Token idAssign, Token r, Token label, Token args, int autoGenType)
507 {
508 if (grammar instanceof LexerGrammar) {
510 if (!Character.isUpperCase(r.getText().charAt(0))) {
511 tool.error("Parser rule " + r.getText() + " referenced in lexer");
512 return;
513 }
514 if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
515 tool.error("AST specification ^ not allowed in lexer", r.getLine());
516 }
517 }
518
519 super.refRule(idAssign, r, label, args, autoGenType);
520 lastRuleRef = new RuleRefElement(grammar, r, autoGenType);
521 if (args != null)
522 {
523 lastRuleRef.setArgs(args.getText());
524 }
525 if (idAssign != null)
526 {
527 lastRuleRef.setIdAssign(idAssign.getText());
528 }
529 addElementToCurrentAlt(lastRuleRef);
530
531 String id = r.getText();
532 if ( Character.isUpperCase(id.charAt(0)) ) { id = CodeGenerator.lexerRuleName(id);
534 }
535 RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
537 rs.addReference(lastRuleRef);
538 labelElement(lastRuleRef, label);
539 }
540 public void refSemPred(Token pred) {
541 super.refSemPred(pred);
543 if ( context().currentAlt().atStart() ) {
545 context().currentAlt().semPred = pred.getText();
546 }
547 else {
548 ActionElement a = new ActionElement(grammar,pred);
549 a.isSemPred = true;
550 addElementToCurrentAlt(a);
551 }
552 }
554 public void refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule) {
555 super.refStringLiteral(lit, label, autoGenType, lastInRule);
556 if (grammar instanceof TreeWalkerGrammar && autoGenType == GrammarElement.AUTO_GEN_CARET) {
557 tool.error("^ not allowed in here for tree-walker", lit.getLine());
558 }
559 StringLiteralElement sl = new StringLiteralElement(grammar, lit, autoGenType);
560
561 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", lit.getLine());
567 break;
568 }
569 }
570 }
571
572 addElementToCurrentAlt(sl);
573 labelElement(sl, label);
574
575 String ignore = ruleBlock.getIgnoreRule();
577 if ( !lastInRule && ignore!=null ) {
578 addElementToCurrentAlt(createOptionalRuleRef(ignore, lit.getLine()));
579 }
580 }
581 public void refToken(Token idAssign, Token t, Token label, Token args,
582 boolean inverted, int autoGenType, boolean lastInRule) {
583 if (grammar instanceof LexerGrammar) {
584 if (label != null) {
587 tool.warning("label on token reference in lexer was ignored", t.getLine());
588 }
589 */
590 if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
591 tool.error("AST specification ^ not allowed in lexer", t.getLine());
592 }
593 if (inverted) {
594 tool.error("~TOKEN is not allowed in lexer", t.getLine());
595 }
596 refRule(idAssign, t, label, args, autoGenType);
597
598 String ignore = ruleBlock.getIgnoreRule();
600 if ( !lastInRule && ignore!=null ) {
601 addElementToCurrentAlt(createOptionalRuleRef(ignore, t.getLine()));
602 }
603 } else {
604 if (idAssign!= null)
606 {
607 tool.error("Assignment from token reference only allowed in lexer", idAssign.getLine());
608 }
609 if (args != null)
610 {
611 tool.error("Token reference arguments only allowed in lexer", args.getLine());
612 }
613 super.refToken(idAssign, t, label, args, inverted, autoGenType, lastInRule);
614 TokenRefElement te = new TokenRefElement(grammar, t, inverted, autoGenType);
615 addElementToCurrentAlt(te);
616 labelElement(te, label);
617 }
618 }
619 public void refTokenRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
620 if (grammar instanceof LexerGrammar) {
621 tool.error("Token range not allowed in lexer", t1.getLine());
622 return;
623 }
624 TokenRangeElement tr = new TokenRangeElement(grammar, t1, t2, autoGenType);
625 if (tr.end < tr.begin) {
626 tool.error("Malformed range.", t1.getLine());
627 return;
628 }
629 super.refTokenRange(t1, t2, label, autoGenType, lastInRule);
630 addElementToCurrentAlt(tr);
631 labelElement(tr, label);
632 }
633 public void refTreeSpecifier(Token treeSpec) {
634 context().currentAlt().treeSpecifier = treeSpec;
635 }
636 public void refWildcard(Token t, Token label, int autoGenType) {
637 super.refWildcard(t, label, autoGenType);
638 WildcardElement wc = new WildcardElement(grammar, t, autoGenType);
639 addElementToCurrentAlt(wc);
640 labelElement(wc, label);
641 }
642
643 public void reset() {
644 super.reset();
645 blocks = new LList();
646 lastRuleRef = null;
647 ruleEnd = null;
648 ruleBlock = null;
649 nested = 0;
650 currentExceptionSpec = null;
651 grammarError = false;
652 }
653 public void setArgOfRuleRef(Token argAction) {
654 super.setArgOfRuleRef(argAction);
655 lastRuleRef.setArgs(argAction.getText());
656 }
657 public static void setBlock(AlternativeBlock b, AlternativeBlock src) {
658 b.setAlternatives(src.getAlternatives());
659 b.initAction = src.initAction;
660 b.label = src.label;
662 b.hasASynPred = src.hasASynPred;
663 b.hasAnAction = src.hasAnAction;
664 b.warnWhenFollowAmbig = src.warnWhenFollowAmbig;
665 b.generateAmbigWarnings = src.generateAmbigWarnings;
666 b.line = src.line;
667 }
668 public void setRuleOption(Token key, Token value) {
669 ruleBlock.setOption(key, value);
671 }
672 public void setSubruleOption(Token key, Token value) {
673 ((AlternativeBlock)context().block).setOption(key, value);
674 }
675 public void synPred() {
676 if (context().block.not) {
677 tool.error("'~' cannot be applied to syntactc predicate", context().block.getLine());
678 }
679 SynPredBlock b = new SynPredBlock(grammar);
683 setBlock(b,context().block);
684 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext());
686 context().block = b;
687 context().blockEnd = old.blockEnd;
688 context().blockEnd.block = b;
689 }
690 public void zeroOrMoreSubRule() {
691 if (context().block.not) {
692 tool.error("'~' cannot be applied to (...)+ subrule", context().block.getLine());
693 }
694 ZeroOrMoreBlock b = new ZeroOrMoreBlock(grammar);
698 setBlock(b,context().block);
699 BlockContext old = (BlockContext)blocks.pop(); blocks.push(new BlockContext());
701 context().block = b;
702 context().blockEnd = old.blockEnd;
703 context().blockEnd.block = b;
704 }
705 }
706