de.tla2bAst.Translator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of tla2bAST Show documentation
Show all versions of tla2bAST Show documentation
Translator from TLA+ to ProB's AST representation.
The newest version!
package de.tla2bAst;
import de.be4.classicalb.core.parser.BParser;
import de.be4.classicalb.core.parser.Definitions;
import de.be4.classicalb.core.parser.analysis.prolog.RecursiveMachineLoader;
import de.be4.classicalb.core.parser.exceptions.BCompoundException;
import de.be4.classicalb.core.parser.exceptions.PreParseException;
import de.be4.classicalb.core.parser.node.Node;
import de.be4.classicalb.core.parser.node.Start;
import de.be4.classicalb.core.parser.util.PrettyPrinter;
import de.be4.classicalb.core.parser.util.SuffixIdentifierRenaming;
import de.hhu.stups.sablecc.patch.PositionedNode;
import de.prob.prolog.output.PrologTermOutput;
import de.tla2b.analysis.*;
import de.tla2b.config.ConfigfileEvaluator;
import de.tla2b.config.ModuleOverrider;
import de.tla2b.exceptions.TLA2BFrontEndException;
import de.tla2b.exceptions.TLA2BException;
import de.tla2b.global.TranslationGlobals;
import de.tla2b.output.TlaTypePrinter;
import de.tla2b.translation.BMacroHandler;
import de.tla2b.translation.RecursiveFunctionHandler;
import de.tla2b.types.TLAType;
import de.tla2b.util.FileUtils;
import tla2sany.drivers.FrontEndException;
import tla2sany.drivers.SANY;
import tla2sany.modanalyzer.SpecObj;
import tla2sany.semantic.ModuleNode;
import tlc2.tool.impl.ModelConfig;
import util.ToolIO;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Map;
import java.util.List;
import java.util.stream.Collectors;
public class Translator implements TranslationGlobals {
private static final String GENERATED_BY_TLA2B_HEADER = "/*@ generated by TLA2B ";
private String parentPath;
private File moduleFile;
private File configFile;
private List moduleFiles = new ArrayList<>();
private BAstCreator bAstCreator;
// private String moduleName;
private ModuleNode moduleNode;
private ModelConfig modelConfig;
private SpecAnalyser specAnalyser;
private TypeChecker typechecker;
public Translator(String moduleFileName) throws TLA2BFrontEndException {
this.moduleFile = new File(moduleFileName);
if (!moduleFile.exists()) {
throw new RuntimeException("Can not find module file: '" + moduleFileName + "'");
}
try {
this.moduleFile = moduleFile.getCanonicalFile();
} catch (IOException e) {
throw new RuntimeException("Can not access module file: '" + moduleFileName + "'");
}
this.parentPath = moduleFile.getParent() == null ? "." : moduleFile.getParent();
this.configFile = new File(FileUtils.removeExtension(moduleFile.getAbsolutePath()) + ".cfg");
if (!configFile.exists()) {
this.configFile = null;
}
parse();
}
/**
* External interface
*/
public static String translateModuleString(String moduleName, String moduleString, String configString)
throws TLA2BException {
Translator translator = new Translator(moduleName, moduleString, configString);
Start bAST = translator.getBAST();
PrettyPrinter pp = new PrettyPrinter();
pp.setRenaming(new SuffixIdentifierRenaming());
bAST.apply(pp);
return pp.getPrettyPrint();
}
public Translator(String moduleName, String moduleString, String configString) throws TLA2BException {
createTLATempFile(moduleString, moduleName);
createCfgFile(configString, moduleName);
parse();
translate();
}
// Used for Testing in tla2bAST project
public Translator(String moduleString, String configString) throws TLA2BFrontEndException {
String moduleName = "Testing";
createTLATempFile(moduleString, moduleName);
createCfgFile(configString, moduleName);
parse();
}
private void createTLATempFile(String moduleString, String moduleName) {
File dir = new File("temp/");
dir.mkdirs();
dir.deleteOnExit();
moduleFile = new File("temp/" + moduleName + ".tla");
try (BufferedWriter out = Files.newBufferedWriter(moduleFile.toPath(), StandardCharsets.UTF_8)) {
out.write(moduleString);
} catch (IOException e) {
System.err.println("Error while writing file '" + moduleFile.getAbsolutePath() + "':\n" + e.getMessage());
}
}
private void createCfgFile(String configString, String moduleName) {
modelConfig = null;
if (configString != null) {
configFile = new File("temp/" + moduleName + ".cfg");
try (BufferedWriter out = Files.newBufferedWriter(configFile.toPath(), StandardCharsets.UTF_8)) {
out.write(configString);
} catch (IOException e) {
System.err.println("Error while writing file '" + configFile.getAbsolutePath() + "':\n" + e.getMessage());
}
}
}
private void parse() throws TLA2BFrontEndException {
moduleNode = parseModule();
modelConfig = null;
if (configFile != null) {
modelConfig = new ModelConfig(configFile.getAbsolutePath(), new SimpleResolver());
modelConfig.parse();
}
}
public ModuleNode parseModule() throws TLA2BFrontEndException {
String fileName = moduleFile.getName();
ToolIO.setUserDir(moduleFile.getParent());
SpecObj spec = new SpecObj(fileName, null);
try {
SANY.frontEndMain(spec, fileName, ToolIO.out);
} catch (FrontEndException e) {
// should never happen
throw new RuntimeException("Could not parse module: '" + fileName + "'", e);
}
if (spec.getParseErrors().isFailure()) {
throw new TLA2BFrontEndException(allMessagesToString(ToolIO.getAllMessages()) + spec.getParseErrors(), spec);
}
if (spec.getSemanticErrors().isFailure()) {
throw new TLA2BFrontEndException(allMessagesToString(ToolIO.getAllMessages()) + spec.getSemanticErrors(), spec);
}
// RootModule
ModuleNode n = spec.getExternalModuleTable().getRootModule();
if (spec.getInitErrors().isFailure()) {
throw new TLA2BFrontEndException(spec.getInitErrors().toString(), spec);
}
if (n == null) { // Parse Error
throw new TLA2BFrontEndException(allMessagesToString(ToolIO.getAllMessages()), spec);
}
return n;
}
public static String allMessagesToString(String[] allMessages) {
return String.join("\n", allMessages) + "\n";
}
public Start translate() throws TLA2BException {
InstanceTransformation.run(moduleNode);
SymbolSorter.sort(moduleNode);
ConfigfileEvaluator conEval = null;
if (modelConfig != null) {
conEval = new ConfigfileEvaluator(modelConfig, moduleNode);
conEval.start();
ModuleOverrider.run(moduleNode, conEval);
specAnalyser = SpecAnalyser.createSpecAnalyser(moduleNode, conEval);
} else {
specAnalyser = SpecAnalyser.createSpecAnalyser(moduleNode);
}
specAnalyser.start();
typechecker = new TypeChecker(moduleNode, conEval, specAnalyser);
typechecker.start();
SymbolRenamer.run(moduleNode, specAnalyser);
bAstCreator = new BAstCreator(moduleNode, conEval, specAnalyser,
new UsedExternalFunctions(moduleNode, specAnalyser),
new PredicateVsExpression(moduleNode),
new BMacroHandler(specAnalyser, conEval),
new RecursiveFunctionHandler(specAnalyser));
this.moduleFiles = bAstCreator.getFilesOrderedById().stream()
.map(file -> new File(parentPath, file + ".tla")).collect(Collectors.toList());
return getBAST();
}
public void createProbFile() {
File probFile = new File(FileUtils.removeExtension(moduleFile.getAbsolutePath()) + ".prob");
BParser bParser = new BParser();
try (BufferedWriter outWriter = Files.newBufferedWriter(probFile.toPath(), StandardCharsets.UTF_8)) {
bParser.getDefinitions().addDefinitions(getBDefinitions());
final RecursiveMachineLoader rml = parseAllMachines(getBAST(), getModuleFile(), bParser);
rml.printAsProlog(new PrologTermOutput(outWriter, false));
System.out.println(probFile.getAbsolutePath() + " created.");
} catch (BCompoundException | IOException | PreParseException e) {
System.err.println(e.getMessage());
System.exit(-1);
}
}
public void createMachineFile() {
File machineFile = new File(FileUtils.removeExtension(moduleFile.getAbsolutePath()) + "_tla.txt");
if (machineFile.exists()) {
try (BufferedReader in = new BufferedReader(new FileReader(machineFile))) {
String firstLine = in.readLine();
if (firstLine != null && !firstLine.startsWith(GENERATED_BY_TLA2B_HEADER)) {
System.err.println("Error: File " + machineFile.getName() + " already exists"
+ " and was not generated by TLA2B.\n" + "Delete or move this file.");
System.exit(-1);
}
} catch (IOException e) {
System.err.println(e.getMessage());
System.exit(-1);
}
}
PrettyPrinter pp = new PrettyPrinter();
pp.setRenaming(new SuffixIdentifierRenaming());
getBAST().apply(pp);
try (BufferedWriter out = Files.newBufferedWriter(machineFile.toPath(), StandardCharsets.UTF_8)) {
out.write(GENERATED_BY_TLA2B_HEADER + VERSION_NUMBER + " */\n" + pp.getPrettyPrint());
System.out.println("B-Machine " + machineFile.getAbsolutePath() + " created.");
} catch (IOException e) {
System.err.println("Error while creating file '" + machineFile.getAbsolutePath() + "':\n" + e.getMessage());
System.exit(-1);
}
}
public RecursiveMachineLoader parseAllMachines(final Start ast, final File f, final BParser bparser) throws BCompoundException {
final RecursiveMachineLoader rml = new RecursiveMachineLoader(parentPath, bparser.getContentProvider());
rml.loadAllMachines(f, ast, bparser.getDefinitions());
// Create the assignment of nodes to TLA modules:
// manipulate loaded files in RML: this is necessary for printing ALL included module file names in rml.printAsProlog
// per default only the main module (startFile) is included
rml.getMachineFilesLoaded().clear(); // clear to ensure correct order of file numbers assigned below
rml.getMachineFilesLoaded().addAll(this.moduleFiles);
for (PositionedNode node : bAstCreator.getSourcePositions()) {
// Overwrite node ID mapping with the assignment that is created when positioned nodes are created
rml.getNodeIdMapping().assignIdentifiers(bAstCreator.getNodeFileNumbers().lookupFileNumber((Node) node), (Node) node);
}
// this is required for correct positions in ProB2(-UI) when rml.printAsProlog is called
rml.setPositionPrinter(new TlaTypePrinter(rml.getNodeIdMapping(), bAstCreator.getTypes()));
return rml;
}
public Start translateExpressionIncludingModel(String tlaExpression) throws TLA2BException {
ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression, this);
expressionTranslator.parse();
return expressionTranslator.translateIncludingModel();
}
@Deprecated
public Start translateExpression(String tlaExpression) throws TLA2BException {
return this.translateExpressionIncludingModel(tlaExpression);
}
public static Start translateExpressionWithoutModel(String tlaExpression) {
ExpressionTranslator expressionTranslator = new ExpressionTranslator(tlaExpression);
expressionTranslator.parse();
return expressionTranslator.translateWithoutModel();
}
@Deprecated
public static Start translateTlaExpression(String tlaExpression) {
return translateExpressionWithoutModel(tlaExpression);
}
public Definitions getBDefinitions() {
return bAstCreator.getBDefinitions();
}
public ModuleNode getModuleNode() {
return moduleNode;
}
protected TypeChecker getTypeChecker() {
return this.typechecker;
}
protected SpecAnalyser getSpecAnalyser() {
return this.specAnalyser;
}
public Start getBAST() {
return bAstCreator.getStartNode();
}
public File getModuleFile() {
return moduleFile;
}
public List getModuleFiles() {
return Collections.unmodifiableList(moduleFiles);
}
public Map getTypes() {
return bAstCreator.getTypes();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy