package antlr;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.jGuru.com
* Software rights: http://www.antlr.org/license.html
*
* $Id: //depot/code/org.antlr/release/antlr-2.7.5/antlr/MakeGrammar.java#1 $
*/
import antlr.collections.Stack;
import antlr.collections.impl.LList;
import antlr.collections.impl.Vector;
public class MakeGrammar extends DefineGrammarSymbols {
protected Stack blocks = new LList(); // track subrules--Stack<BlockContext>
protected RuleRefElement lastRuleRef;
protected RuleEndElement ruleEnd; // used if not nested
protected RuleBlock ruleBlock; // points to block of current rule.
protected int nested = 0; // nesting inside a subrule
protected boolean grammarError = false;
ExceptionSpec currentExceptionSpec = null;
public MakeGrammar(Tool tool_, String[] args_, LLkAnalyzer analyzer_) {
super(tool_, args_, analyzer_);
}
/** Abort the processing of a grammar (due to syntax errors) */
public void abortGrammar() {
String s = "unknown grammar";
if (grammar != null) {
s = grammar.getClassName();
}
tool.error("aborting grammar '" + s + "' due to errors");
super.abortGrammar();
}
protected void addElementToCurrentAlt(AlternativeElement e) {
e.enclosingRuleName = ruleBlock.ruleName;
context().addAlternativeElement(e);
}
public void beginAlt(boolean doAutoGen_) {
super.beginAlt(doAutoGen_);
Alternative alt = new Alternative();
alt.setAutoGen(doAutoGen_);
context().block.addAlternative(alt);
}
public void beginChildList() {
super.beginChildList();
context().block.addAlternative(new Alternative());
}
/** Add an exception group to a rule (currently a no-op) */
public void beginExceptionGroup() {
super.beginExceptionGroup();
if (!(context().block instanceof RuleBlock)) {
tool.panic("beginExceptionGroup called outside of rule block");
}
}
/** Add an exception spec to an exception group or rule block */
public void beginExceptionSpec(Token label) {
// Hack the label string a bit to remove leading/trailing space.
if (label != null) {
label.setText(StringUtils.stripFront(StringUtils.stripBack(label.getText(), " \n\r\t"), " \n\r\t"));
}
super.beginExceptionSpec(label);
// Don't check for currentExceptionSpec!=null because syntax errors
// may leave it set to something.
currentExceptionSpec = new ExceptionSpec(label);
}
public void beginSubRule(Token label, Token start, boolean not) {
super.beginSubRule(label, start, not);
// we don't know what kind of subrule it is yet.
// push a dummy one that will allow us to collect the
// alternatives. Later, we'll switch to real object.
blocks.push(new BlockContext());
context().block = new AlternativeBlock(grammar, start, not);
context().altNum = 0; // reset alternative number
nested++;
// create a final node to which the last elememt of each
// alternative will point.
context().blockEnd = new BlockEndElement(grammar);
// make sure end node points to start of block
context().blockEnd.block = context().block;
labelElement(context().block, label);
}
public void beginTree(Token tok) throws SemanticException {
if (!(grammar instanceof TreeWalkerGrammar)) {
tool.error("Trees only allowed in TreeParser", grammar.getFilename(), tok.getLine(), tok.getColumn());
throw new SemanticException("Trees only allowed in TreeParser");
}
super.beginTree(tok);
blocks.push(new TreeBlockContext());
context().block = new TreeElement(grammar, tok);
context().altNum = 0; // reset alternative number
}
public BlockContext context() {
if (blocks.height() == 0) {
return null;
}
else {
return (BlockContext)blocks.top();
}
}
/**Used to build nextToken() for the lexer.
* This builds a rule which has every "public" rule in the given Vector of
* rules as it's alternate. Each rule ref generates a Token object.
* @param g The Grammar that is being processed
* @param lexRules A vector of lexer rules that will be used to create an alternate block.
* @param rname The name of the resulting rule.
*/
public static RuleBlock createNextTokenRule(Grammar g, Vector lexRules, String rname) {
// create actual rule data structure
RuleBlock rb = new RuleBlock(g, rname);
rb.setDefaultErrorHandler(g.getDefaultErrorHandler());
RuleEndElement ruleEnd = new RuleEndElement(g);
rb.setEndElement(ruleEnd);
ruleEnd.block = rb;
// Add an alternative for each element of the rules vector.
for (int i = 0; i < lexRules.size(); i++) {
RuleSymbol r = (RuleSymbol)lexRules.elementAt(i);
if (!r.isDefined()) {
g.antlrTool.error("Lexer rule " + r.id.substring(1) + " is not defined");
}
else {
if (r.access.equals("public")) {
Alternative alt = new Alternative(); // create alt we'll add to ref rule
RuleBlock targetRuleBlock = r.getBlock();
Vector targetRuleAlts = targetRuleBlock.getAlternatives();
// collect a sem pred if only one alt and it's at the start;
// simple, but faster to implement until real hoisting
if ( targetRuleAlts!=null && targetRuleAlts.size()==1 ) {
Alternative onlyAlt = (Alternative)targetRuleAlts.elementAt(0);
if ( onlyAlt.semPred!=null ) {
// ok, has sem pred, make this rule ref alt have a pred
alt.semPred = onlyAlt.semPred;
// REMOVE predicate from target rule??? NOPE, another
// rule other than nextToken() might invoke it.
}
}
// create a rule ref to lexer rule
// the Token is a RULE_REF not a TOKEN_REF since the
// conversion to mRulename has already taken place
RuleRefElement rr =
new RuleRefElement(g,
new CommonToken(ANTLRTokenTypes.RULE_REF, r.getId()),
GrammarElement.AUTO_GEN_NONE);
rr.setLabel("theRetToken");
rr.enclosingRuleName = "nextToken";
rr.next = ruleEnd;
alt.addElement(rr); // add rule ref to alt
alt.setAutoGen(true); // keep text of elements
rb.addAlternative(alt); // add alt to rule block
r.addReference(rr); // track ref to this rule in rule blk
}
}
}
rb.setAutoGen(true); // keep text of elements
rb.prepareForAnalysis();
//System.out.println(rb);
return rb;
}
/** Return block as if they had typed: "( rule )?" */
private AlternativeBlock createOptionalRuleRef(String rule, Token start) {
// Make the subrule
AlternativeBlock blk = new AlternativeBlock(grammar, start, false);
// Make sure rule is defined
String mrule = CodeGenerator.encodeLexerRuleName(rule); // can only be a lexer rule!
if (!grammar.isDefined(mrule)) {
grammar.define(new RuleSymbol(mrule));
}
// Make the rule ref element
// RK: fixme probably easier to abuse start token..
Token t = new CommonToken(ANTLRTokenTypes.TOKEN_REF, rule);
t.setLine(start.getLine());
t.setLine(start.getColumn());
RuleRefElement rref =
new RuleRefElement(grammar, t, GrammarElement.AUTO_GEN_NONE);
rref.enclosingRuleName = ruleBlock.ruleName;
// Make the end of block element
BlockEndElement end = new BlockEndElement(grammar);
end.block = blk; // end block points back to start of blk
// Make an alternative, putting the rule ref into it
Alternative alt = new Alternative(rref);
alt.addElement(end); // last element in alt points to end of block
// Add the alternative to this block
blk.addAlternative(alt);
// create an empty (optional) alt and add to blk
Alternative optAlt = new Alternative();
optAlt.addElement(end); // points immediately to end of block
blk.addAlternative(optAlt);
blk.prepareForAnalysis();
return blk;
}
public void defineRuleName(Token r,
String access,
boolean ruleAutoGen,
String docComment)
throws SemanticException {
// if ( Character.isUpperCase(r.getText().charAt(0)) ) {
if (r.type == ANTLRTokenTypes.TOKEN_REF) {
if (!(grammar instanceof LexerGrammar)) {
tool.error("Lexical rule " + r.getText() +
" defined outside of lexer",
grammar.getFilename(), r.getLine(), r.getColumn());
r.setText(r.getText().toLowerCase());
}
}
else {
if (grammar instanceof LexerGrammar) {
tool.error("Lexical rule names must be upper case, '" + r.getText() +
"' is not",
grammar.getFilename(), r.getLine(), r.getColumn());
r.setText(r.getText().toUpperCase());
}
}
super.defineRuleName(r, access, ruleAutoGen, docComment);
String id = r.getText();
// if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
if (r.type == ANTLRTokenTypes.TOKEN_REF) { // lexer rule?
id = CodeGenerator.encodeLexerRuleName(id);
}
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
RuleBlock rb = new RuleBlock(grammar, r.getText(), r.getLine(), ruleAutoGen);
// Lexer rules do not generate default error handling
rb.setDefaultErrorHandler(grammar.getDefaultErrorHandler());
ruleBlock = rb;
blocks.push(new BlockContext()); // enter new context
context().block = rb;
rs.setBlock(rb);
ruleEnd = new RuleEndElement(grammar);
rb.setEndElement(ruleEnd);
nested = 0;
}
public void endAlt() {
super.endAlt();
if (nested == 0) { // all rule-level alts link to ruleEnd node
addElementToCurrentAlt(ruleEnd);
}
else {
addElementToCurrentAlt(context().blockEnd);
}
context().altNum++;
}
public void endChildList() {
super.endChildList();
// create a final node to which the last elememt of the single
// alternative will point. Done for compatibility with analyzer.
// Does NOT point to any block like alternative blocks because the
// TreeElement is not a block. This is used only as a placeholder.
BlockEndElement be = new BlockEndElement(grammar);
be.block = context().block;
addElementToCurrentAlt(be);
}
public void endExceptionGroup() {
super.endExceptionGroup();
}
public void endExceptionSpec() {
super.endExceptionSpec();
if (currentExceptionSpec == null) {
tool.panic("exception processing internal error -- no active exception spec");
}
if (context().block instanceof RuleBlock) {
// Named rule
((RuleBlock)context().block).addExceptionSpec(currentExceptionSpec);
}
else {
// It must be a plain-old alternative block
if (context().currentAlt().exceptionSpec != null) {
tool.error("Alternative already has an exception specification", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
}
else {
context().currentAlt().exceptionSpec = currentExceptionSpec;
}
}
currentExceptionSpec = null;
}
/** Called at the end of processing a grammar */
public void endGrammar() {
if (grammarError) {
abortGrammar();
}
else {
super.endGrammar();
}
}
public void endRule(String rule) {
super.endRule(rule);
BlockContext ctx = (BlockContext)blocks.pop(); // remove scope
// record the start of this block in the ending node
ruleEnd.block = ctx.block;
ruleEnd.block.prepareForAnalysis();
//System.out.println(ctx.block);
}
public void endSubRule() {
super.endSubRule();
nested--;
// remove subrule context from scope stack
BlockContext ctx = (BlockContext)blocks.pop();
AlternativeBlock block = ctx.block;
// If the subrule is marked with ~, check that it is
// a valid candidate for analysis
if (
block.not &&
!(block instanceof SynPredBlock) &&
!(block instanceof ZeroOrMoreBlock) &&
!(block instanceof OneOrMoreBlock)
) {
if (!analyzer.subruleCanBeInverted(block, grammar instanceof LexerGrammar)) {
String newline = System.getProperty("line.separator");
tool.error(
"This subrule cannot be inverted. Only subrules of the form:" + newline +
" (T1|T2|T3...) or" + newline +
" ('c1'|'c2'|'c3'...)" + newline +
"may be inverted (ranges are also allowed).",
grammar.getFilename(),
block.getLine(), block.getColumn()
);
}
}
// add the subrule as element if not a syn pred
if (block instanceof SynPredBlock) {
// record a reference to the recently-recognized syn pred in the
// enclosing block.
SynPredBlock synpred = (SynPredBlock)block;
context().block.hasASynPred = true;
context().currentAlt().synPred = synpred;
grammar.hasSyntacticPredicate = true;
synpred.removeTrackingOfRuleRefs(grammar);
}
else {
addElementToCurrentAlt(block);
}
ctx.blockEnd.block.prepareForAnalysis();
}
public void endTree() {
super.endTree();
BlockContext ctx = (BlockContext)blocks.pop();
addElementToCurrentAlt(ctx.block); // add new TreeElement to enclosing alt.
}
/** Remember that a major error occured in the grammar */
public void hasError() {
grammarError = true;
}
private void labelElement(AlternativeElement el, Token label) {
if (label != null) {
// Does this label already exist?
for (int i = 0; i < ruleBlock.labeledElements.size(); i++) {
AlternativeElement altEl = (AlternativeElement)ruleBlock.labeledElements.elementAt(i);
String l = altEl.getLabel();
if (l != null && l.equals(label.getText())) {
tool.error("Label '" + label.getText() + "' has already been defined", grammar.getFilename(), label.getLine(), label.getColumn());
return;
}
}
// add this node to the list of labeled elements
el.setLabel(label.getText());
ruleBlock.labeledElements.appendElement(el);
}
}
public void noAutoGenSubRule() {
context().block.setAutoGen(false);
}
public void oneOrMoreSubRule() {
if (context().block.not) {
tool.error("'~' cannot be applied to (...)* subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
}
// create the right kind of object now that we know what that is
// and switch the list of alternatives. Adjust the stack of blocks.
// copy any init action also.
OneOrMoreBlock b = new OneOrMoreBlock(grammar);
setBlock(b, context().block);
BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
blocks.push(new BlockContext());
context().block = b;
context().blockEnd = old.blockEnd;
context().blockEnd.block = b;
}
public void optionalSubRule() {
if (context().block.not) {
tool.error("'~' cannot be applied to (...)? subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
}
// convert (X)? -> (X|) so that we can ignore optional blocks altogether!
// It already thinks that we have a simple subrule, just add option block.
beginAlt(false);
endAlt();
}
public void refAction(Token action) {
super.refAction(action);
context().block.hasAnAction = true;
addElementToCurrentAlt(new ActionElement(grammar, action));
}
public void setUserExceptions(String thr) {
((RuleBlock)context().block).throwsSpec = thr;
}
// Only called for rule blocks
public void refArgAction(Token action) {
((RuleBlock)context().block).argAction = action.getText();
}
public void refCharLiteral(Token lit, Token label, boolean inverted, int autoGenType, boolean lastInRule) {
if (!(grammar instanceof LexerGrammar)) {
tool.error("Character literal only valid in lexer", grammar.getFilename(), lit.getLine(), lit.getColumn());
return;
}
super.refCharLiteral(lit, label, inverted, autoGenType, lastInRule);
CharLiteralElement cl = new CharLiteralElement((LexerGrammar)grammar, lit, inverted, autoGenType);
// Generate a warning for non-lowercase ASCII when case-insensitive
if (
!((LexerGrammar)grammar).caseSensitive && cl.getType() < 128 &&
Character.toLowerCase((char)cl.getType()) != (char)cl.getType()
) {
tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn());
}
addElementToCurrentAlt(cl);
labelElement(cl, label);
// if ignore option is set, must add an optional call to the specified rule.
String ignore = ruleBlock.getIgnoreRule();
if (!lastInRule && ignore != null) {
addElementToCurrentAlt(createOptionalRuleRef(ignore, lit));
}
}
public void refCharRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
if (!(grammar instanceof LexerGrammar)) {
tool.error("Character range only valid in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn());
return;
}
int rangeMin = ANTLRLexer.tokenTypeForCharLiteral(t1.getText());
int rangeMax = ANTLRLexer.tokenTypeForCharLiteral(t2.getText());
if (rangeMax < rangeMin) {
tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn());
return;
}
// Generate a warning for non-lowercase ASCII when case-insensitive
if (!((LexerGrammar)grammar).caseSensitive) {
if (rangeMin < 128 && Character.toLowerCase((char)rangeMin) != (char)rangeMin) {
tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t1.getLine(), t1.getColumn());
}
if (rangeMax < 128 && Character.toLowerCase((char)rangeMax) != (char)rangeMax) {
tool.warning("Character literal must be lowercase when caseSensitive=false", grammar.getFilename(), t2.getLine(), t2.getColumn());
}
}
super.refCharRange(t1, t2, label, autoGenType, lastInRule);
CharRangeElement cr = new CharRangeElement((LexerGrammar)grammar, t1, t2, autoGenType);
addElementToCurrentAlt(cr);
labelElement(cr, label);
// if ignore option is set, must add an optional call to the specified rule.
String ignore = ruleBlock.getIgnoreRule();
if (!lastInRule && ignore != null) {
addElementToCurrentAlt(createOptionalRuleRef(ignore, t1));
}
}
public void refTokensSpecElementOption(Token tok,
Token option,
Token value) {
/*
System.out.println("setting tokens spec option for "+tok.getText());
System.out.println(option.getText()+","+value.getText());
*/
TokenSymbol ts = (TokenSymbol)
grammar.tokenManager.getTokenSymbol(tok.getText());
if (ts == null) {
tool.panic("cannot find " + tok.getText() + "in tokens {...}");
}
if (option.getText().equals("AST")) {
ts.setASTNodeType(value.getText());
}
else {
grammar.antlrTool.error("invalid tokens {...} element option:" +
option.getText(),
grammar.getFilename(),
option.getLine(), option.getColumn());
}
}
public void refElementOption(Token option, Token value) {
/*
System.out.println("setting option for "+context().currentElement());
System.out.println(option.getText()+","+value.getText());
*/
AlternativeElement e = context().currentElement();
if (e instanceof StringLiteralElement ||
e instanceof TokenRefElement ||
e instanceof WildcardElement) {
((GrammarAtom)e).setOption(option, value);
}
else {
tool.error("cannot use element option (" + option.getText() +
") for this kind of element",
grammar.getFilename(), option.getLine(), option.getColumn());
}
}
/** Add an exception handler to an exception spec */
public void refExceptionHandler(Token exTypeAndName, Token action) {
super.refExceptionHandler(exTypeAndName, action);
if (currentExceptionSpec == null) {
tool.panic("exception handler processing internal error");
}
currentExceptionSpec.addHandler(new ExceptionHandler(exTypeAndName, action));
}
public void refInitAction(Token action) {
super.refAction(action);
context().block.setInitAction(action.getText());
}
public void refMemberAction(Token act) {
grammar.classMemberAction = act;
}
public void refPreambleAction(Token act) {
super.refPreambleAction(act);
}
// Only called for rule blocks
public void refReturnAction(Token returnAction) {
if (grammar instanceof LexerGrammar) {
String name = CodeGenerator.encodeLexerRuleName(((RuleBlock)context().block).getRuleName());
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(name);
if (rs.access.equals("public")) {
tool.warning("public Lexical rules cannot specify return type", grammar.getFilename(), returnAction.getLine(), returnAction.getColumn());
return;
}
}
((RuleBlock)context().block).returnAction = returnAction.getText();
}
public void refRule(Token idAssign,
Token r,
Token label,
Token args,
int autoGenType) {
// Disallow parser rule references in the lexer
if (grammar instanceof LexerGrammar) {
// if (!Character.isUpperCase(r.getText().charAt(0))) {
if (r.type != ANTLRTokenTypes.TOKEN_REF) {
tool.error("Parser rule " + r.getText() + " referenced in lexer");
return;
}
if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), r.getLine(), r.getColumn());
}
}
super.refRule(idAssign, r, label, args, autoGenType);
lastRuleRef = new RuleRefElement(grammar, r, autoGenType);
if (args != null) {
lastRuleRef.setArgs(args.getText());
}
if (idAssign != null) {
lastRuleRef.setIdAssign(idAssign.getText());
}
addElementToCurrentAlt(lastRuleRef);
String id = r.getText();
// if ( Character.isUpperCase(id.charAt(0)) ) { // lexer rule?
if (r.type == ANTLRTokenTypes.TOKEN_REF) { // lexer rule?
id = CodeGenerator.encodeLexerRuleName(id);
}
// update symbol table so it knows what nodes reference the rule.
RuleSymbol rs = (RuleSymbol)grammar.getSymbol(id);
rs.addReference(lastRuleRef);
labelElement(lastRuleRef, label);
}
public void refSemPred(Token pred) {
//System.out.println("refSemPred "+pred.getText());
super.refSemPred(pred);
//System.out.println("context().block: "+context().block);
if (context().currentAlt().atStart()) {
context().currentAlt().semPred = pred.getText();
}
else {
ActionElement a = new ActionElement(grammar, pred);
a.isSemPred = true;
addElementToCurrentAlt(a);
}
//System.out.println("DONE refSemPred "+pred.getText());
}
public void refStringLiteral(Token lit, Token label, int autoGenType, boolean lastInRule) {
super.refStringLiteral(lit, label, autoGenType, lastInRule);
if (grammar instanceof TreeWalkerGrammar && autoGenType == GrammarElement.AUTO_GEN_CARET) {
tool.error("^ not allowed in here for tree-walker", grammar.getFilename(), lit.getLine(), lit.getColumn());
}
StringLiteralElement sl = new StringLiteralElement(grammar, lit, autoGenType);
// If case-insensitive, then check each char of the stirng literal
if (grammar instanceof LexerGrammar && !((LexerGrammar)grammar).caseSensitive) {
for (int i = 1; i < lit.getText().length() - 1; i++) {
char c = lit.getText().charAt(i);
if (c < 128 && Character.toLowerCase(c) != c) {
tool.warning("Characters of string literal must be lowercase when caseSensitive=false", grammar.getFilename(), lit.getLine(), lit.getColumn());
break;
}
}
}
addElementToCurrentAlt(sl);
labelElement(sl, label);
// if ignore option is set, must add an optional call to the specified rule.
String ignore = ruleBlock.getIgnoreRule();
if (!lastInRule && ignore != null) {
addElementToCurrentAlt(createOptionalRuleRef(ignore, lit));
}
}
public void refToken(Token idAssign, Token t, Token label, Token args,
boolean inverted, int autoGenType, boolean lastInRule) {
if (grammar instanceof LexerGrammar) {
// In lexer, token references are really rule references
if (autoGenType == GrammarElement.AUTO_GEN_CARET) {
tool.error("AST specification ^ not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn());
}
if (inverted) {
tool.error("~TOKEN is not allowed in lexer", grammar.getFilename(), t.getLine(), t.getColumn());
}
refRule(idAssign, t, label, args, autoGenType);
// if ignore option is set, must add an optional call to the specified token rule.
String ignore = ruleBlock.getIgnoreRule();
if (!lastInRule && ignore != null) {
addElementToCurrentAlt(createOptionalRuleRef(ignore, t));
}
}
else {
// Cannot have token ref args or assignment outside of lexer
if (idAssign != null) {
tool.error("Assignment from token reference only allowed in lexer", grammar.getFilename(), idAssign.getLine(), idAssign.getColumn());
}
if (args != null) {
tool.error("Token reference arguments only allowed in lexer", grammar.getFilename(), args.getLine(), args.getColumn());
}
super.refToken(idAssign, t, label, args, inverted, autoGenType, lastInRule);
TokenRefElement te = new TokenRefElement(grammar, t, inverted, autoGenType);
addElementToCurrentAlt(te);
labelElement(te, label);
}
}
public void refTokenRange(Token t1, Token t2, Token label, int autoGenType, boolean lastInRule) {
if (grammar instanceof LexerGrammar) {
tool.error("Token range not allowed in lexer", grammar.getFilename(), t1.getLine(), t1.getColumn());
return;
}
super.refTokenRange(t1, t2, label, autoGenType, lastInRule);
TokenRangeElement tr = new TokenRangeElement(grammar, t1, t2, autoGenType);
if (tr.end < tr.begin) {
tool.error("Malformed range.", grammar.getFilename(), t1.getLine(), t1.getColumn());
return;
}
addElementToCurrentAlt(tr);
labelElement(tr, label);
}
public void refTreeSpecifier(Token treeSpec) {
context().currentAlt().treeSpecifier = treeSpec;
}
public void refWildcard(Token t, Token label, int autoGenType) {
super.refWildcard(t, label, autoGenType);
WildcardElement wc = new WildcardElement(grammar, t, autoGenType);
addElementToCurrentAlt(wc);
labelElement(wc, label);
}
/** Get ready to process a new grammar */
public void reset() {
super.reset();
blocks = new LList();
lastRuleRef = null;
ruleEnd = null;
ruleBlock = null;
nested = 0;
currentExceptionSpec = null;
grammarError = false;
}
public void setArgOfRuleRef(Token argAction) {
super.setArgOfRuleRef(argAction);
lastRuleRef.setArgs(argAction.getText());
}
public static void setBlock(AlternativeBlock b, AlternativeBlock src) {
b.setAlternatives(src.getAlternatives());
b.initAction = src.initAction;
//b.lookaheadDepth = src.lookaheadDepth;
b.label = src.label;
b.hasASynPred = src.hasASynPred;
b.hasAnAction = src.hasAnAction;
b.warnWhenFollowAmbig = src.warnWhenFollowAmbig;
b.generateAmbigWarnings = src.generateAmbigWarnings;
b.line = src.line;
b.greedy = src.greedy;
b.greedySet = src.greedySet;
}
public void setRuleOption(Token key, Token value) {
//((RuleBlock)context().block).setOption(key, value);
ruleBlock.setOption(key, value);
}
public void setSubruleOption(Token key, Token value) {
((AlternativeBlock)context().block).setOption(key, value);
}
public void synPred() {
if (context().block.not) {
tool.error("'~' cannot be applied to syntactic predicate", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
}
// create the right kind of object now that we know what that is
// and switch the list of alternatives. Adjust the stack of blocks.
// copy any init action also.
SynPredBlock b = new SynPredBlock(grammar);
setBlock(b, context().block);
BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
blocks.push(new BlockContext());
context().block = b;
context().blockEnd = old.blockEnd;
context().blockEnd.block = b;
}
public void zeroOrMoreSubRule() {
if (context().block.not) {
tool.error("'~' cannot be applied to (...)+ subrule", grammar.getFilename(), context().block.getLine(), context().block.getColumn());
}
// create the right kind of object now that we know what that is
// and switch the list of alternatives. Adjust the stack of blocks.
// copy any init action also.
ZeroOrMoreBlock b = new ZeroOrMoreBlock(grammar);
setBlock(b, context().block);
BlockContext old = (BlockContext)blocks.pop(); // remove old scope; we want new type of subrule
blocks.push(new BlockContext());
context().block = b;
context().blockEnd = old.blockEnd;
context().blockEnd.block = b;
}
}