package antlr;
/* ANTLR Translator Generator
* Project led by Terence Parr at http://www.cs.usfca.edu
* Software rights: http://www.antlr.org/license.html
*
* $Id: //depot/code/org.antlr/release/antlr-2.7.7/antlr/RuleBlock.java#2 $
*/
import antlr.collections.impl.
Vector;
import java.util.
Hashtable;
/**A list of alternatives and info contained in
* the rule definition.
*/
public class
RuleBlock extends
AlternativeBlock {
protected
String ruleName;
protected
String argAction = null; // string for rule arguments [...]
protected
String throwsSpec = null;
protected
String returnAction = null;// string for rule return type(s) <...>
protected
RuleEndElement endNode; // which node ends this rule?
// Generate literal-testing code for lexer rule?
protected boolean
testLiterals = false;
Vector labeledElements; // List of labeled elements found in this rule
// This is a list of AlternativeElement (or subclass)
protected boolean[]
lock; // for analysis; used to avoid infinite loops
// 1..k
protected
Lookahead cache[];// Each rule can cache it's lookahead computation.
// This cache contains an epsilon
// imaginary token if the FOLLOW is required. No
// FOLLOW information is cached here.
// The FIRST(rule) is stored in this cache; 1..k
// This set includes FIRST of all alts.
Hashtable exceptionSpecs; // table of String-to-ExceptionSpec.
// grammar-settable options
protected boolean
defaultErrorHandler = true;
protected
String ignoreRule = null;
/** Construct a named rule. */
public
RuleBlock(
Grammar g,
String r) {
super(
g);
ruleName =
r;
labeledElements = new
Vector();
cache = new
Lookahead[
g.
maxk + 1];
exceptionSpecs = new
Hashtable();
setAutoGen(
g instanceof
ParserGrammar);
}
/** Construct a named rule with line number information */
public
RuleBlock(
Grammar g,
String r, int
line, boolean
doAutoGen_) {
this(
g,
r);
this.
line =
line;
setAutoGen(
doAutoGen_);
}
public void
addExceptionSpec(
ExceptionSpec ex) {
if (
findExceptionSpec(
ex.
label) != null) {
if (
ex.
label != null) {
grammar.
antlrTool.
error("Rule '" +
ruleName + "' already has an exception handler for label: " +
ex.
label);
}
else {
grammar.
antlrTool.
error("Rule '" +
ruleName + "' already has an exception handler");
}
}
else {
exceptionSpecs.
put((
ex.
label == null ? "" :
ex.
label.
getText()),
ex);
}
}
public
ExceptionSpec findExceptionSpec(
Token label) {
return (
ExceptionSpec)
exceptionSpecs.
get(
label == null ? "" :
label.
getText());
}
public
ExceptionSpec findExceptionSpec(
String label) {
return (
ExceptionSpec)
exceptionSpecs.
get(
label == null ? "" :
label);
}
public void
generate() {
grammar.
generator.
gen(this);
}
public boolean
getDefaultErrorHandler() {
return
defaultErrorHandler;
}
public
RuleEndElement getEndElement() {
return
endNode;
}
public
String getIgnoreRule() {
return
ignoreRule;
}
public
String getRuleName() {
return
ruleName;
}
public boolean
getTestLiterals() {
return
testLiterals;
}
public boolean
isLexerAutoGenRule() {
return
ruleName.
equals("nextToken");
}
public
Lookahead look(int
k) {
return
grammar.
theLLkAnalyzer.
look(
k, this);
}
public void
prepareForAnalysis() {
super.prepareForAnalysis();
lock = new boolean[
grammar.
maxk + 1];
}
// rule option values
public void
setDefaultErrorHandler(boolean
value) {
defaultErrorHandler =
value;
}
public void
setEndElement(
RuleEndElement re) {
endNode =
re;
}
public void
setOption(
Token key,
Token value) {
if (
key.
getText().
equals("defaultErrorHandler")) {
if (
value.
getText().
equals("true")) {
defaultErrorHandler = true;
}
else if (
value.
getText().
equals("false")) {
defaultErrorHandler = false;
}
else {
grammar.
antlrTool.
error("Value for defaultErrorHandler must be true or false",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
}
else if (
key.
getText().
equals("testLiterals")) {
if (!(
grammar instanceof
LexerGrammar)) {
grammar.
antlrTool.
error("testLiterals option only valid for lexer rules",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
else {
if (
value.
getText().
equals("true")) {
testLiterals = true;
}
else if (
value.
getText().
equals("false")) {
testLiterals = false;
}
else {
grammar.
antlrTool.
error("Value for testLiterals must be true or false",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
}
}
else if (
key.
getText().
equals("ignore")) {
if (!(
grammar instanceof
LexerGrammar)) {
grammar.
antlrTool.
error("ignore option only valid for lexer rules",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
else {
ignoreRule =
value.
getText();
}
}
else if (
key.
getText().
equals("paraphrase")) {
if (!(
grammar instanceof
LexerGrammar)) {
grammar.
antlrTool.
error("paraphrase option only valid for lexer rules",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
else {
// find token def associated with this rule
TokenSymbol ts =
grammar.
tokenManager.
getTokenSymbol(
ruleName);
if (
ts == null) {
grammar.
antlrTool.
panic("cannot find token associated with rule " +
ruleName);
}
ts.
setParaphrase(
value.
getText());
}
}
else if (
key.
getText().
equals("generateAmbigWarnings")) {
if (
value.
getText().
equals("true")) {
generateAmbigWarnings = true;
}
else if (
value.
getText().
equals("false")) {
generateAmbigWarnings = false;
}
else {
grammar.
antlrTool.
error("Value for generateAmbigWarnings must be true or false",
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
}
else {
grammar.
antlrTool.
error("Invalid rule option: " +
key.
getText(),
grammar.
getFilename(),
key.
getLine(),
key.
getColumn());
}
}
public
String toString() {
String s = " FOLLOW={";
Lookahead cache[] =
endNode.
cache;
int
k =
grammar.
maxk;
boolean
allNull = true;
for (int
j = 1;
j <=
k;
j++) {
if (
cache[
j] == null) continue;
s +=
cache[
j].
toString(",",
grammar.
tokenManager.
getVocabulary());
allNull = false;
if (
j <
k &&
cache[
j + 1] != null)
s += ";";
}
s += "}";
if (
allNull)
s = "";
return
ruleName + ": " + super.toString() + " ;" +
s;
}
}