package org.watertemplate.interpreter.parser;
import org.watertemplate.interpreter.parser.exception.ParseException;
import java.util.ArrayList;
import java.util.List;
import static org.watertemplate.interpreter.parser.Terminal.*;
enum NonTerminal implements GrammarSymbol {
IF_COMMAND {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.If());
symbols.add(new Production.IfElse());
}
},
FOR_COMMAND {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.For());
symbols.add(new Production.ForElse());
}
},
NESTED_PROP {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.NestedProperty());
symbols.add(new Production.Empty());
}
},
ID {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.Id());
symbols.add(PROPERTY_KEY);
}
},
EVALUATION {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.Evaluation());
}
},
STATEMENT {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(FOR_COMMAND);
symbols.add(IF_COMMAND);
symbols.add(EVALUATION);
symbols.add(TEXT);
}
},
STATEMENTS {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.Statements(STATEMENT, STATEMENTS));
symbols.add(new Production.Empty());
}
},
TEMPLATE {
@Override
void addProductions(final List<GrammarSymbol> symbols) {
symbols.add(new Production.Statements(STATEMENTS, END_OF_INPUT));
}
};
static {
for (final NonTerminal nonTerminal : NonTerminal.values()) {
nonTerminal.addProductions(nonTerminal.symbols);
}
}
private final List<GrammarSymbol> symbols = new ArrayList<>();
abstract void addProductions(final List<GrammarSymbol> symbols);
public final AbstractSyntaxTree buildAbstractSyntaxTree(final TokenStream tokenStream) throws ParseException {
ParseException lastException = null;
for (GrammarSymbol symbol : symbols) {
try {
return symbol.buildAbstractSyntaxTree(tokenStream);
} catch (ParseException e) {
lastException = e;
}
}
throw lastException;
}
}