});
for (Iterator i = tokens.entrySet().iterator(); i.hasNext();)
{
Map.Entry e = (Map.Entry) i.next();
String name = (String) e.getKey();
Symbol symb = (Symbol) e.getValue();
log.warning(symb, "declared terminal is not used by the grammar");
symbols.remove(name);
n_terms--;
}
root.accept(new DeclarationWalker()
{
/** Next unused highest precedence */
private int precedence = Integer.MAX_VALUE;
private Set imports = new HashSet();
private Set impls = new HashSet();
public void visit(GrammarTreeRoot root)
{
imports.add(Grammar.EBNF_LIST_TYPE);
imports.add("beaver.*");
super.visit(root);
grammar.imports = (String[]) imports.toArray(new String[imports.size()]);
grammar.impls = (String[]) impls.toArray(new String[impls.size()]);
}
public void visit(Declaration.Header decl)
{
if (grammar.prolog == null)
{
String text = (String) decl.code.value;
int i = 0;
char c;
while (Character.isWhitespace(c = text.charAt(i)) || c == '\n') i++;
grammar.prolog = i > 0 ? text.substring(i) : text;
}
else
{
grammar.prolog += (String) decl.code.value;
}
}
public void visit(Declaration.PackageName decl)
{
if (grammar.package_name != null)
{
log.warning(decl.name, "Parser package has been already defined as \"" + grammar.package_name + "\", new name ignored.");
}
else
{
grammar.package_name = decl.getName();
}
}
public void visit(Declaration.Implements decl)
{
for (int i = 0; i < decl.symbols.length; i++)
{
impls.add(decl.symbols[i].value);
}
}
public void visit(Declaration.Imports decl)
{
for (int i = 0; i < decl.symbols.length; i++)
{
imports.add(decl.symbols[i].value);
}
}
public void visit(Declaration.ClassName decl)
{
if (grammar.class_name != null)
{
log.warning(decl.name, "Parser class name has been already defined as \"" + grammar.class_name + "\", new name ignored.");
}
else
{
grammar.class_name = decl.getName();
}
}
public void visit(Declaration.ClassCode decl)
{
if (grammar.class_code != null)
{
log.warning(decl.code, "Embedded parser class code has been already defined, new code ignored.");
}
else
{
grammar.class_code = trimCode(getCode(decl));
}
}
public void visit(Declaration.ConstructorCode decl)
{
if (grammar.init_code != null)
{
log.warning(decl.code, "Parser initialization code has been already defined, new code ignored.");
}
else
{
grammar.init_code = trimCode(getCode(decl));
}
}
public void visit(Declaration.Goal decl)
{
String sym_name = decl.getName();
GrammarSymbol sym = (GrammarSymbol) symbols.get(sym_name);
if (sym == null)
{
log.error(decl.name, "Symbol is undefined");
}
else if (sym instanceof Terminal)
{
log.error(decl.name, "Symbol is a terminal");
}
else
{
goals.add(sym);
nonterms.remove(sym_name); // because it is used
}
}
public void visit(Declaration.TypeOf decl)
{
String type = decl.getTypeName();
for (int i = 0; i < decl.symbols.length; i++)
{
GrammarSymbol sym = (GrammarSymbol) symbols.get(decl.symbols[i].value);
if (sym == null)
{
log.error(decl.symbols[i], "Symbol is undefined");
}
else if (sym.type != null)
{
log.error(decl.symbols[i], "Symbol's Java type is already set to \"" + sym.type + "\"");
}
else
{
sym.type = type;
}
}
}
public void visit(Declaration.LeftAssoc decl)
{
setPrecedence(decl, Terminal.Associativity.LEFT);
}
public void visit(Declaration.RightAssoc decl)
{
setPrecedence(decl, Terminal.Associativity.RIGHT);
}
public void visit(Declaration.NonAssoc decl)
{
setPrecedence(decl, Terminal.Associativity.NONE);
}
private void setPrecedence(Declaration.SymbolsContainer decl, Terminal.Associativity type)
{
for (int i = 0; i < decl.symbols.length; i++)
{
String sym_name = (String) decl.symbols[i].value;
GrammarSymbol sym = (GrammarSymbol) symbols.get(sym_name);
if (sym == null)
{
log.warning(decl.symbols[i], "Symbol is not used by the grammar");
}
else if (sym instanceof NonTerminal)
{
log.error(decl.symbols[i], "Symbol is a non-terminal.");
}
else
{
((Terminal) sym).setPrecedence(precedence, type);
}
}
precedence--;
}
private String getCode(Declaration.CodeContainer decl)
{
String code = decl.getCode();
if (!checkBraces(code))
{
log.warning(decl, "Java code has unbalanced braces");
}
return code;
}
});
for (Iterator i = nonterms.entrySet().iterator(); i.hasNext();)
{
Map.Entry e = (Map.Entry) i.next();
String name = (String) e.getKey();
Symbol symb = (Symbol) e.getValue();
log.warning(symb, "non-terminal is not used by the grammar");
symbols.remove(name);
n_nonterms--;
}