package rationals.converters.analyzers;
import rationals.Automaton;
import rationals.converters.ConverterException;
import rationals.transformations.Concatenation;
import rationals.transformations.Mix;
import rationals.transformations.Reducer;
import rationals.transformations.Shuffle;
import rationals.transformations.Star;
import rationals.transformations.Union;
// Grammar :
// E -> T E'
// E' -> + T E' | '/' '{' L '}' | eps
// T -> S T"
// T" -> '|' S T" | '#' S T" | eps
// S -> F T'
// T' -> F T' | eps
// F -> B B'
// B' -> * | int | ^ | eps
// B -> letter | 1 | 0 | ( E )
public class Parser {
private Lexer lexico ;
/**
* Parse given string using standard grammar and lexical analyzer.
*
* @param expression the expression to parse
* @see Lexer
* @see DefaultLexer
*/
public Parser(String expression) {
lexico = new DefaultLexer(expression) ;
}
/**
* Parse using the given lexer.
*
* @param lexer the lexer to use for parsing.
*/
public Parser(Lexer lexer) {
this.lexico = lexer;
}
private Automaton error(String message) throws ConverterException {
if (true) throw new ConverterException(
"line " + lexico.lineNumber() + " , " + lexico.label() + " : " + message) ;
return new Automaton() ;
}
public Automaton analyze() throws ConverterException {
lexico.read() ;
Automaton r = E() ;
if (lexico.current() != Lexer.END) error("end of expression expected") ;
return r ;
}
private Automaton E() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL : {
Automaton a = T() ;
Automaton b = EP() ;
return new Reducer().transform(new Union().transform(a , b)) ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.SHUFFLE :
case Lexer.MIX :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("expression expected") ;
}
}
private Automaton EP() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL : return error("union expected") ;
case Lexer.CLOSE :
case Lexer.END : return new Automaton() ;
case Lexer.UNION : {
lexico.read() ;
Automaton a = T() ;
Automaton b = EP() ;
return new Reducer().transform(new Union().transform(a , b)) ;
}
case Lexer.SHUFFLE :
case Lexer.MIX :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("union expected") ;
}
}
private Automaton T() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL : {
Automaton a = S() ;
Automaton b = TS() ;
return new Reducer().transform(
new Shuffle().transform(a , b)) ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.SHUFFLE :
case Lexer.MIX :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("expression expected") ;
}
}
private Automaton TS() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL :return error("concatenation expected") ;
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION : return Automaton.epsilonAutomaton() ;
case Lexer.SHUFFLE : {
lexico.read() ;
Automaton a = S() ;
Automaton b = TS() ;
return new Reducer().transform(
new Shuffle().transform(a , b)) ;
}
case Lexer.MIX :
{
lexico.read() ;
Automaton a = S() ;
Automaton b = TS() ;
return new Reducer().transform(
new Mix().transform(a , b)) ;
}
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("concatenation expected") ;
}
}
private Automaton S() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL : {
Automaton a = F() ;
Automaton b = TP() ;
return new Reducer().transform(
new Concatenation().transform(a , b)) ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.SHUFFLE :
case Lexer.MIX :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("expression expected") ;
}
}
private Automaton TP() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL :{
Automaton a = F() ;
Automaton b = TP() ;
return new Reducer().transform(
new Concatenation().transform(a , b)) ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.MIX :
case Lexer.SHUFFLE :return Automaton.epsilonAutomaton() ;
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("concatenation expected") ;
}
}
private Automaton F() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.OPEN :
case Lexer.LABEL : {
Automaton a = BP(B()) ;
return a ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.MIX :
case Lexer.SHUFFLE :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("factor expected") ;
}
}
private Automaton B() throws ConverterException {
switch(lexico.current()) {
case Lexer.EPSILON : {
Automaton a = Automaton.epsilonAutomaton() ;
lexico.read() ;
return a ;
}
case Lexer.EMPTY : {
Automaton a = new Automaton() ;
lexico.read() ;
return a ;
}
case Lexer.OPEN : {
lexico.read() ;
Automaton a = E() ;
if (lexico.current() != Lexer.CLOSE) return error("( expected") ;
lexico.read() ;
return a ;
}
case Lexer.LABEL : {
Automaton a = Automaton.labelAutomaton(lexico.label()) ;
lexico.read() ;
return a ;
}
case Lexer.CLOSE :
case Lexer.END :
case Lexer.SHUFFLE :
case Lexer.MIX :
case Lexer.UNION :
case Lexer.STAR :
case Lexer.ITERATION :
case Lexer.INT :
default : return error("factor expected") ;
}
}
private Automaton BP(Automaton a) throws ConverterException {
switch(lexico.current()) {
case Lexer.OPEN :
case Lexer.LABEL :
case Lexer.CLOSE :
case Lexer.END :
case Lexer.UNION :
case Lexer.MIX :
case Lexer.SHUFFLE :return a ;
case Lexer.STAR : {
lexico.read() ;
return new Reducer().transform(new Star().transform(a)) ;
}
case Lexer.ITERATION :
lexico.read() ;
return new Reducer().transform(
new Concatenation().transform(a ,
new Star().transform(a))) ;
case Lexer.EPSILON :
case Lexer.EMPTY :
case Lexer.INT : {
int value = lexico.value() ;
lexico.read() ;
Automaton b = Automaton.epsilonAutomaton() ;
for (int i = 0 ; i < value ; i++) {
b = new Reducer().transform(
new Concatenation().transform(b , a)) ;
}
return b ;
}
default : return error("Unexpected character") ;
}
}
}