/* * (C) Copyright 2001 Arnaud Bailly (arnaud.oqube@gmail.com), * Yves Roos (yroos@lifl.fr) and others. * * Licensed under the Apache License, Version 2.0 (the License); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an AS IS BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package rationals.converters.analyzers; import rationals.Automaton; import rationals.Builder; import rationals.Transition; 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<L, Tr extends Transition<L>, T extends Builder<L, Tr, T>> { private Lexer<L> 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<L> lexer) { this.lexico = lexer; } private Automaton<L, Tr, T> error(String message) throws ConverterException { throw new ConverterException("line " + lexico.lineNumber() + " , " + lexico.label() + " : " + message); } public Automaton<L, Tr, T> analyze() throws ConverterException { lexico.read() ; Automaton<L, Tr, T> r = E() ; if (lexico.current() != Lexer.END) error("end of expression expected") ; return r ; } private Automaton<L, Tr, T> E() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.OPEN : case Lexer.LABEL : { Automaton<L, Tr, T> a = T() ; Automaton<L, Tr, T> b = EP() ; return new Reducer<L, Tr, T>().transform(new Union<L, Tr, T>().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<L, Tr, T> 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<L, Tr, T>() ; case Lexer.UNION : { lexico.read() ; Automaton<L, Tr, T> a = T() ; Automaton<L, Tr, T> b = EP() ; return new Reducer<L, Tr, T>().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<L, Tr, T> T() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.OPEN : case Lexer.LABEL : { Automaton<L, Tr, T> a = S() ; Automaton<L, Tr, T> b = TS() ; return new Reducer<L, Tr, T>().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<L, Tr, T> 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<L, Tr, T> a = S() ; Automaton<L, Tr, T> b = TS() ; return new Reducer<L, Tr, T>().transform(new Shuffle<L, Tr, T>().transform(a , b)) ; } case Lexer.MIX : { lexico.read() ; Automaton<L, Tr, T> a = S() ; Automaton<L, Tr, T> b = TS() ; return new Reducer<L, Tr, T>().transform(new Mix().transform(a , b)) ; } case Lexer.STAR : case Lexer.ITERATION : case Lexer.INT : default : return error("concatenation expected") ; } } private Automaton<L, Tr, T> S() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.OPEN : case Lexer.LABEL : { Automaton<L, Tr, T> a = F() ; Automaton<L, Tr, T> b = TP() ; return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().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<L, Tr, T> TP() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.OPEN : case Lexer.LABEL :{ Automaton<L, Tr, T> a = F() ; Automaton<L, Tr, T> b = TP() ; return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().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<L, Tr, T> F() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.OPEN : case Lexer.LABEL : { Automaton<L, Tr, T> 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<L, Tr, T> B() throws ConverterException { switch(lexico.current()) { case Lexer.EPSILON : { Automaton<L, Tr, T> a = Automaton.epsilonAutomaton() ; lexico.read() ; return a ; } case Lexer.EMPTY : { Automaton<L, Tr, T> a = new Automaton<>() ; lexico.read() ; return a ; } case Lexer.OPEN : { lexico.read() ; Automaton<L, Tr, T> a = E() ; if (lexico.current() != Lexer.CLOSE) return error("( expected") ; lexico.read() ; return a ; } case Lexer.LABEL : { Automaton<L, Tr, T> 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<L, Tr, T> BP(Automaton<L, Tr, T> 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<L, Tr, T>().transform(new Star().transform(a)) ; } case Lexer.ITERATION : lexico.read() ; return new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(a, new Star().transform(a))) ; case Lexer.EPSILON : case Lexer.EMPTY : case Lexer.INT : { int value = lexico.value() ; lexico.read() ; Automaton<L, Tr, T> b = Automaton.epsilonAutomaton(); for (int i = 0 ; i < value ; i++) { b = new Reducer<L, Tr, T>().transform(new Concatenation<L, Tr, T>().transform(b , a)) ; } return b ; } default : return error("Unexpected character") ; } } }