Created
June 4, 2013 15:26
-
-
Save dukeboard/5706789 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* Copyright (c) 2012 The University of York. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
******************************************************************************/ | |
package org.eclipse.epsilon.epl; | |
import java.util.ArrayList; | |
import java.util.List; | |
import org.eclipse.epsilon.common.parse.AST; | |
import org.eclipse.epsilon.eol.exceptions.EolIllegalReturnException; | |
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException; | |
import org.eclipse.epsilon.eol.execute.Return; | |
import org.eclipse.epsilon.eol.execute.context.Frame; | |
import org.eclipse.epsilon.eol.execute.context.FrameType; | |
import org.eclipse.epsilon.eol.execute.context.IEolContext; | |
import org.eclipse.epsilon.eol.execute.context.Variable; | |
import org.eclipse.epsilon.epl.combinations.DynamicListCombinationGenerator; | |
import org.eclipse.epsilon.epl.combinations.CombinationGenerator; | |
import org.eclipse.epsilon.epl.combinations.CombinationGeneratorListener; | |
import org.eclipse.epsilon.epl.combinations.CompositeCombinationGenerator; | |
import org.eclipse.epsilon.epl.combinations.CompositeCombinationValidator; | |
public class PatternMatcher { | |
protected Frame frame = null; | |
public PatternMatchModel match(EplModule module) throws Exception { | |
frame = null; | |
IEolContext context = module.getContext(); | |
PatternMatchModel model = new PatternMatchModel(); | |
if (module.getMaximumLevel() > 0) { | |
model.setName(module.getPatternMatchModelName()); | |
context.getModelRepository().addModel(model); | |
} | |
model.setPatterns(module.getPatterns()); | |
for (int level=0;level<=module.getMaximumLevel();level++) { | |
for (Pattern pattern : module.getPatterns()) { | |
if (pattern.getLevel() == level) { | |
for (PatternMatch match : match(pattern, context)) { | |
model.addMatch(match); | |
} | |
} | |
} | |
for (PatternMatch match : model.getMatches()) { | |
if (match.getPattern().getLevel() == level) { | |
AST doAst = match.getPattern().getDoAst(); | |
if (doAst != null) { | |
context.getFrameStack().enterLocal(FrameType.UNPROTECTED, doAst); | |
for (String componentName : match.getRoleBindings().keySet()) { | |
context.getFrameStack().put(Variable.createReadOnlyVariable(componentName, match.getRoleBinding(componentName))); | |
} | |
context.getExecutorFactory().executeAST(doAst, context); | |
context.getFrameStack().leaveLocal(doAst); | |
} | |
} | |
} | |
} | |
return model; | |
} | |
public List<PatternMatch> match(final Pattern pattern, final IEolContext context) throws Exception { | |
List<PatternMatch> patternMatches = new ArrayList<PatternMatch>(); | |
context.getFrameStack().enterLocal(FrameType.PROTECTED, pattern.getAst()); | |
CompositeCombinationGenerator<Object> generator = new CompositeCombinationGenerator<Object>(); | |
for (Role role : pattern.getRoles()) { | |
generator.addCombinationGenerator(createCombinationGenerator(role, context)); | |
} | |
generator.setValidator(new CompositeCombinationValidator<Object>() { | |
@Override | |
public boolean isValid(List<List<Object>> combination) throws Exception { | |
for (Object o : combination.get(combination.size()-1)) { | |
if (o instanceof NoMatch) return true; | |
} | |
frame = context.getFrameStack().enterLocal(FrameType.PROTECTED, pattern.getAst()); | |
boolean result = true; | |
int i = 0; | |
Role role = null; | |
for (List<Object> values : combination) { | |
role = pattern.getRoles().get(i); | |
for (Variable variable : getVariables(values, role)) { | |
frame.put(variable); | |
} | |
i++; | |
} | |
if (!role.isNegative() && role.getGuard() != null && role.isActive(context) && role.getCardinality().isOne()) { | |
Return ret = null; | |
ret = (Return) context.getExecutorFactory().executeBlockOrExpressionAst(role.getGuard().getAst().getFirstChild(), context); | |
if (ret.getValue() instanceof Boolean) result = (Boolean) ret.getValue(); | |
} | |
context.getFrameStack().leaveLocal(pattern.getAst()); | |
return result; | |
} | |
}); | |
while (generator.hasMore()) { | |
List<List<Object>> candidate = generator.getNext(); | |
boolean matches = true; | |
frame = context.getFrameStack().enterLocal(FrameType.PROTECTED, pattern.getAst()); | |
if (pattern.getMatchAst() != null || pattern.getNoMatchAst() != null || pattern.getOnMatchAst() != null) { | |
int i = 0; | |
for (Role role : pattern.getRoles()) { | |
for (Variable variable : getVariables(candidate.get(i), role)) { | |
frame.put(variable); | |
} | |
i++; | |
} | |
} | |
if (pattern.getMatchAst() != null) { | |
Object result = context.getExecutorFactory().executeAST(pattern.getMatchAst(), context); | |
if (result instanceof Return) result = ((Return) result).getValue(); | |
if (result instanceof Boolean) { | |
matches = (Boolean) result; | |
} | |
else throw new EolIllegalReturnException("Boolean", result, pattern.getMatchAst(), context); | |
} | |
if (matches) { | |
context.getExecutorFactory().executeAST(pattern.getOnMatchAst(), context); | |
patternMatches.add(createPatternMatch(pattern, candidate)); | |
} | |
else context.getExecutorFactory().executeAST(pattern.getNoMatchAst(), context); | |
context.getFrameStack().leaveLocal(pattern.getAst()); | |
} | |
context.getFrameStack().leaveLocal(pattern.getAst()); | |
return patternMatches; | |
} | |
protected List<Variable> getVariables(List<Object> combination, Role role) { | |
ArrayList<Variable> variables = new ArrayList<Variable>(); | |
int i = 0; | |
for (String name : role.getNames()) { | |
variables.add(Variable.createReadOnlyVariable(name, combination.get(i))); | |
i++; | |
} | |
//if (component.getAlias() != null) { | |
// variables.add(Variable.createReadOnlyVariable(component.getAlias(), combination)); | |
//} | |
return variables; | |
} | |
protected CombinationGenerator<Object> createCombinationGenerator(final Role role, final IEolContext context) throws EolRuntimeException { | |
DynamicListCombinationGenerator<Object> combinationGenerator = null; | |
combinationGenerator = new DynamicListCombinationGenerator<Object>(role.getInstances(context), role.getNames().size()) { | |
@Override | |
public Boolean checkOptional() { | |
try { | |
return role.isOptional(context); | |
} catch (EolRuntimeException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
}; | |
//FixedCombinationGenerator<Object> combinationGenerator = null; | |
//combinationGenerator = new FixedCombinationGenerator<Object>(component.getInstances(context), component.getNames().size()); | |
combinationGenerator.addListener(new CombinationGeneratorListener<Object>() { | |
@Override | |
public void generated(List<Object> next) { | |
//if (next != null) | |
if (next == null) { | |
for (String name : role.getNames()) { | |
context.getFrameStack().put(Variable.createReadOnlyVariable(name, NoMatch.INSTANCE)); | |
} | |
} | |
else { | |
for (Variable variable : getVariables(next, role)) { | |
context.getFrameStack().put(variable); | |
}} | |
} | |
@Override | |
public void reset() { | |
for (String variableName : role.getNames()) { | |
context.getFrameStack().remove(variableName); | |
} | |
} | |
}); | |
return combinationGenerator; | |
} | |
protected PatternMatch createPatternMatch(Pattern pattern, List<List<Object>> combination) { | |
PatternMatch patternMatch = new PatternMatch(pattern); | |
int i = 0; | |
for (Role role : pattern.getRoles()) { | |
for (Variable variable : getVariables(combination.get(i), role)) { | |
patternMatch.getRoleBindings().put(variable.getName(), variable.getValue()); | |
} | |
i++; | |
} | |
return patternMatch; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment