Skip to content
Snippets Groups Projects
Select Git revision
  • 0b0c0b84a58ebcf1fc8c7d8dda7fec34d15c47c4
  • master default protected
  • release/1.1.4
  • release/1.1.3
  • release/1.1.1
  • 1.4.2
  • 1.4.1
  • 1.4.0
  • 1.3.0
  • 1.2.1
  • 1.2.0
  • 1.1.5
  • 1.1.4
  • 1.1.3
  • 1.1.1
  • 1.1.0
  • 1.0.9
  • 1.0.8
  • 1.0.7
  • v1.0.5
  • 1.0.5
21 results

ExpressionTranslator.java

Blame
  • user avatar
    hansen authored
    1080f053
    History
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    ExpressionTranslator.java 9.47 KiB
    package de.tla2bAst;
    
    import java.io.File;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.Set;
    
    import tla2sany.drivers.FrontEndException;
    import tla2sany.drivers.InitException;
    import tla2sany.drivers.SANY;
    import tla2sany.modanalyzer.ParseUnit;
    import tla2sany.modanalyzer.SpecObj;
    import tla2sany.parser.ParseException;
    import tla2sany.semantic.ModuleNode;
    import tla2sany.st.SyntaxTreeConstants;
    import tla2sany.st.TreeNode;
    import util.ToolIO;
    import de.be4.classicalb.core.parser.node.Start;
    import de.tla2b.analysis.SpecAnalyser;
    import de.tla2b.analysis.SymbolRenamer;
    import de.tla2b.analysis.TypeChecker;
    import de.tla2b.exceptions.TLA2BException;
    
    public class ExpressionTranslator implements SyntaxTreeConstants {
    
    	private final String tlaExpression;
    	private final ArrayList<String> variables = new ArrayList<String>();
    	private final ArrayList<String> noVariables = new ArrayList<String>();
    	private Start expressionStart;
    	private ModuleNode moduleNode;
    	private String expr;
    	private Translator translator;
    
    	public Start getBExpressionParseUnit() {
    		return expressionStart;
    	}
    
    	public ExpressionTranslator(String tlaExpression) {
    		this.tlaExpression = tlaExpression;
    	}
    
    	public ExpressionTranslator(String tlaExpression, Translator translator) {
    		this.tlaExpression = tlaExpression;
    		this.translator = translator;
    	}
    
    	public void parse() {
    		String dir = System.getProperty("java.io.tmpdir");
    		ToolIO.setUserDir(dir);
    
    		File tempFile = null;
    		String moduleName = null;
    		String module = null;
    		try {
    			tempFile = File.createTempFile("Testing", ".tla");
    
    			moduleName = tempFile.getName().substring(0,
    					tempFile.getName().indexOf("."));
    
    			module = "----MODULE " + moduleName + " ----\n" + "Expression == "
    					+ tlaExpression + "\n====";
    
    			FileWriter fw = new FileWriter(tempFile);
    			fw.write(module);
    			fw.close();
    		} catch (IOException e) {
    			throw new RuntimeException("Can not create file temporary file in directory '" + dir + "'");
    		}
    
    		SpecObj spec = parseModuleWithoutSemanticAnalyse(moduleName, module);
    		evalVariables(spec, moduleName);
    
    		StringBuilder sb = new StringBuilder();
    		sb.append("----MODULE " + moduleName + " ----\n");
    		sb.append("EXTENDS Naturals, Integers, Sequences, FiniteSets \n");
    		if (variables.size() > 0) {
    			sb.append("VARIABLES ");
    			for (int i = 0; i < variables.size(); i++) {
    				if (i != 0) {
    					sb.append(", ");
    				}
    				sb.append(variables.get(i));
    			}
    			sb.append("\n");
    		}
    		sb.append("Expression");
    		sb.append(" == ");
    		sb.append(tlaExpression);
    		sb.append("\n====================");
    
    		try {
    			FileWriter fw = new FileWriter(tempFile);
    			fw.write(sb.toString());
    			fw.close();
    			tempFile.deleteOnExit();
    		} catch (IOException e) {
    			e.printStackTrace();
    			throw new RuntimeException(e.getMessage());
    		}
    		ToolIO.reset();
    
    		this.expr = sb.toString();
    
    		this.moduleNode = null;
    		try {
    			moduleNode = parseModule(moduleName, sb.toString());
    		} catch (de.tla2b.exceptions.FrontEndException e) {
    			throw new RuntimeException(e.getLocalizedMessage());
    		}
    	}
    
    	public Start translateIncludingModel() throws TLA2BException {
    		SpecAnalyser specAnalyser = SpecAnalyser
    				.createSpecAnalyserForTlaExpression(moduleNode);
    		TypeChecker tc = translator.getTypeChecker();
    		tc.visitOpDefNode(specAnalyser.getExpressionOpdefNode());
    
    		SymbolRenamer symRenamer = new SymbolRenamer(moduleNode, specAnalyser);
    		symRenamer.start();
    		BAstCreator bASTCreator = new BAstCreator(moduleNode, specAnalyser);
    
    		this.expressionStart = bASTCreator.expressionStart;
    		return this.expressionStart;
    	}
    
    	public Start translate() {
    		SpecAnalyser specAnalyser = SpecAnalyser
    				.createSpecAnalyserForTlaExpression(moduleNode);
    		TypeChecker tc = new TypeChecker(moduleNode, specAnalyser);
    		try {
    			tc.start();
    		} catch (TLA2BException e) {
    			// String[] m = ToolIO.getAllMessages();
    			String message = "****TypeError****\n" + e.getLocalizedMessage()
    					+ "\n" + expr + "\n";
    			// System.out.println(message);
    			throw new RuntimeException(message);
    		}
    
    		SymbolRenamer symRenamer = new SymbolRenamer(moduleNode, specAnalyser);
    		symRenamer.start();
    		BAstCreator bASTCreator = new BAstCreator(moduleNode, specAnalyser);
    
    		this.expressionStart = bASTCreator.expressionStart;
    		return this.expressionStart;
    	}
    
    	public static ModuleNode parseModule(String moduleName, String module)
    			throws de.tla2b.exceptions.FrontEndException {
    		SpecObj spec = new SpecObj(moduleName, null);
    		try {
    			SANY.frontEndMain(spec, moduleName, ToolIO.out);
    		} catch (FrontEndException e) {
    			// Error in Frontend, should never happens
    			return null;
    		}
    
    		if (spec.parseErrors.isFailure()) {
    			// String[] m = ToolIO.getAllMessages();
    			String message = module + "\n\n" + spec.parseErrors;
    			// System.out.println(spec.parseErrors);
    			message += allMessagesToString(ToolIO.getAllMessages());
    			throw new de.tla2b.exceptions.FrontEndException(message, spec);
    		}
    
    		if (spec.semanticErrors.isFailure()) {
    			// String[] m = ToolIO.getAllMessages();
    			String message = module + "\n\n" + spec.semanticErrors;
    			message += allMessagesToString(ToolIO.getAllMessages());
    			throw new de.tla2b.exceptions.FrontEndException(message, spec);
    		}
    
    		// RootModule
    		ModuleNode n = spec.getExternalModuleTable().rootModule;
    		if (spec.getInitErrors().isFailure()) {
    			System.err.println(spec.getInitErrors());
    			throw new de.tla2b.exceptions.FrontEndException(
    
    			allMessagesToString(ToolIO.getAllMessages()), spec);
    		}
    
    		if (n == null) { // Parse Error
    			// System.out.println("Rootmodule null");
    			throw new de.tla2b.exceptions.FrontEndException(
    					allMessagesToString(ToolIO.getAllMessages()), spec);
    		}
    		return n;
    	}
    
    	/**
    	 * @param moduleFileName
    	 * @throws de.tla2b.exceptions.FrontEndException
    	 */
    	private SpecObj parseModuleWithoutSemanticAnalyse(String moduleFileName,
    			String module) {
    		SpecObj spec = new SpecObj(moduleFileName, null);
    
    		try {
    			SANY.frontEndInitialize(spec, ToolIO.out);
    			SANY.frontEndParse(spec, ToolIO.out);
    
    		} catch (InitException e1) {
    			System.out.println(e1);
    		} catch (ParseException e1) {
    			System.out.println(e1);
    		}
    
    		if (spec.parseErrors.isFailure()) {
    			String message = module + "\n\n";
    			message += allMessagesToString(ToolIO.getAllMessages());
    			// throw new de.tla2b.exceptions.FrontEndException(message, spec);
    			throw new RuntimeException(message);
    		}
    		return spec;
    	}
    
    	/**
    	 * @param spec
    	 * @return
    	 */
    	private void evalVariables(SpecObj spec, String moduleName) {
    		ParseUnit p = (ParseUnit) spec.parseUnitContext.get(moduleName);
    		TreeNode n_module = p.getParseTree();
    		TreeNode n_body = n_module.heirs()[2];
    		TreeNode n_operatorDefintion = n_body.heirs()[0];
    		TreeNode expr = n_operatorDefintion.heirs()[2];
    		searchVarInSyntaxTree(expr);
    
    		for (int i = 0; i < noVariables.size(); i++) {
    			variables.remove(noVariables.get(i));
    		}
    
    	}
    
    	private final static Set<String> KEYWORDS = new HashSet<String>();
    	static {
    		KEYWORDS.add("BOOLEAN");
    		KEYWORDS.add("TRUE");
    		KEYWORDS.add("FALSE");
    		KEYWORDS.add("Nat");
    		KEYWORDS.add("Int");
    		KEYWORDS.add("Cardinality");
    		KEYWORDS.add("IsFiniteSet");
    		KEYWORDS.add("Append");
    		KEYWORDS.add("Head");
    		KEYWORDS.add("Tail");
    		KEYWORDS.add("Len");
    		KEYWORDS.add("Seq");
    		KEYWORDS.add("SubSeq");
    		KEYWORDS.add("SelectSeq");
    		KEYWORDS.add("MinOfSet");
    		KEYWORDS.add("MaxOfSet");
    		KEYWORDS.add("SetProduct");
    		KEYWORDS.add("SetSummation");
    		KEYWORDS.add("PermutedSequences");
    		KEYWORDS.add("@");
    	}
    
    	/**
    	 * 
    	 */
    	private void searchVarInSyntaxTree(TreeNode treeNode) {
    		// System.out.println(treeNode.getKind() + " " + treeNode.getImage());
    		switch (treeNode.getKind()) {
    		case N_GeneralId: {
    			String con = treeNode.heirs()[1].getImage();
    			if (!variables.contains(con) && !KEYWORDS.contains(con)) {
    				variables.add(con);
    			}
    			break;
    		}
    		case N_IdentLHS: { // left side of a definition
    			TreeNode[] children = treeNode.heirs();
    			noVariables.add(children[0].getImage());
    			break;
    		}
    		case N_IdentDecl: { // parameter of a LET definition
    							// e.g. x in LET foo(x) == e
    			noVariables.add(treeNode.heirs()[0].getImage());
    			break;
    		}
    		case N_FunctionDefinition: {
    			// the first child is the function name
    			noVariables.add(treeNode.heirs()[0].getImage());
    			break;
    		}
    		case N_UnboundQuant: {
    			TreeNode[] children = treeNode.heirs();
    			for (int i = 1; i < children.length - 2; i = i + 2) {
    				// System.out.println(children[i].getImage());
    			}
    			searchVarInSyntaxTree(treeNode.heirs()[children.length - 1]);
    			break;
    		}
    		case N_QuantBound: {
    			TreeNode[] children = treeNode.heirs();
    			for (int i = 0; i < children.length - 2; i = i + 2) {
    				String boundedVar = children[i].getImage();
    				if (!noVariables.contains(boundedVar)) {
    					noVariables.add(boundedVar);
    				}
    			}
    			searchVarInSyntaxTree(treeNode.heirs()[children.length - 1]);
    			break;
    		}
    		case N_SubsetOf: { // { x \in S : e }
    			TreeNode[] children = treeNode.heirs();
    			String boundedVar = children[1].getImage(); // x
    			if (!noVariables.contains(boundedVar)) {
    				noVariables.add(boundedVar);
    			}
    			searchVarInSyntaxTree(treeNode.heirs()[3]); // S
    			searchVarInSyntaxTree(treeNode.heirs()[5]); // e
    			break;
    		}
    
    		}
    
    		for (int i = 0; i < treeNode.heirs().length; i++) {
    			searchVarInSyntaxTree(treeNode.heirs()[i]);
    		}
    	}
    
    	public static String allMessagesToString(String[] allMessages) {
    		StringBuilder sb = new StringBuilder();
    		for (int i = 0; i < allMessages.length - 1; i++) {
    			sb.append(allMessages[i] + "\n");
    		}
    		return sb.toString();
    	}
    }