KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > persistence > antlr > MakeGrammar


1 package persistence.antlr;
2
3 /* ANTLR Translator Generator
4  * Project led by Terence Parr at http://www.jGuru.com
5  * Software rights: http://www.antlr.org/license.html
6  *
7  */

8
9 import persistence.antlr.collections.Stack;
10 import persistence.antlr.collections.impl.LList;
11 import persistence.antlr.collections.impl.Vector;
12
13 public class MakeGrammar extends DefineGrammarSymbols {
14
15     protected Stack blocks = new LList(); // track subrules--Stack<BlockContext>
16
protected RuleRefElement lastRuleRef;
17
18     protected RuleEndElement ruleEnd; // used if not nested
19
protected RuleBlock ruleBlock; // points to block of current rule.
20
protected int nested = 0; // nesting inside a subrule
21
protected boolean grammarError = false;
22
23     ExceptionSpec currentExceptionSpec = null;
24
25     public MakeGrammar(Tool tool_, String JavaDoc[] args_, LLkAnalyzer analyzer_) {
26         super(tool_, args_, analyzer_);
27     }
28
29     /** Abort the processing of a grammar (due to syntax errors) */
30     public void abortGrammar() {
31         String JavaDoc s = "unknown grammar";
32         if (grammar != null) {
33             s = grammar.getClassName();
34         }
35         tool.error("aborting grammar '" + s + "' due to errors");
36         super.abortGrammar();
37     }
38
39     protected void addElementToCurrentAlt(AlternativeElement e) {
40         e.enclosingRuleName = ruleBlock.ruleName;
41         context().addAlternativeElement(e);
42     }
43
44     public void beginAlt(boolean doAutoGen_) {
45         super.beginAlt(doAutoGen_);
46         Alternative alt = new Alternative();
47         alt.setAutoGen(doAutoGen_);
48         context().block.addAlternative(alt);
49     }
50
51     public void beginChildList() {
52         super.beginChildList();
53         context().block.addAlternative(new Alternative());
54     }
55
56     /** Add an exception group to a rule (currently a no-op) */
57     public void beginExceptionGroup() {
58         super.beginExceptionGroup();
59         if (!(context().block instanceof RuleBlock)) {
60             tool.panic("beginExceptionGroup called outside of rule block");
61         }
62     }
63
64     /** Add an exception spec to an exception group or rule block */
65     public void beginExceptionSpec(Token label) {
66         // Hack the label string a bit to remove leading/trailing space.
67
if (label != null) {
68             label.setText(StringUtils.stripFront(StringUtils.stripBack(label.getText(), " \n\r\t"), " \n\r\t"));
69         }
70         super.beginExceptionSpec(label);
71         // Don't check for currentExceptionSpec!=null because syntax errors
72
// may leave it set to something.
73
currentExceptionSpec = new ExceptionSpec(label);
74     }
75
76     public void beginSubRule(Token label, Token start, boolean not) {
77         super.beginSubRule(label, start, not);
78         // we don't know what kind of subrule it is yet.
79
// push a dummy one that will allow us to collect the
80
// alternatives. Later, we'll switch to real object.
81
blocks.push(new BlockContext());
82         context().block = new AlternativeBlock(grammar, start, not);
83         context().altNum = 0; // reset alternative number
84
nested++;
85         // create a final node to which the last elememt of each
86
// alternative will point.
87
context().blockEnd = new BlockEndElement(grammar);
88         // make sure end node points to start of block
89
context().blockEnd.block = context().block;
90         labelElement(context().block, label);
91     }
92
93     public void beginTree(Token tok) throws SemanticException {
94         if (!(grammar instanceof TreeWalkerGrammar)) {
95             tool.error("Trees only allowed in TreeParser", grammar.getFilename(), tok.getLine(), tok.getColumn());
96             throw new SemanticException("Trees only allowed in TreeParser");
97         }
98         super.beginTree(tok);
99         blocks.push(new TreeBlockContext());
100         context().block = new TreeElement(grammar, tok);
101         context().altNum = 0; // reset alternative number
102
}
103
104     public BlockContext context() {
105         if (blocks.height() == 0) {
106             return null;
107         }
108         else {
109             return (BlockContext)blocks.top();
110         }
111     }
112
113     /**Used to build nextToken() for the lexer.
114      * This builds a rule which has every "public" rule in the given Vector of
115      * rules as it's alternate. Each rule ref generates a Token object.
116      * @param g The Grammar that is being processed
117      * @param lexRules A vector of lexer rules that will be used to create an alternate block.
118      * @param rname The name of the resulting rule.
119      */

120     public static RuleBlock createNextTokenRule(Grammar g, Vector lexRules, String JavaDoc rname) {
121         // create actual rule data structure
122
RuleBlock rb = new RuleBlock(g, rname);
123         rb.setDefaultErrorHandler(g.getDefaultErrorHandler());
124         RuleEndElement ruleEnd = new RuleEndElement(g);
125         rb.setEndElement(ruleEnd);
126         ruleEnd.block = rb;
127         // Add an alternative for each element of the rules vector.
128
for (int i = 0; i < lexRules.size(); i++) {
129             RuleSymbol r = (RuleSymbol)lexRules.elementAt(i);
130             if (!r.isDefined()) {
131                 g.antlrTool.error("Lexer rule " + r.id.substring(1) + " is not defined");
132             }
133             else {
134                 if (r.access.equals("public")) {
135                     Alternative alt = new Alternative(); // create alt we'll add to ref rule
136
RuleBlock targetRuleBlock = r.getBlock();
137                     Vector targetRuleAlts = targetRuleBlock.getAlternatives();
138                     // collect a sem pred if only one alt and it's at the start;
139
// simple, but faster to implement until real hoisting
140
if ( targetRuleAlts!=null && targetRuleAlts.size()==1 ) {
141                         Alternative onlyAlt = (Alternative)targetRuleAlts.elementAt(0);
142                         if ( onlyAlt.semPred!=null ) {
143                             // ok, has sem pred, make this rule ref alt have a pred
144
alt.semPred = onlyAlt.semPred;
145                             // REMOVE predicate from target rule??? NOPE, another
146
// rule other than nextToken() might invoke it.
147
}
148                     }
149
150                     // create a rule ref to lexer rule
151
// the Token is a RULE_REF not a TOKEN_REF since the
152
// conversion to mRulename has already taken place
153
RuleRefElement rr =
154                         new RuleRefElement(g,
155                                            new CommonToken(ANTLRTokenTypes.RULE_REF, r.getId()),
156                                            GrammarElement.AUTO_GEN_NONE);
157                     rr.setLabel("theRetToken");
158                     rr.enclosingRuleName = "nextToken";
159                     rr.next = ruleEnd;
160                     alt.addElement(rr); // add rule ref to alt
161
alt.setAutoGen(true); // keep text of elements
162
rb.addAlternative(alt); // add alt to rule block
163
r.addReference(rr); // track ref to this rule in rule blk
164
}
165             }
166         }
167
168         rb.setAutoGen(true); // keep text of elements
169
rb.prepareForAnalysis();
170         //System.out.println(rb);
171
return rb;
172     }
173
174     /** Return block as if they had typed: "( rule )?" */
175     private AlternativeBlock createOptionalRuleRef(String JavaDoc rule, Token start) {
176         // Make the subrule
177
AlternativeBlock blk = new AlternativeBlock(grammar, start, false);
178
179         // Make sure rule is defined
180
String JavaDoc mrule = CodeGenerator.encodeLexerRuleName(rule); // can only be a lexer rule!
181
if (!grammar.isDefined(mrule)) {
182             grammar.define(new RuleSymbol(mrule));
183         }
184
185         // Make the rule ref element
186
// RK: fixme probably easier to abuse start token..
187
Token t = new CommonToken(ANTLRTokenTypes.TOKEN_REF, rule);
188         t.setLine(start.getLine());
189         t.setLine(start.getColumn());
190         RuleRefElement rref =
191             new RuleRefElement(grammar, t, GrammarElement.AUTO_GEN_NONE);
192
193         rref.enclosingRuleName = ruleBlock.ruleName;
194
195         // Make the end of block element
196
BlockEndElement end = new BlockEndElement(grammar);
197         end.block = blk; // end block points back to start of blk
198

199         // Make an alternative, putting the rule ref into it
200
Alternative alt = new Alternative(rref);
201         alt.addElement(end); // last element in alt points to end of block
202

203         // Add the alternative to this block
204
blk.addAlternative(alt);
205
206         // create an empty (optional) alt and add to blk
207
Alternative optAlt = new Alternative();
208         optAlt.addElement(end); // points immediately to end of block
209

210         blk.addAlternative(optAlt);
211
212         blk.prepareForAnalysis();
213         return blk;
214     }
215
216     public void defineRuleName(Token r,
217                                String JavaDoc access,
218                                boolean ruleAutoGen,
219                                String JavaDoc docComment)
220         throws SemanticException {
221         // if ( Character.isUpperCase(r.getText().charAt(0)) ) {
222
if (r.type == ANTLRTokenTypes.TOKEN_REF) {
223             if (!(grammar instanceof LexerGrammar)) {
224                 tool.error("Lexical rule " + r.getText() +
225                            " defined outside of lexer",
226                            grammar.getFilename(), r.getLine(), r.getColumn());
227                 r.setText(r.getText().toLowerCase());
228             }
229         }
230         else {
231             if (grammar instanceof LexerGrammar) {
232                 tool.error("Lexical rule names must be upper case, '" + r.getText() +
233                            "' is not",
234                            grammar.getFilename(), r.getLine(), r.getColumn());
235                 r.setText(r.getText().toUpperCase());
236             }
237         }
238
239         super.defineRuleName(r, access, ruleAutoGen, docComment);
240         String JavaDoc id = r.getText();
241         // if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
242
if (r.type == ANTLRTokenTypes.TOKEN_REF) { // lexer rule?
243
id = CodeGenerator.encodeLexerRuleName(id);
244         }
245         RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
246         RuleBlock rb = new RuleBlock(grammar, r.getText(), r.getLine(), ruleAutoGen);
247
248         // Lexer rules do not generate default error handling
249
rb.setDefaultErrorHandler(grammar.getDefaultErrorHandler());
250
251         ruleBlock = rb;
252         blocks.push(new BlockContext()); // enter new context
253
context().block = rb;
254         rs.setBlock(rb);
255         ruleEnd = new RuleEndElement(grammar);
256         rb.setEndElement(ruleEnd);
257         nested = 0;
258     }
259
260     public void endAlt() {
261         super.endAlt();
262         if (nested == 0) { // all rule-level alts link to ruleEnd node
263
addElementToCurrentAlt(ruleEnd);
264         }
265         else {
266             addElementToCurrentAlt(context().blockEnd);
267         }
268         context().altNum++;
269     }
270
271     public void endChildList() {
272         super.endChildList();
273         // create a final node to which the last elememt of the single
274
// alternative will point. Done for compatibility with analyzer.
275
// Does NOT point to any block like alternative blocks because the
276
// TreeElement is not a block. This is used only as a placeholder.
277
BlockEndElement be = new BlockEndElement(grammar);
278         be.block = context().block;
279         addElementToCurrentAlt(be);
280     }
281
282     public void endExceptionGroup() {
283         super.endExceptionGroup();
284     }
285
286     public void endExceptionSpec() {
287         super.endExceptionSpec();
288         if (currentExceptionSpec == null) {
289             tool.panic("exception processing internal error -- no active exception spec");
290         }
291         if (context().block instanceof RuleBlock) {
292             // Named rule
293
((RuleBlock)context().block).addExceptionSpec(currentExceptionSpec);
294         }
295         else {
296             // It must be a plain-old alternative block
297
if (context().currentAlt().exceptionSpec != null) {
298                 tool.error("Alternative already has an exception specification", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
299             }
300             else {
301                 context().currentAlt().exceptionSpec = currentExceptionSpec;
302             }
303         }
304         currentExceptionSpec = null;
305     }
306
307     /** Called at the end of processing a grammar */
308     public void endGrammar() {
309         if (grammarError) {
310             abortGrammar();
311         }
312         else {
313             super.endGrammar();
314         }
315     }
316
317     public void endRule(String JavaDoc rule) {
318         super.endRule(rule);
319         BlockContext ctx = (BlockContext)blocks.pop(); // remove scope
320
// record the start of this block in the ending node
321
ruleEnd.block = ctx.block;
322         ruleEnd.block.prepareForAnalysis();
323         //System.out.println(ctx.block);
324
}
325
326     public void endSubRule() {
327         super.endSubRule();
328         nested--;
329         // remove subrule context from scope stack
330
BlockContext ctx = (BlockContext)blocks.pop();
331         AlternativeBlock block = ctx.block;
332
333         // If the subrule is marked with ~, check that it is
334
// a valid candidate for analysis
335
if (
336             block.not &&
337             !(block instanceof SynPredBlock) &&
338             !(block instanceof ZeroOrMoreBlock) &&
339             !(block instanceof OneOrMoreBlock)
340         ) {
341             if (!analyzer.subruleCanBeInverted(block, grammar instanceof LexerGrammar)) {
342                 String JavaDoc newline = System.getProperty("line.separator");
343                 tool.error(
344                     "This subrule cannot be inverted. Only subrules of the form:" + newline +
345                     " (T1|T2|T3...) or" + newline +
346                     " ('c1'|'c2'|'c3'...)" + newline +
347                     "may be inverted (ranges are also allowed).",
348                     grammar.getFilename(),
349                     block.getLine(), block.getColumn()
350                 );
351             }
352         }
353
354         // add the subrule as element if not a syn pred
355
if (block instanceof SynPredBlock) {
356             // record a reference to the recently-recognized syn pred in the
357
// enclosing block.
358
SynPredBlock synpred = (SynPredBlock)block;
359             context().block.hasASynPred = true;
360             context().currentAlt().synPred = synpred;
361             grammar.hasSyntacticPredicate = true;
362             synpred.removeTrackingOfRuleRefs(grammar);
363         }
364         else {
365             addElementToCurrentAlt(block);
366         }
367         ctx.blockEnd.block.prepareForAnalysis();
368     }
369
370     public void endTree() {
371         super.endTree();
372         BlockContext ctx = (BlockContext)blocks.pop();
373         addElementToCurrentAlt(ctx.block); // add new TreeElement to enclosing alt.
374
}
375
376     /** Remember that a major error occured in the grammar */
377     public void hasError() {
378         grammarError = true;
379     }
380
381     private void labelElement(AlternativeElement el, Token label) {
382         if (label != null) {
383             // Does this label already exist?
384
for (int i = 0; i < ruleBlock.labeledElements.size(); i++) {
385                 AlternativeElement altEl = (AlternativeElement)ruleBlock.labeledElements.elementAt(i);
386                 String JavaDoc l = altEl.getLabel();
387                 if (l != null && l.equals(label.getText())) {
388                     tool.error("Label '" + label.getText() + "' has already been defined", grammar.getFilename(), label.getLine(), label.getColumn());
389                     return;
390                 }
391             }
392             // add this node to the list of labeled elements
393
el.setLabel(label.getText());
394             ruleBlock.labeledElements.appendElement(el);
395         }
396     }
397
398     public void noAutoGenSubRule() {
399         context().block.setAutoGen(false);
400     }
401
402     public void oneOrMoreSubRule() {
403         if (context().block.not) {
404             tool.error("'~' cannot be applied to (...)* subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
405         }
406         // create the right kind of object now that we know what that is
407
// and switch the list of alternatives. Adjust the stack of blocks.
408
// copy any init action also.
409
OneOrMoreBlock b = new OneOrMoreBlock(grammar);
410         setBlock(b, context().block);
411         BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
412
blocks.push(new BlockContext());
413         context().block = b;
414         context().blockEnd = old.blockEnd;
415         context().blockEnd.block = b;
416     }
417
418     public void optionalSubRule() {
419         if (context().block.not) {
420             tool.error("'~' cannot be applied to (...)? subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
421         }
422         // convert (X)? -> (X|) so that we can ignore optional blocks altogether!
423
// It already thinks that we have a simple subrule, just add option block.
424
beginAlt(false);
425         endAlt();
426     }
427
428     public void refAction(Token action) {
429         super.refAction(action);
430         context().block.hasAnAction = true;
431         addElementToCurrentAlt(new ActionElement(grammar, action));
432     }
433
434     public void setUserExceptions(String JavaDoc thr) {
435         ((RuleBlock)context().block).throwsSpec = thr;
436     }
437
438     // Only called for rule blocks
439
public void refArgAction(Token action) {
440         ((RuleBlock)context().block).argAction = action.getText();
441     }
442
443     public void refCharLiteral(Token lit, Token label, boolean inverted, int autoGenType, boolean lastInRule) {
444         if (!(grammar instanceof LexerGrammar)) {
445             tool.error("Character literal only valid in lexer", grammar.getFilename(), lit.getLine(), lit.getColumn());
446             return;
447         }
448         super.refCharLiteral(lit, label, inverted, autoGenType, lastInRule);
449         CharLiteralElement cl = new CharLiteralElement((LexerGrammar)grammar, lit, inverted, autoGenType);
450
451         // Generate a warning for non-lowercase ASCII when case-insensitive
452
if (
453             !((LexerGrammar)grammar).caseSensitive && cl.getType() < 128 &&
454             Character.toLowerCase((char)cl.getType()) != (char)cl.getType()
455         ) {
456             tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn());
457         }
458
459         addElementToCurrentAlt(cl);
460         labelElement(cl, label);
461
462         // if ignore option is set, must add an optional call to the specified rule.
463
String JavaDoc ignore = ruleBlock.getIgnoreRule();
464         if (!lastInRule && ignore != null) {
465             addElementToCurrentAlt(createOptionalRuleRef(ignore, lit));
466         }
467     }
468
469     public void refCharRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
470         if (!(grammar instanceof LexerGrammar)) {
471             tool.error("Character range only valid in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn());
472             return;
473         }
474         int rangeMin = ANTLRLexer.tokenTypeForCharLiteral(t1.getText());
475         int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(t2.getText());
476         if (rangeMax < rangeMin) {
477             tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn());
478             return;
479         }
480
481         // Generate a warning for non-lowercase ASCII when case-insensitive
482
if (!((LexerGrammar)grammar).caseSensitive) {
483             if (rangeMin < 128 && Character.toLowerCase((char)rangeMin) != (char)rangeMin) {
484                 tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t1.getLine(), t1.getColumn());
485             }
486             if (rangeMax < 128 && Character.toLowerCase((char)rangeMax) != (char)rangeMax) {
487                 tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t2.getLine(), t2.getColumn());
488             }
489         }
490
491         super.refCharRange(t1, t2, label, autoGenType, lastInRule);
492         CharRangeElement cr = new CharRangeElement((LexerGrammar)grammar, t1, t2, autoGenType);
493         addElementToCurrentAlt(cr);
494         labelElement(cr, label);
495
496         // if ignore option is set, must add an optional call to the specified rule.
497
String JavaDoc ignore = ruleBlock.getIgnoreRule();
498         if (!lastInRule && ignore != null) {
499             addElementToCurrentAlt(createOptionalRuleRef(ignore, t1));
500         }
501     }
502
503     public void refTokensSpecElementOption(Token tok,
504                                            Token option,
505                                            Token value) {
506         /*
507         System.out.println("setting tokens spec option for "+tok.getText());
508         System.out.println(option.getText()+","+value.getText());
509         */

510         TokenSymbol ts = (TokenSymbol)
511             grammar.tokenManager.getTokenSymbol(tok.getText());
512         if (ts == null) {
513             tool.panic("cannot find " + tok.getText() + "in tokens {...}");
514         }
515         if (option.getText().equals("AST")) {
516             ts.setASTNodeType(value.getText());
517         }
518         else {
519             grammar.antlrTool.error("invalid tokens {...} element option:" +
520                                option.getText(),
521                                grammar.getFilename(),
522                                option.getLine(), option.getColumn());
523         }
524     }
525
526     public void refElementOption(Token option, Token value) {
527         /*
528         System.out.println("setting option for "+context().currentElement());
529         System.out.println(option.getText()+","+value.getText());
530         */

531         AlternativeElement e = context().currentElement();
532         if (e instanceof StringLiteralElement ||
533             e instanceof TokenRefElement ||
534             e instanceof WildcardElement) {
535             ((GrammarAtom)e).setOption(option, value);
536         }
537         else {
538             tool.error("cannot use element option (" + option.getText() +
539                        ") for this kind of element",
540                        grammar.getFilename(), option.getLine(), option.getColumn());
541         }
542     }
543
544     /** Add an exception handler to an exception spec */
545     public void refExceptionHandler(Token exTypeAndName, Token action) {
546         super.refExceptionHandler(exTypeAndName, action);
547         if (currentExceptionSpec == null) {
548             tool.panic("exception handler processing internal error");
549         }
550         currentExceptionSpec.addHandler(new ExceptionHandler(exTypeAndName, action));
551     }
552
553     public void refInitAction(Token action) {
554         super.refAction(action);
555         context().block.setInitAction(action.getText());
556     }
557
558     public void refMemberAction(Token act) {
559         grammar.classMemberAction = act;
560     }
561
562     public void refPreambleAction(Token act) {
563         super.refPreambleAction(act);
564     }
565
566     // Only called for rule blocks
567
public void refReturnAction(Token returnAction) {
568         if (grammar instanceof LexerGrammar) {
569             String JavaDoc name = CodeGenerator.encodeLexerRuleName(((RuleBlock)context().block).getRuleName());
570             RuleSymbol rs = (RuleSymbol)grammar.getSymbol(name);
571             if (rs.access.equals("public")) {
572                 tool.warning("public Lexical rules cannot specify return type", grammar.getFilename(), returnAction.getLine(), returnAction.getColumn());
573                 return;
574             }
575         }
576         ((RuleBlock)context().block).returnAction = returnAction.getText();
577     }
578
579     public void refRule(Token idAssign,
580                         Token r,
581                         Token label,
582                         Token args,
583                         int autoGenType) {
584         // Disallow parser rule references in the lexer
585
if (grammar instanceof LexerGrammar) {
586             // if (!Character.isUpperCase(r.getText().charAt(0))) {
587
if (r.type != ANTLRTokenTypes.TOKEN_REF) {
588                 tool.error("Parser rule " + r.getText() + " referenced in lexer");
589                 return;
590             }
591             if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
592                 tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), r.getLine(), r.getColumn());
593             }
594         }
595
596         super.refRule(idAssign, r, label, args, autoGenType);
597         lastRuleRef = new RuleRefElement(grammar, r, autoGenType);
598         if (args != null) {
599             lastRuleRef.setArgs(args.getText());
600         }
601         if (idAssign != null) {
602             lastRuleRef.setIdAssign(idAssign.getText());
603         }
604         addElementToCurrentAlt(lastRuleRef);
605
606         String JavaDoc id = r.getText();
607         // if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
608
if (r.type == ANTLRTokenTypes.TOKEN_REF) { // lexer rule?
609
id = CodeGenerator.encodeLexerRuleName(id);
610         }
611         // update symbol table so it knows what nodes reference the rule.
612
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
613         rs.addReference(lastRuleRef);
614         labelElement(lastRuleRef, label);
615     }
616
617     public void refSemPred(Token pred) {
618         //System.out.println("refSemPred "+pred.getText());
619
super.refSemPred(pred);
620         //System.out.println("context().block: "+context().block);
621
if (context().currentAlt().atStart()) {
622             context().currentAlt().semPred = pred.getText();
623         }
624         else {
625             ActionElement a = new ActionElement(grammar, pred);
626             a.isSemPred = true;
627             addElementToCurrentAlt(a);
628         }
629         //System.out.println("DONE refSemPred "+pred.getText());
630
}
631
632     public void refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule) {
633         super.refStringLiteral(lit, label, autoGenType, lastInRule);
634         if (grammar instanceof TreeWalkerGrammar && autoGenType == GrammarElement.AUTO_GEN_CARET) {
635             tool.error("^ not allowed in here for tree-walker", grammar.getFilename(), lit.getLine(), lit.getColumn());
636         }
637         StringLiteralElement sl = new StringLiteralElement(grammar, lit, autoGenType);
638
639         // If case-insensitive, then check each char of the stirng literal
640
if (grammar instanceof LexerGrammar && !((LexerGrammar)grammar).caseSensitive) {
641             for (int i = 1; i < lit.getText().length() - 1; i++) {
642                 char c = lit.getText().charAt(i);
643                 if (c < 128 && Character.toLowerCase(c) != c) {
644                     tool.warning("Characters of string literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn());
645                     break;
646                 }
647             }
648         }
649
650         addElementToCurrentAlt(sl);
651         labelElement(sl, label);
652
653         // if ignore option is set, must add an optional call to the specified rule.
654
String JavaDoc ignore = ruleBlock.getIgnoreRule();
655         if (!lastInRule && ignore != null) {
656             addElementToCurrentAlt(createOptionalRuleRef(ignore, lit));
657         }
658     }
659
660     public void refToken(Token idAssign, Token t, Token label, Token args,
661                          boolean inverted, int autoGenType, boolean lastInRule) {
662         if (grammar instanceof LexerGrammar) {
663             // In lexer, token references are really rule references
664
if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
665                 tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn());
666             }
667             if (inverted) {
668                 tool.error("~TOKEN is not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn());
669             }
670             refRule(idAssign, t, label, args, autoGenType);
671
672             // if ignore option is set, must add an optional call to the specified token rule.
673
String JavaDoc ignore = ruleBlock.getIgnoreRule();
674             if (!lastInRule && ignore != null) {
675                 addElementToCurrentAlt(createOptionalRuleRef(ignore, t));
676             }
677         }
678         else {
679             // Cannot have token ref args or assignment outside of lexer
680
if (idAssign != null) {
681                 tool.error("Assignment from token reference only allowed in lexer", grammar.getFilename(), idAssign.getLine(), idAssign.getColumn());
682             }
683             if (args != null) {
684                 tool.error("Token reference arguments only allowed in lexer", grammar.getFilename(), args.getLine(), args.getColumn());
685             }
686             super.refToken(idAssign, t, label, args, inverted, autoGenType, lastInRule);
687             TokenRefElement te = new TokenRefElement(grammar, t, inverted, autoGenType);
688             addElementToCurrentAlt(te);
689             labelElement(te, label);
690         }
691     }
692
693     public void refTokenRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
694         if (grammar instanceof LexerGrammar) {
695             tool.error("Token range not allowed in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn());
696             return;
697         }
698         super.refTokenRange(t1, t2, label, autoGenType, lastInRule);
699         TokenRangeElement tr = new TokenRangeElement(grammar, t1, t2, autoGenType);
700         if (tr.end < tr.begin) {
701             tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn());
702             return;
703         }
704         addElementToCurrentAlt(tr);
705         labelElement(tr, label);
706     }
707
708     public void refTreeSpecifier(Token treeSpec) {
709         context().currentAlt().treeSpecifier = treeSpec;
710     }
711
712     public void refWildcard(Token t, Token label, int autoGenType) {
713         super.refWildcard(t, label, autoGenType);
714         WildcardElement wc = new WildcardElement(grammar, t, autoGenType);
715         addElementToCurrentAlt(wc);
716         labelElement(wc, label);
717     }
718
719     /** Get ready to process a new grammar */
720     public void reset() {
721         super.reset();
722         blocks = new LList();
723         lastRuleRef = null;
724         ruleEnd = null;
725         ruleBlock = null;
726         nested = 0;
727         currentExceptionSpec = null;
728         grammarError = false;
729     }
730
731     public void setArgOfRuleRef(Token argAction) {
732         super.setArgOfRuleRef(argAction);
733         lastRuleRef.setArgs(argAction.getText());
734     }
735
736     public static void setBlock(AlternativeBlock b, AlternativeBlock src) {
737         b.setAlternatives(src.getAlternatives());
738         b.initAction = src.initAction;
739         //b.lookaheadDepth = src.lookaheadDepth;
740
b.label = src.label;
741         b.hasASynPred = src.hasASynPred;
742         b.hasAnAction = src.hasAnAction;
743         b.warnWhenFollowAmbig = src.warnWhenFollowAmbig;
744         b.generateAmbigWarnings = src.generateAmbigWarnings;
745         b.line = src.line;
746         b.greedy = src.greedy;
747         b.greedySet = src.greedySet;
748     }
749
750     public void setRuleOption(Token key, Token value) {
751         //((RuleBlock)context().block).setOption(key, value);
752
ruleBlock.setOption(key, value);
753     }
754
755     public void setSubruleOption(Token key, Token value) {
756         ((AlternativeBlock)context().block).setOption(key, value);
757     }
758
759     public void synPred() {
760         if (context().block.not) {
761             tool.error("'~' cannot be applied to syntactic predicate", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
762         }
763         // create the right kind of object now that we know what that is
764
// and switch the list of alternatives. Adjust the stack of blocks.
765
// copy any init action also.
766
SynPredBlock b = new SynPredBlock(grammar);
767         setBlock(b, context().block);
768         BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
769
blocks.push(new BlockContext());
770         context().block = b;
771         context().blockEnd = old.blockEnd;
772         context().blockEnd.block = b;
773     }
774
775     public void zeroOrMoreSubRule() {
776         if (context().block.not) {
777             tool.error("'~' cannot be applied to (...)+ subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
778         }
779         // create the right kind of object now that we know what that is
780
// and switch the list of alternatives. Adjust the stack of blocks.
781
// copy any init action also.
782
ZeroOrMoreBlock b = new ZeroOrMoreBlock(grammar);
783         setBlock(b, context().block);
784         BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
785
blocks.push(new BlockContext());
786         context().block = b;
787         context().blockEnd = old.blockEnd;
788         context().blockEnd.block = b;
789     }
790 }
791
Popular Tags