Package dk.brics.string.grammar.operations

Source Code of dk.brics.string.grammar.operations.Grammar2MLFA

package dk.brics.string.grammar.operations;

import dk.brics.string.directedgraph.StronglyConnectedComponents;
import dk.brics.string.grammar.*;
import dk.brics.string.grammar.operations.Component.Recursion;
import dk.brics.string.mlfa.MLFA;
import dk.brics.string.mlfa.MLFAState;
import dk.brics.string.mlfa.MLFAStatePair;

/**
* Converter from strongly regular grammars to MLFAs.
*
* @see dk.brics.string.StringAnalysis
*/
public class Grammar2MLFA {

    private Grammar g;

    private StronglyConnectedComponents<Nonterminal, Component> comp;

    private MLFAState[] nt_states;

    /**
     * Constructs a new converter for the given grammar.
     */
    public Grammar2MLFA(Grammar g) {
        this.g = g;
    }

    /**
     * Constructs {@link MLFA} from the grammar.
     * The grammar is assumed to be approximated first (see {@link RegularApproximation}).
     *
     * @see #getMLFAStatePair(Nonterminal)
     */
    public MLFA convert() {
        comp = g.getComponents(true);
        nt_states = new MLFAState[g.getNumberOfNonterminals()];
        MLFA mlfa = new MLFA();
        for (Component c : comp.getComponents()) {
            convertComponent(c, mlfa);
        }
        return mlfa;
    }

    /**
     * Returns MLFA state pair representing initial and final state for the given nonterminal.
     * {@link #convert()} must be called first.
     */
    public MLFAStatePair getMLFAStatePair(Nonterminal n) {
        MLFAStatePair p;
        Component c = comp.getComponent(n);
        if (c.getRecursion() == Recursion.RIGHT || c.getRecursion() == Recursion.NONE) {
            p = new MLFAStatePair(nt_states[n.getKey()], c.getState());
        } else {
            p = new MLFAStatePair(c.getState(), nt_states[n.getKey()]);
        }
        p.setTaint(n.isTaint());
        return p;
    }

