Commit 90c10929 authored by Alexander Weigl's avatar Alexander Weigl

matcher api and bugfixes

parent db98546f
Pipeline #10521 passed with stage
in 1 minute and 54 seconds
......@@ -75,7 +75,7 @@ literals :
</pre>*/
matchPattern
: MATCH ( TERM_LITERAL | ID)
: MATCH pattern=expression
(USING LBRACKET argList RBRACKET)?
;
......
......@@ -2,9 +2,11 @@ package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.DefaultASTVisitor;
import edu.kit.formal.proofscriptparser.ast.*;
import lombok.Getter;
import lombok.Setter;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* Class handling evaluation of expressions (visitor for expressions)
......@@ -12,11 +14,13 @@ import java.util.Stack;
* @author S.Grebing
*/
public class Evaluator extends DefaultASTVisitor<Value> {
private State currentState;
private Stack<List<GoalNode>> matchedGoals = new Stack<>();
private EvaluatorABI abi;
private GoalNode currentState;
private List<VariableAssignment> matchedVariables = new ArrayList<>();
@Getter
@Setter
private MatcherApi matcher;
public Evaluator(State s) {
public Evaluator(GoalNode s) {
this.currentState = s;
}
......@@ -46,9 +50,16 @@ public class Evaluator extends DefaultASTVisitor<Value> {
*/
@Override
public Value visit(MatchExpression match) {
Value pattern = (Value) match.getPattern().accept(this);
List<VariableAssignment> va = null;
if (pattern.getType() == Type.STRING) {
va = matcher.matchLabel(currentState, (String) pattern.getData());
} else if (pattern.getType() == Type.TERM) {
va = matcher.matchSeq(currentState, (String) pattern.getData());
}
return Value.TRUE;
return va != null && va.size() > 0 ? Value.TRUE : Value.FALSE;
}
/**
......@@ -71,8 +82,7 @@ public class Evaluator extends DefaultASTVisitor<Value> {
public Value visit(Variable variable) {
//get variable value
String id = variable.getIdentifier();
GoalNode n = currentState.getSelectedGoalNode();
Value v = n.lookupVarValue(id);
Value v = currentState.lookupVarValue(id);
if (v != null) {
return v;
} else {
......
package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.ast.Type;
import lombok.Getter;
/**
* Objects of this class represent a GoalNode in a script state
......@@ -9,8 +10,8 @@ import edu.kit.formal.proofscriptparser.ast.Type;
* @author S.Grebing
*/
public class GoalNode {
//TODO this is only for testing, later Sequent object or similar
@Getter
private String sequent;
private VariableAssignment assignments;
......@@ -18,9 +19,7 @@ public class GoalNode {
private GoalNode parent;
public GoalNode(GoalNode parent, String seq) {
if (parent == null) {
this.assignments = new VariableAssignment(null);
}
this.assignments = new VariableAssignment(parent == null ? null : parent.assignments);
this.parent = parent;
this.sequent = seq;
}
......@@ -29,11 +28,6 @@ public class GoalNode {
return assignments;
}
public GoalNode setAssignments(VariableAssignment assignments) {
this.assignments = assignments;
return this;
}
public GoalNode getParent() {
return parent;
}
......@@ -47,7 +41,6 @@ public class GoalNode {
* @return value of variable if it exists
*/
public Value lookupVarValue(String varname) {
Value v = assignments.getValue(varname);
if (v != null) {
return v;
......@@ -85,8 +78,7 @@ public class GoalNode {
* @param t
*/
public void addVarDecl(String name, Type t) {
this.assignments = getAssignments().addVariable(name, t);
getAssignments().addVariable(name, t);
}
/**
......@@ -107,16 +99,13 @@ public class GoalNode {
/**
* Enter new variable scope and push onto stack
*/
public void enterNewVarScope() {
this.assignments = this.assignments.push();
public VariableAssignment enterNewVarScope() {
assignments = assignments.push();
return assignments;
}
public void exitNewVarScope() {
public VariableAssignment exitNewVarScope() {
this.assignments = this.assignments.pop();
return assignments;
}
public VariableAssignment peek() {
return null;
}
}
......@@ -60,7 +60,7 @@ public class Interpreter<T> extends DefaultASTVisitor<T> {
if (node != null) {
Type t = node.lookUpType(var.getIdentifier());
if (t != null) {
Evaluator eval = new Evaluator((State) state);
Evaluator eval = new Evaluator(state.getSelectedGoalNode());
Value v = (Value) expr.accept(eval);
node.getAssignments().setVar(var.getIdentifier(), v);
} else {
......
package edu.kit.formal.interpreter;
import java.util.List;
/**
* @author Alexander Weigl
* @version 1 (16.05.17)
*/
public interface EvaluatorABI {
public interface MatcherApi {
List<VariableAssignment> matchLabel(GoalNode currentState, String label);
List<VariableAssignment> matchSeq(GoalNode currentState, String data);
}
......@@ -22,6 +22,10 @@ public class VariableAssignment {
this.parent = parent;
}
public VariableAssignment() {
this(null);
}
public VariableAssignment getParent() {
return parent;
}
......
......@@ -23,7 +23,6 @@ package edu.kit.formal.proofscriptparser;
*/
import edu.kit.formal.proofscriptparser.ast.*;
import java.util.ArrayList;
......@@ -37,46 +36,58 @@ import java.util.Set;
* @version 1 (29.04.17)
*/
public class ASTChanger extends DefaultASTVisitor<ASTNode> {
@Override public ProofScript visit(ProofScript proofScript) {
@Override
public ProofScript visit(ProofScript proofScript) {
proofScript.setBody((Statements) proofScript.getBody().accept(this));
return proofScript;
}
@Override public AssignmentStatement visit(AssignmentStatement assign) {
@Override
public AssignmentStatement visit(AssignmentStatement assign) {
assign.setRhs((Expression) assign.getRhs().accept(this));
assign.setLhs((Variable) assign.getLhs().accept(this));
return assign;
}
@Override public Expression visit(BinaryExpression e) {
@Override
public Expression visit(BinaryExpression e) {
e.setLeft((Expression) e.getLeft().accept(this));
e.setRight((Expression) e.getRight().accept(this));
return e;
}
@Override public MatchExpression visit(MatchExpression match) {
if (match.getTerm() != null)
match.setTerm((TermLiteral) match.getTerm().accept(this));
@Override
public MatchExpression visit(MatchExpression match) {
if (match.getSignature() != null)
match.setSignature((Signature)
match.getSignature().accept(this));
match.setPattern((Expression) match.getPattern().accept(this));
return match;
}
@Override public TermLiteral visit(TermLiteral term) {
@Override
public TermLiteral visit(TermLiteral term) {
return term;
}
@Override public StringLiteral visit(StringLiteral string) {
@Override
public StringLiteral visit(StringLiteral string) {
return string;
}
@Override public Variable visit(Variable variable) {
@Override
public Variable visit(Variable variable) {
return variable;
}
@Override public BooleanLiteral visit(BooleanLiteral bool) {
@Override
public BooleanLiteral visit(BooleanLiteral bool) {
return bool;
}
@Override public Statements visit(Statements statements) {
@Override
public Statements visit(Statements statements) {
ArrayList copy = new ArrayList<>(statements.size());
for (Statement statement : statements) {
copy.add(statement.accept(this));
......@@ -86,44 +97,52 @@ public class ASTChanger extends DefaultASTVisitor<ASTNode> {
return statements;
}
@Override public IntegerLiteral visit(IntegerLiteral integer) {
@Override
public IntegerLiteral visit(IntegerLiteral integer) {
return integer;
}
@Override public CasesStatement visit(CasesStatement casesStatement) {
@Override
public CasesStatement visit(CasesStatement casesStatement) {
for (CaseStatement c : casesStatement.getCases()) {
c.accept(this);
}
return casesStatement;
}
@Override public CaseStatement visit(CaseStatement caseStatement) {
@Override
public CaseStatement visit(CaseStatement caseStatement) {
caseStatement.getGuard().accept(this);
caseStatement.getBody().accept(this);
return caseStatement;
}
@Override public CallStatement visit(CallStatement call) {
@Override
public CallStatement visit(CallStatement call) {
call.setParameters((Parameters) call.getParameters().accept(this));
return call;
}
@Override public ASTNode visit(TheOnlyStatement theOnly) {
@Override
public ASTNode visit(TheOnlyStatement theOnly) {
theOnly.setBody((Statements) theOnly.getBody().accept(this));
return theOnly;
}
@Override public ASTNode visit(ForeachStatement foreach) {
@Override
public ASTNode visit(ForeachStatement foreach) {
foreach.setBody((Statements) foreach.getBody().accept(this));
return foreach;
}
@Override public ASTNode visit(RepeatStatement repeat) {
@Override
public ASTNode visit(RepeatStatement repeat) {
repeat.setBody((Statements) repeat.getBody().accept(this));
return repeat;
}
@Override public ASTNode visit(Signature signature) {
@Override
public ASTNode visit(Signature signature) {
Set<Map.Entry<Variable, Type>> entries = signature.entrySet();
signature.clear();
for (Map.Entry<Variable, Type> e : entries) {
......@@ -132,7 +151,8 @@ public class ASTChanger extends DefaultASTVisitor<ASTNode> {
return signature;
}
@Override public ASTNode visit(Parameters parameters) {
@Override
public ASTNode visit(Parameters parameters) {
Set<Map.Entry<Variable, Expression>> entries = parameters.entrySet();
parameters.clear();
for (Map.Entry<Variable, Expression> e : entries) {
......@@ -141,7 +161,8 @@ public class ASTChanger extends DefaultASTVisitor<ASTNode> {
return parameters;
}
@Override public ASTNode visit(UnaryExpression e) {
@Override
public ASTNode visit(UnaryExpression e) {
e.setExpression((Expression) e.getExpression().accept(this));
return e;
}
......
......@@ -50,9 +50,8 @@ public class ASTTraversal<T> implements Visitor<T> {
}
@Override public T visit(MatchExpression match) {
if (match.getTerm() != null)
match.getTerm().accept(this);
match.getPattern().accept(this);
match.getSignature().accept(this);
return null;
}
......
......@@ -119,10 +119,7 @@ public class PrettyPrinter extends DefaultASTVisitor<Void> {
public Void visit(MatchExpression match) {
s.append("match ");
String prefix = getWhitespacePrefix();
if (match.getTerm() != null) {
match.getTerm().accept(this);
}
match.getPattern().accept(this);
if (!match.getSignature().isEmpty()) {
if (getCurrentLineLength() > maxWidth) {
......
......@@ -239,11 +239,7 @@ public class TransformAst implements ScriptLanguageVisitor<Object> {
match.setRuleContext(ctx);
if (ctx.argList() != null)
match.setSignature((Signature) ctx.argList().accept(this));
if (ctx.TERM_LITERAL() != null) {
match.setTerm(new TermLiteral(ctx.TERM_LITERAL().getText()));
} else {
match.setVariable(new Variable(ctx.ID().getSymbol()));
}
match.setPattern((Expression) ctx.pattern.accept(this));
return match;
}
......
......@@ -23,9 +23,8 @@ package edu.kit.formal.proofscriptparser.ast;
*/
import edu.kit.formal.proofscriptparser.ScriptLanguageParser;
import edu.kit.formal.proofscriptparser.NotWelldefinedException;
import edu.kit.formal.proofscriptparser.ScriptLanguageParser;
import edu.kit.formal.proofscriptparser.Visitor;
import lombok.Data;
......@@ -38,27 +37,25 @@ import lombok.Data;
@Data
public class MatchExpression extends Expression<ScriptLanguageParser.MatchPatternContext> {
private Signature signature;
private TermLiteral term;
private Variable variable;
private Expression pattern;
/**
* {@inheritDoc}
*/
@Override public <T> T accept(Visitor<T> visitor) {
@Override
public <T> T accept(Visitor<T> visitor) {
return visitor.visit(this);
}
/**
* {@inheritDoc}
*/
@Override public MatchExpression copy() {
@Override
public MatchExpression copy() {
MatchExpression me = new MatchExpression();
if(signature!=null)
me.signature=signature.copy();
if(term!=null)
me.term = term.copy();
if(variable!=null)
me.variable = variable.copy();
if (signature != null)
me.signature = signature.copy();
me.pattern = pattern.copy();
return me;
}
......@@ -67,15 +64,27 @@ public class MatchExpression extends Expression<ScriptLanguageParser.MatchPatter
*/
@Override
public Type getType(Signature signature) throws NotWelldefinedException {
if(term==null && variable==null)
Type patternType = pattern.getType(signature);
switch (patternType) {
case TERM:
case STRING:
break;
default:
throw new NotWelldefinedException("Missing parameter", this);
}
return Type.BOOL;
}
/**
* {@inheritDoc}
*/
@Override public int getPrecedence() {
@Override
public int getPrecedence() {
return Operator.MATCH.precedence();
}
public void setPattern(Expression pattern) {
this.pattern = pattern;
}
}
......@@ -23,7 +23,6 @@ package edu.kit.formal.proofscriptparser.ast;
*/
import edu.kit.formal.proofscriptparser.NotWelldefinedException;
import edu.kit.formal.proofscriptparser.Visitor;
import lombok.Data;
......@@ -37,10 +36,10 @@ public class StringLiteral extends Literal {
private final String text;
public StringLiteral(String text) {
if (text.charAt(0) == '"')
if (text.charAt(0) == '\'')
text = text.substring(1);
if (text.charAt(0) == '"')
text = text.substring(0, text.length() - 2);
if (text.charAt(text.length()-1) == '\'')
text = text.substring(0, text.length() - 1);
this.text = text;
}
......
......@@ -2,6 +2,7 @@ package edu.kit.formal.interpreter;
import edu.kit.formal.proofscriptparser.TestHelper;
import edu.kit.formal.proofscriptparser.ast.Expression;
import edu.kit.formal.proofscriptparser.ast.Type;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
......@@ -9,8 +10,10 @@ import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Alexander Weigl
......@@ -31,14 +34,17 @@ public class EvaluatorTest {
return TestHelper.loadLines("eval.txt", 2);
}
@Before public void setup() {
@Before
public void setup() {
GoalNode parent = new GoalNode(null, "pa");
GoalNode selected = new GoalNode(parent,"sel");
GoalNode g1 = new GoalNode(parent,"g1");
GoalNode g2 = new GoalNode(parent,"g2");
List<GoalNode> goals = Arrays.asList(g1,g2,selected);
State state = new State(goals, selected);
eval = new Evaluator(state);
parent.addVarDecl("a", Type.INT);
parent.addVarDecl("b", Type.INT);
VariableAssignment va = parent.getAssignments();
va.setVar("a", Value.from(1));
va.setVar("b", Value.from(1));
GoalNode selected = new GoalNode(parent, "selg");
eval = new Evaluator(selected);
eval.setMatcher(new PseudoMatcher());
}
@Test
......@@ -48,4 +54,20 @@ public class EvaluatorTest {
System.out.println(expr);
Assert.assertEquals(truthValue, result);
}
class PseudoMatcher implements MatcherApi {
@Override
public List<VariableAssignment> matchLabel(GoalNode currentState, String label) {
Pattern p = Pattern.compile(label,Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(currentState.getSequent());
return m.matches()
? Collections.singletonList(new VariableAssignment())
: Collections.emptyList();
}
@Override
public List<VariableAssignment> matchSeq(GoalNode currentState, String data) {
return Collections.emptyList();
}
}
}
\ No newline at end of file
......@@ -5,7 +5,7 @@
2*(8) >>> 16
(5+3) >>> 8
16163542361*1612316161341421+2+56+2+2+2+2+2+2 >>> 26060740573166968917435051
match `.*g.*` >>> true
match '.*g.*' >>> true
true >>> true
false >>> false
true & false >>> false
......@@ -14,3 +14,5 @@ false | true >>> true
true | false >>> true
not true >>> false
not false >>> true
a + b >>> 2
(a+a+a+a+a+a+a)*(b+b+b+b+a+a+a) >>> 49
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment