use of de.be4.classicalb.core.parser.Definitions in project probparsers by bendisposto.
the class MachineContext method caseADefinitionsMachineClause.
/**
* Definitions
*/
@Override
public void caseADefinitionsMachineClause(ADefinitionsMachineClause node) {
definitionMachineClause = node;
DefinitionsSorter.sortDefinitions(node);
List<PDefinition> copy = node.getDefinitions();
/*
* The definitions are not in a predefined order. In particular
* definitions can depend on each other. First all definitions are added
* to the definitions context table. Then all definitions are visited.
*/
Collection<PDefinition> definitionsToRemove = new HashSet<PDefinition>();
for (PDefinition e : copy) {
if (e instanceof AExpressionDefinitionDefinition) {
AExpressionDefinitionDefinition def = (AExpressionDefinitionDefinition) e;
String name = def.getName().getText();
if (name.startsWith("ASSERT_LTL")) {
LTLFormulaVisitor visitor = new LTLFormulaVisitor(name, this);
visitor.parseDefinition(def);
this.ltlVisitors.add(visitor);
definitionsToRemove.add(def);
} else if (name.startsWith("ANIMATION_")) {
definitionsToRemove.add(def);
}
evalDefinitionName(((AExpressionDefinitionDefinition) e).getName().getText().toString(), e);
} else if (e instanceof APredicateDefinitionDefinition) {
evalDefinitionName(((APredicateDefinitionDefinition) e).getName().getText().toString(), e);
} else if (e instanceof ASubstitutionDefinitionDefinition) {
evalDefinitionName(((ASubstitutionDefinitionDefinition) e).getName().getText().toString(), e);
}
}
/*
* At this point all LTL definitions (ASSERT_LTL) are removed. LTL
* formulas are stored in the Arraylist {@value #ltlVisitors}.
*/
copy.removeAll(definitionsToRemove);
this.contextTable = new ArrayList<LinkedHashMap<String, Node>>();
ArrayList<MachineContext> list = lookupReferencedMachines();
for (int i = 0; i < list.size(); i++) {
MachineContext s = list.get(i);
contextTable.add(s.getDeferredSets());
contextTable.add(s.getEnumeratedSets());
contextTable.add(s.getEnumValues());
contextTable.add(s.getConstants());
contextTable.add(s.getVariables());
contextTable.add(s.getDefinitions());
}
for (PDefinition e : copy) {
e.apply(this);
}
}
use of de.be4.classicalb.core.parser.Definitions in project probparsers by bendisposto.
the class ASTBuilder method addToStringDefinition.
public static void addToStringDefinition(IDefinitions definitions) {
if (definitions.containsDefinition(TO_STRING)) {
return;
}
/*-
* TO_STRING(S) == "0";
* EXTERNAL_FUNCTION_TO_STRING(X) == X -->STRING;
*/
AExpressionDefinitionDefinition toStringDef = new AExpressionDefinitionDefinition();
toStringDef.setName(new TIdentifierLiteral(TO_STRING));
toStringDef.setParameters(createIdentifierList("S"));
toStringDef.setRhs(new AStringExpression(new TStringLiteral("0")));
definitions.addDefinition(toStringDef, IDefinitions.Type.Expression);
AExpressionDefinitionDefinition toStringTypeDef = new AExpressionDefinitionDefinition();
toStringTypeDef.setName(new TIdentifierLiteral("EXTERNAL_FUNCTION_TO_STRING"));
toStringTypeDef.setParameters(createIdentifierList("X"));
toStringTypeDef.setRhs(new ATotalFunctionExpression(createIdentifier("X"), new AStringSetExpression()));
definitions.addDefinition(toStringTypeDef, IDefinitions.Type.Expression);
}
use of de.be4.classicalb.core.parser.Definitions in project probparsers by bendisposto.
the class PreParser method sortDefinitionsByTopologicalOrderAndCheckForCycles.
private List<Token> sortDefinitionsByTopologicalOrderAndCheckForCycles(Map<Token, Token> definitions) throws PreParseException {
final Set<String> definitionNames = new HashSet<>();
final Map<String, Token> definitionMap = new HashMap<>();
for (Token token : definitions.keySet()) {
final String definitionName = token.getText();
definitionNames.add(definitionName);
definitionMap.put(definitionName, token);
}
Map<String, Set<String>> dependencies = determineDependencies(definitionNames, definitions);
List<String> sortedDefinitionNames = Utils.sortByTopologicalOrder(dependencies);
if (sortedDefinitionNames.size() < definitionNames.size()) {
Set<String> remaining = new HashSet<>(definitionNames);
remaining.removeAll(sortedDefinitionNames);
List<String> cycle = Utils.determineCycle(remaining, dependencies);
StringBuilder sb = new StringBuilder();
for (Iterator<String> iterator = cycle.iterator(); iterator.hasNext(); ) {
sb.append(iterator.next());
if (iterator.hasNext()) {
sb.append(" -> ");
}
}
final Token firstDefinitionToken = definitionMap.get(cycle.get(0));
throw new PreParseException(firstDefinitionToken, "Cyclic references in definitions: " + sb.toString());
} else {
List<Token> sortedDefinitionTokens = new ArrayList<>();
for (String name : sortedDefinitionNames) {
sortedDefinitionTokens.add(definitionMap.get(name));
}
return sortedDefinitionTokens;
}
}
use of de.be4.classicalb.core.parser.Definitions in project probparsers by bendisposto.
the class PreParser method parse.
public void parse() throws PreParseException, IOException, BException, BCompoundException {
final PreLexer preLexer = new PreLexer(pushbackReader);
final Parser preParser = new Parser(preLexer);
Start rootNode = null;
try {
rootNode = preParser.parse();
} catch (final ParserException e) {
if (e.getToken() instanceof de.be4.classicalb.core.preparser.node.TDefinitions) {
final Token errorToken = e.getToken();
final String message = "[" + errorToken.getLine() + "," + errorToken.getPos() + "] " + "Clause 'DEFINITIONS' is used more than once";
throw new PreParseException(e.getToken(), message);
} else {
throw new PreParseException(e.getToken(), e.getLocalizedMessage());
}
} catch (final LexerException e) {
throw new PreParseException(e.getLocalizedMessage());
}
final DefinitionPreCollector collector = new DefinitionPreCollector();
rootNode.apply(collector);
evaluateDefinitionFiles(collector.getFileDefinitions());
List<Token> sortedDefinitionList = sortDefinitionsByTopologicalOrderAndCheckForCycles(collector.getDefinitions());
evaluateTypes(sortedDefinitionList, collector.getDefinitions());
}
use of de.be4.classicalb.core.parser.Definitions in project probparsers by bendisposto.
the class RecursiveMachineLoader method recursivlyLoadMachine.
private void recursivlyLoadMachine(final File machineFile, final Start currentAst, final List<String> ancestors, final boolean isMain, File directory, final IDefinitions definitions) throws BCompoundException {
// make a copy of the referencing machines
List<String> newAncestors = new ArrayList<>(ancestors);
ReferencedMachines refMachines = new ReferencedMachines(machineFile, currentAst, parsingBehaviour.isMachineNameMustMatchFileName());
try {
refMachines.findReferencedMachines();
} catch (BException e) {
throw new BCompoundException(e);
}
final String name = refMachines.getName();
if (name == null) {
/*
* the parsed file is a definition file, hence the name of the
* machine is null
*/
throw new BCompoundException(new BException(machineFile.getName(), "Expecting a B machine but was a definition file in file: '" + machineFile.getName() + "\'", null));
}
machineFilesLoaded.add(machineFile);
final int fileNumber = machineFilesLoaded.indexOf(machineFile) + 1;
getNodeIdMapping().assignIdentifiers(fileNumber, currentAst);
definitions.assignIdsToNodes(getNodeIdMapping(), machineFilesLoaded);
injectDefinitions(currentAst, definitions);
getParsedMachines().put(name, currentAst);
parsedFiles.put(name, machineFile);
if (name != null) {
newAncestors.add(name);
}
if (isMain) {
main = name;
}
final Set<String> referencesSet = refMachines.getSetOfReferencedMachines();
try {
checkForCycles(newAncestors, referencesSet);
} catch (BException e) {
throw new BCompoundException(e);
}
final List<MachineReference> references = refMachines.getReferences();
for (final MachineReference refMachine : references) {
try {
final String filePragma = refMachine.getPath();
File file = null;
if (filePragma == null) {
file = lookupFile(directory, refMachine, newAncestors, refMachines.getPathList());
} else {
File p = new File(filePragma);
if (p.isAbsolute()) {
file = p;
} else {
file = new File(directory, filePragma);
}
}
if (file.exists() && parsedFiles.containsKey(refMachine.getName()) && !parsedFiles.get(refMachine.getName()).getCanonicalPath().equals(file.getCanonicalPath())) {
final String message = "Two files with the same name are referenced:\n" + parsedFiles.get(refMachine.getName()).getCanonicalPath() + "\n" + file.getCanonicalPath();
throw new BException(machineFile.getCanonicalPath(), new CheckException(message, refMachine.getNode()));
}
if (!getParsedMachines().containsKey(refMachine.getName())) {
try {
loadMachine(newAncestors, file);
} catch (IOException e) {
throw new BException(machineFile.getCanonicalPath(), new CheckException(e.getMessage(), refMachine.getNode(), e));
}
}
} catch (final BException e) {
// we do not longer wrap a B Exception in a B Exception
throw new BCompoundException(e);
} catch (final IOException e) {
throw new BCompoundException(new BException(machineFile.getAbsolutePath(), e));
} catch (final CheckException e) {
throw new BCompoundException(new BException(machineFile.getAbsolutePath(), e));
}
}
}
Aggregations