Commit 87c7b159 authored by Sergio Pérez's avatar Sergio Pérez
Browse files

* Left Recursive Grammars transformed to Right Recursive avoiding infinite T...

* Left Recursive Grammars transformed to Right Recursive avoiding infinite T generations with suffix analysis
* Grammar.printGrammarInFile
parent 87a2afef
Loading
Loading
Loading
Loading
+145 −15
Original line number Diff line number Diff line
@@ -4,15 +4,13 @@ import edg.config.Config;
import edg.graph.*;
import edg.slicing.Phase;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.*;

public class GrammarConstraint extends EdgeConstraint {
	private final Grammar grammar;
	private final Node refNode;
	private boolean flowReached = false;
	private boolean leftRecursive = false;

	public GrammarConstraint(Grammar grammar, Node refNode)
	{
@@ -26,7 +24,9 @@ public class GrammarConstraint extends EdgeConstraint {
	}

	public boolean isFlowReached(){ return this.flowReached; }
	public boolean isLeftRecursive() { return this.leftRecursive; }
	public void setFlowReached(boolean flowReached){ this.flowReached = flowReached; }
	public void setLeftRecursive() { leftRecursive = true; }

	public boolean equals(Object object)
	{
@@ -140,32 +140,162 @@ public class GrammarConstraint extends EdgeConstraint {
					if (!(constraint instanceof GrammarConstraint))
						resolvedConstraintsList.addAll(constraint.resolve(phase, edg, edge, pendingConstraints, topConstraint, productionDepth + 1));
					else {
						Map<GrammarConstraint, List<Constraints>> newProcessedStates = new HashMap<>();
						newProcessedStates.putAll(processedStates);

						Map<GrammarConstraint, List<Constraints>> newProcessedStates = new HashMap<>(processedStates);
						GrammarConstraint gConstraint = (GrammarConstraint) constraint;

						if (newProcessedStates.containsKey(gConstraint)) {
							if (newProcessedStates.get(gConstraint).contains(pendingConstraints))
								continue productionLoop;
						}
						else {
						} else
							newProcessedStates.put(gConstraint, new LinkedList<>());

						if (this.isTailConstraintSequence(pendingConstraints))
							if (this.hasProcessedPrefix(pendingConstraints, gConstraint, newProcessedStates)) {
								resolvedConstraintsList.add(this.removeTailConstraintSequence(pendingConstraints));
								continue;
							}

						newProcessedStates.get(gConstraint).add(pendingConstraints);

						try {
							resolvedConstraintsList.addAll(
									((GrammarConstraint) constraint)
											.resolveProductions(phase, edg, edge, pendingConstraints, productionDepth, newProcessedStates));
						} catch (StackOverflowError e) {
							// IF AN OVERFLOW IS GIVEN WHEN EVALUATING A GRAMMAR CONSTRAINT
							// THE STACK IS EMPTIED AND THE NEXT CONSTRAINT IN THE SUMMARY IS EVALUATED
							resolvedConstraintsList.add(new Constraints());
						}
					}
				}
				pendingConstraintsList.clear();
				pendingConstraintsList.addAll(resolvedConstraintsList);
			}

			newConstraintsList.addAll(pendingConstraintsList);
			// TODO: Avoid duplicated results generated by different productions in newConstraintsList
			for (Constraints pendingConstraints : pendingConstraintsList)
				if (!newConstraintsList.contains(pendingConstraints))
					newConstraintsList.add(pendingConstraints);
		}