    private void convertComponent(final Component c, final MLFA mlfa) {
        if (c.getState() == null) {

            // make states
            c.setState(mlfa.addState());
            for (Nonterminal a : c.getNodes()) {
                nt_states[a.getKey()] = mlfa.addState();
            }

            // make transitions
            for (Nonterminal a : c.getNodes()) {
                for (Production p : a.getProductions()) {
                    if (c.getRecursion() == Recursion.BOTH) {
                        throw new RuntimeException("grammar is not strongly regular");
                    } else if (c.getRecursion() == Recursion.RIGHT || c.getRecursion() == Recursion.NONE) {
                        // component is right or non recursive
                        p.visitBy(a, new ProductionVisitor() {

                            public void visitUnitProduction(Nonterminal a, UnitProduction p) {
                                if (c.contains(p.getNonterminal())) {
                                    // A -> B  =>  (A)--e-->(B)
                                    mlfa.addEpsilonTransition(nt_states[a.getKey()], nt_states[p.getNonterminal().getKey()]);
                                } else {
                                    // A -> X  =>  (A)--[X]-->(T)
                                    convertComponent(comp.getComponent(p.getNonterminal()), mlfa);
                                    mlfa.addIdentityTransition(nt_states[a.getKey()], c.getState(), getMLFAStatePair(p.getNonterminal()));
                                }
                            }

                            public void visitPairProduction(Nonterminal a, PairProduction p) {
                                if (c.contains(p.getNonterminal2())) {
                                    // A -> X B  =>  (A)--[X]-->(B)
                                    convertComponent(comp.getComponent(p.getNonterminal1()), mlfa);
                                    mlfa.addIdentityTransition(nt_states[a.getKey()], nt_states[p.getNonterminal2().getKey()], getMLFAStatePair(p.getNonterminal1()));
                                } else {
                                    // A -> X Y  =>  (A)--[X]-->(R), (R)--[Y]-->(T)
                                    MLFAState r = mlfa.addState();
                                    convertComponent(comp.getComponent(p.getNonterminal1()), mlfa);
                                    convertComponent(comp.getComponent(p.getNonterminal2()), mlfa);
                                    mlfa.addIdentityTransition(nt_states[a.getKey()], r, getMLFAStatePair(p.getNonterminal1()));
                                    mlfa.addIdentityTransition(r, c.getState(), getMLFAStatePair(p.getNonterminal2()));
                                }
                            }

                            public void visitAutomatonProduction(Nonterminal a, AutomatonProduction p) {
                                // A -> reg  =>  (A)--[reg]-->(T)
                                mlfa.addAutomatonTransition(nt_states[a.getKey()], c.getState(), p.getAutomaton());
                            }

                            public void visitUnaryProduction(Nonterminal a, UnaryProduction p) {
                                // A -> op1(X)  =>  (A)--[op1(X)]-->(T)
                                convertComponent(comp.getComponent(p.getNonterminal()), mlfa);
                                mlfa.addUnaryTransition(nt_states[a.getKey()], c.getState(), p.getOperation(), getMLFAStatePair(p.getNonterminal()));
                            }

                            public void visitBinaryProduction(Nonterminal a, BinaryProduction p) {
                                // A -> op2(X,Y)  =>  (A)--[op2(X,Y)]-->(T)
                                convertComponent(comp.getComponent(p.getNonterminal1()), mlfa);
                                convertComponent(comp.getComponent(p.getNonterminal2()), mlfa);
                                mlfa.addBinaryTransition(nt_states[a.getKey()], c.getState(), p.getOperation(),
                                        getMLFAStatePair(p.getNonterminal1()), getMLFAStatePair(p.getNonterminal2()));
                            }

                            public void visitEpsilonProduction(Nonterminal a, EpsilonProduction p) {
                                // A -> ""  =>  (A)--e-->(T)
                                mlfa.addEpsilonTransition(nt_states[a.getKey()], c.getState());
                            }
                        });
                    } else {
                        // component is left recursive
                        p.visitBy(a, new ProductionVisitor() {

                            public void visitUnitProduction(Nonterminal a, UnitProduction p) {
                                if (c.contains(p.getNonterminal())) {
                                    // A -> B  =>  (B)---e--->(A)
                                    mlfa.addEpsilonTransition(nt_states[p.getNonterminal().getKey()], nt_states[a.getKey()]);
                                } else {
                                    // A -> X  =>  (S)--[X]-->(A)
                                    convertComponent(comp.getComponent(p.getNonterminal()), mlfa);
                                    mlfa.addIdentityTransition(c.getState(), nt_states[a.getKey()], getMLFAStatePair(p.getNonterminal()));
                                }
                            }

                            public void visitPairProduction(Nonterminal a, PairProduction p) {
                                if (c.contains(p.getNonterminal1())) {
                                    // A -> B X  =>  (B)--[X]-->(A)
                                    convertComponent(comp.getComponent(p.getNonterminal2()), mlfa);
                                    mlfa.addIdentityTransition(nt_states[p.getNonterminal1().getKey()], nt_states[a.getKey()], getMLFAStatePair(p.getNonterminal2()));
                                } else {
                                    // A -> X Y  =>  (S)--[X]-->(R), (R)--[Y]-->(A)
                                    MLFAState r = mlfa.addState();
                                    convertComponent(comp.getComponent(p.getNonterminal1()), mlfa);
                                    convertComponent(comp.getComponent(p.getNonterminal2()), mlfa);
                                    mlfa.addIdentityTransition(c.getState(), r, getMLFAStatePair(p.getNonterminal1()));
                                    mlfa.addIdentityTransition(r, nt_states[a.getKey()], getMLFAStatePair(p.getNonterminal2()));
                                }
                            }

                            public void visitAutomatonProduction(Nonterminal a, AutomatonProduction p) {
                                // A -> reg  =>  (S)--[reg]-->(A)
                                mlfa.addAutomatonTransition(c.getState(), nt_states[a.getKey()], p.getAutomaton());
                            }

                            public void visitUnaryProduction(Nonterminal a, UnaryProduction p) {
                                // A -> op1(X)  =>  (S)--[op1(X)]-->(A)
                                convertComponent(comp.getComponent(p.getNonterminal()), mlfa);
                                mlfa.addUnaryTransition(c.getState(), nt_states[a.getKey()], p.getOperation(), getMLFAStatePair(p.getNonterminal()));
                            }

                            public void visitBinaryProduction(Nonterminal a, BinaryProduction p) {
                                // A -> op2(X,Y)  =>  (S)--[op2(X,Y)]-->(A)
                                convertComponent(comp.getComponent(p.getNonterminal1()), mlfa);
                                convertComponent(comp.getComponent(p.getNonterminal2()), mlfa);
                                mlfa.addBinaryTransition(c.getState(), nt_states[a.getKey()], p.getOperation(),
                                        getMLFAStatePair(p.getNonterminal1()),
                                        getMLFAStatePair(p.getNonterminal2()));
                            }

                            public void visitEpsilonProduction(Nonterminal a, EpsilonProduction p) {
                                // A -> ""  =>  (S)---e--->(A)
                                mlfa.addEpsilonTransition(c.getState(), nt_states[a.getKey()]);
                            }
                        });
                    }
                }
            }
        }
    }
}
TOP

Related Classes of dk.brics.string.grammar.operations.Grammar2MLFA

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.