		return newConstraintsList;
	}

	private boolean isTailConstraintSequence(Constraints constraints) {
		if (constraints.getEdgeConstraints().isEmpty())
			return false;

		Constraints constraintsClone = (Constraints) constraints.clone();
		Constraint topConstraint = constraintsClone.popEdgeConstraint();
		if (!(topConstraint instanceof ListConstraint))
			return false;
		ListConstraint listConstraint =  (ListConstraint) topConstraint;
		if (listConstraint.getPosition() != ListConstraint.Position.T
				|| listConstraint.getOperation() != AccessConstraint.Operation.Add)
			return false;

		while (!constraintsClone.getEdgeConstraints().isEmpty() &&
				topConstraint instanceof ListConstraint) {
			ListConstraint lc = (ListConstraint) topConstraint;
			if (lc.getPosition() == ListConstraint.Position.T
					&& lc.getOperation() == AccessConstraint.Operation.Add)
				topConstraint = constraintsClone.popEdgeConstraint();
			else if (lc.getPosition() == ListConstraint.Position.H
					&& lc.getOperation() == AccessConstraint.Operation.Add)
				return true;
			else // +[]S
				return false;
		}
		return topConstraint instanceof LiteralConstraint || topConstraint instanceof ListComprehensionConstraint;
	}

	private boolean hasProcessedPrefix(Constraints constraints, GrammarConstraint grammarConstraint,
									   Map<GrammarConstraint,List<Constraints>> processed){
		Constraints constraintsClone = (Constraints) constraints.clone();
		List<Constraints> processedStates = processed.get(grammarConstraint);
		for (Constraints state : processedStates) {
			Constraints stateClone = (Constraints) state.clone();
			if(this.isValidPrefix(stateClone.getEdgeConstraints(), constraintsClone.getEdgeConstraints()))
				return true;
		}
		return false;
	}

	private boolean isValidPrefix(Stack<EdgeConstraint> stack1, Stack<EdgeConstraint> stack2) {
		if (stack1.isEmpty())
			return false;
		if (stack1.size() >= stack2.size())
			return false;

		// The last constraint of stack1 is a Tail Constraint
		Constraint lastConstraint = stack1.peek();

		if (!(lastConstraint instanceof ListConstraint))
			return false;

		ListConstraint listConstraint = (ListConstraint) lastConstraint;
		if(listConstraint.getPosition() != ListConstraint.Position.T
				|| listConstraint.getOperation() != AccessConstraint.Operation.Add)
			return false;

		// Remove same constraints from the bottom of the stack and
		// stores the last constraint before the list sequence

		Constraint cBeforeTailSeq = null;
		while (stack1.size() > 0){
			EdgeConstraint stk1Item = stack1.get(0);
			EdgeConstraint stk2Item = stack2.get(0);
			if (stk1Item.equals(stk2Item)){
				if (!(stk1Item instanceof ListConstraint))
					cBeforeTailSeq = stk1Item;
				else {
					ListConstraint lc = (ListConstraint) stk1Item;
					if (lc.getPosition() != ListConstraint.Position.T
							|| lc.getOperation() != AccessConstraint.Operation.Add)
						cBeforeTailSeq = stk1Item;
				}
				stack1.remove(0);
				stack2.remove(0);
			}
			else
				return false;
		}
		// The remaining constraints must be Tail Positive Constraints
		for (int i = 0; i < stack2.size(); i++) {
			EdgeConstraint ec = stack2.get(i);
			if (!(ec instanceof ListConstraint))
				return false;
			ListConstraint lc = (ListConstraint) ec;
			if (lc.getPosition() != ListConstraint.Position.T
					|| lc.getOperation() != AccessConstraint.Operation.Add)
				return false;
		}

		if (cBeforeTailSeq instanceof LiteralConstraint || cBeforeTailSeq instanceof ListComprehensionConstraint)
			return true;
		if (cBeforeTailSeq instanceof ListConstraint) {
			ListConstraint lc = (ListConstraint) cBeforeTailSeq;
			return lc.getPosition() == ListConstraint.Position.H &&
					lc.getOperation() == AccessConstraint.Operation.Add;
		}
		return false;
	}

	private Constraints removeTailConstraintSequence(Constraints stack) {
		Constraints stackClone = (Constraints) stack.clone();
		Constraint topConstraint = stackClone.popEdgeConstraint();

		while (topConstraint instanceof ListConstraint) {
			ListConstraint listConstraint = (ListConstraint) topConstraint;
			if (listConstraint.getPosition() == ListConstraint.Position.H
					&& listConstraint.getOperation() == AccessConstraint.Operation.Add)
				break;
			topConstraint = stackClone.popEdgeConstraint();
		}
		if (topConstraint instanceof LiteralConstraint)
			stackClone.pushEdgeConstraint((LiteralConstraint) topConstraint);

		stackClone.pushEdgeConstraint(new ListComprehensionConstraint(AccessConstraint.Operation.Add));

		return stackClone;
	}
}
+5 −0
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ public class LiteralConstraint extends EdgeConstraint {
    }
    protected List<Constraints> resolve(Phase phase, EDG edg, Edge edge, Constraints constraints, AccessConstraint topConstraint, int productionDepth)
    {
        if (phase.isInstanceof(Phase.Slicing)) {
            Constraints cs = new Constraints();
            return super.wrap(super.push(phase, cs));
        }
        super.check(phase, Phase.SummaryGeneration);
        return super.wrap(super.push(phase, constraints));
    }
    protected List<Constraints> resolve(Phase phase, EDG edg, Edge edge, Constraints constraints, LiteralConstraint topConstraint, int productionDepth){
+12 −17
Original line number Diff line number Diff line
@@ -22,12 +22,19 @@ public class SummaryEdgeGenerator extends EdgeGenerator
	{
		this.generateExternalSummaryEdges();
		this.generateInternalSummaryEdges();

		// REMOVE LEFT RECURSIVE GRAMMARS
		edg.getGrammar().transformLeftRecursiveGrammars(edg);
	}

	public void generateAsExternal(){
		this.generateSummaryEdgesAsExternal();
	}

	public void generateeOnlyExternal(){
		this.generateExternalSummaryEdges();
	}

	private void generateSummaryEdgesAsExternal() {
		final List<Node> calls = edg.getNodes(Node.Type.Call);

@@ -119,7 +126,7 @@ public class SummaryEdgeGenerator extends EdgeGenerator

				if (isFormalIn = this.isFormalIn(currentNode, initialNode))
				{
					Production p = new Production(constraints, nodeWork.getPreviousEdgeType() == Edge.Type.Control);
					Production p = new Production(constraints, nodeWork.getPreviousEdgeType() == Edge.Type.Control, currentNode);
					final List<Node> nodesToContinue =
							this.createSummaryEdges(currentNode, p);
					this.rependWorks(workList, nodesToContinue);
@@ -180,12 +187,10 @@ public class SummaryEdgeGenerator extends EdgeGenerator
			grammarConstraint.setFlowReached(true);
			grammar.removeControlReachingProductions(grammarConstraint);
		}
		if (isLeftRecursiveGrammar(grammarConstraint, production)) {
			production.setLeftRecursive();
		}
		else{

		this.edg.addProduction(grammarConstraint, production);
		}
		if (production.isLeftRecursive())
			grammarConstraint.setLeftRecursive();

		final List<Node> nodesToContinue = new LinkedList<>();
		if (!isNewGrammarTerm)
@@ -214,16 +219,6 @@ public class SummaryEdgeGenerator extends EdgeGenerator
		}
	}

	private boolean isLeftRecursiveGrammar(GrammarConstraint grammarConstraint, Constraints constraints)
	{
		if (constraints.getEdgeConstraints().isEmpty())
			return false;

		String grammarId = grammarConstraint.getRefNode().getId() + "";
		String stackBottomTerm = constraints.getEdgeConstraints().firstElement().toString();
		return grammarId.equals(stackBottomTerm);
	}

	private void buildSummaryEdges(Node call, Node callee) {
		Node scopeNode = this.edg.getChild(callee, Node.Type.Scope);
		Node scopeExpr = this.edg.getChild(scopeNode, Node.Type.Value);
+84 −4
Original line number Diff line number Diff line
package edg.graph;

import edg.constraint.Constraint;
import edg.constraint.GrammarConstraint;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -12,12 +17,15 @@ public class Grammar
	private final Map<Node, GrammarConstraint> grammarConstraints = new HashMap<>();
	private final Map<GrammarConstraint, List<Production>> grammar = new HashMap<>();

	public boolean existsTerm(GrammarConstraint grammarConstraint) {
		return this.getProductions(grammarConstraint) != null;
	}

	private List<Production> createProductions(GrammarConstraint grammarConstraint)
	{
		List<Production> productions = this.getProductions(grammarConstraint);

		if (productions == null)
		{
		if (productions == null) {
			productions = new LinkedList<>();
			this.grammar.put(grammarConstraint, productions);
		}
@@ -29,8 +37,7 @@ public class Grammar
		final Node refNode = grammarConstraint.getRefNode();
		GrammarConstraint grammarConstraint0 = this.grammarConstraints.get(refNode);

		if (grammarConstraint0 == null)
		{
		if (grammarConstraint0 == null) {
			grammarConstraint0 = grammarConstraint;
			this.grammarConstraints.put(refNode, grammarConstraint0);
		}
@@ -80,4 +87,77 @@ public class Grammar
			return new GrammarConstraint(this, refNode);
		return gc;
	}

	public void transformLeftRecursiveGrammars(EDG edg) {

		List<GrammarConstraint> leftRecursiveConstraints = new LinkedList<>();

		for (GrammarConstraint g : this.grammarConstraints.values()) {
			if (!g.isLeftRecursive())
				continue;
			leftRecursiveConstraints.add(g);
		}

		for (GrammarConstraint g : leftRecursiveConstraints) {
			// NEW GRAMMAR NODE IS THE CORRESPONDING EXPRESSION NODE OF THE GIVEN RESULT NODE
			GrammarConstraint newGrammarConstraint =
					new GrammarConstraint(this, edg.getNodeFromRes(g.getRefNode()));
			if (!this.existsTerm(newGrammarConstraint)) {
				this.createProductions(newGrammarConstraint);

				// THIS PRODUCTION CAN BE OMITTED AND ALL WILL WORK THE SAME WAY
				// this.insertEmptyProduction(newGrammarConstraint);
			}

			List<Production> productions = this.getProductions(g);
			List<Production> leftRecursiveProductions = new LinkedList<>();

			for (Production p : productions) {
				if (p.isLeftRecursive()){
					leftRecursiveProductions.add(p);
					Production rightRecursiveProd = p.createRightRecursiveProduction(newGrammarConstraint);
					this.addProduction(newGrammarConstraint, rightRecursiveProd);
				} else
					p.getEdgeConstraints().add(newGrammarConstraint);
			}

			productions.removeAll(leftRecursiveProductions);
		}
	}

	private void insertEmptyProduction(GrammarConstraint grammarConstraint) {
		this.addProduction(grammarConstraint, new Production(false, false));
	}

	public void printGrammarInFile(String path){
		new File(path).delete();
		FileWriter timeFileWriter;
		PrintWriter timeWriter = null;
		try {
			timeFileWriter = new FileWriter(path, true);
			timeWriter = new PrintWriter(timeFileWriter);

			for(Node n : this.grammarConstraints.keySet()){
				timeWriter.printf("%d => \n",n.getId());
				GrammarConstraint gc = grammarConstraints.get(n);
				List<Production> productions = this.getProductions(gc);
				for (Production p : productions){
					timeWriter.printf("\t");
					if (p.getEdgeConstraints().isEmpty())
						timeWriter.printf("empty");
					else
						for (Constraint c : p.getEdgeConstraints())
							timeWriter.printf("%s ", c.toString());
					timeWriter.printf("\n");
				}
				timeWriter.printf("\n");
			}

		} catch (IOException e) {
			System.out.println("FILE NOT FOUND ERROR");
		} finally {
			if (timeWriter != null)
				timeWriter.close();
		}
	}
}
 No newline at end of file
+41 −2
Original line number Diff line number Diff line
package edg.graph;

import edg.constraint.Constraints;
import edg.constraint.EdgeConstraint;
import edg.constraint.GrammarConstraint;

import java.util.Stack;

public class Production extends Constraints {

    private boolean controlReached;
    private final boolean controlReached;
    private final boolean leftRecursive;

    public Production(boolean controlReached, boolean leftRecursive){
        super();
        this.controlReached = controlReached;
        this.leftRecursive = leftRecursive;
    }

    public Production(Constraints constraints, boolean controlReached){
    public Production(Constraints constraints, boolean controlReached, Node formalIn){
        this.nodeConstraints = constraints.getNodeConstraints();
        this.edgeConstraints = constraints.getEdgeConstraints();
        this.controlReached = controlReached;
        this.leftRecursive = this.evaluateRecursiveTerm(formalIn);
    }

    public boolean isLeftRecursive() { return leftRecursive; }
    public boolean isControlReached() { return this.controlReached; }

    public boolean evaluateRecursiveTerm(Node grammarNode) {
        if (this.getEdgeConstraints().isEmpty())
            return false;

        String grammarId = grammarNode.getId() + "";
        String stackBottomTerm = this.getEdgeConstraints().firstElement().toString();
        return grammarId.equals(stackBottomTerm) && this.getEdgeConstraints().size() > 1;
    }

    public Object clone()
    {
        final Production production = new Production(this.controlReached, false);

        production.nodeConstraints.addAll(this.nodeConstraints);
        production.edgeConstraints.addAll(this.edgeConstraints);

        return production;
    }

    public Production createRightRecursiveProduction(GrammarConstraint gc){
        Production p = (Production) this.clone();
        p.getEdgeConstraints().remove(0);
        p.getEdgeConstraints().add(gc);
        return p;
    }
}
Loading