/* * Copyright (c) 2014, IETR/INSA of Rennes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.ui.editor; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import net.sf.orcc.OrccRuntimeException; import net.sf.orcc.cal.cal.AstExpression; import net.sf.orcc.cal.cal.AstType; import net.sf.orcc.cal.cal.AstTypeBool; import net.sf.orcc.cal.cal.AstTypeDouble; import net.sf.orcc.cal.cal.AstTypeFloat; import net.sf.orcc.cal.cal.AstTypeHalf; import net.sf.orcc.cal.cal.AstTypeInt; import net.sf.orcc.cal.cal.AstTypeList; import net.sf.orcc.cal.cal.AstTypeString; import net.sf.orcc.cal.cal.AstTypeUint; import net.sf.orcc.cal.cal.ExpressionBinary; import net.sf.orcc.cal.cal.ExpressionBoolean; import net.sf.orcc.cal.cal.ExpressionFloat; import net.sf.orcc.cal.cal.ExpressionInteger; import net.sf.orcc.cal.cal.ExpressionList; import net.sf.orcc.cal.cal.ExpressionString; import net.sf.orcc.cal.cal.ExpressionUnary; import net.sf.orcc.cal.cal.ExpressionVariable; import net.sf.orcc.cal.cal.Variable; import net.sf.orcc.cal.cal.util.CalSwitch; import net.sf.orcc.cal.services.CalGrammarAccess; import net.sf.orcc.cal.services.Typer; import net.sf.orcc.cal.ui.internal.CalActivator; import net.sf.orcc.cal.util.Util; import net.sf.orcc.ir.ExprInt; import net.sf.orcc.ir.ExprList; import net.sf.orcc.ir.Expression; import net.sf.orcc.ir.IrFactory; import net.sf.orcc.ir.OpBinary; import net.sf.orcc.ir.OpUnary; import net.sf.orcc.ir.Type; import net.sf.orcc.ir.Var; import net.sf.orcc.ir.util.ExpressionEvaluator; import net.sf.orcc.util.OrccUtil; import org.eclipse.emf.ecore.EObject; import org.eclipse.xtext.IGrammarAccess; import org.eclipse.xtext.nodemodel.ICompositeNode; import org.eclipse.xtext.nodemodel.ILeafNode; import org.eclipse.xtext.nodemodel.util.NodeModelUtils; import org.eclipse.xtext.parser.IParseResult; import org.eclipse.xtext.parser.IParser; import com.google.inject.Injector; /** * This class reuse the Xtext CAL logic and the defined transformers to parse * Strings and try to convert them into their equivalent object in the IR * package. * * @author Antoine Lorence * */ public class PartialCalParser extends CalSwitch<EObject> { private final Injector injector; private final IParser parser; private final CalGrammarAccess grammarAccess; /** * This will be used to perform linking between declaration and usage of * variables. Xtext do it automatically in a classical context, but here we * need to ensure mechanism is working even if variables are declared and * used in a Network or an Instance. */ private final Map<String, Var> declaredVars; public PartialCalParser() { injector = CalActivator.getInstance().getInjector("net.sf.orcc.cal.Cal"); parser = injector.getInstance(IParser.class); grammarAccess = (CalGrammarAccess) injector.getInstance(IGrammarAccess.class); declaredVars = new HashMap<String, Var>(); } public void setDeclaredVars(final Iterable<Var> vars) { declaredVars.clear(); for (final Var var : vars) { declaredVars.put(var.getName(), var); } } public void addDeclaredVar(final Var var) { declaredVars.put(var.getName(), var); } public void addDeclaredVars(final Iterable<Var> vars) { for (final Var var : vars) { declaredVars.put(var.getName(), var); } } public boolean isVariableDeclaration(final String declString) { final Reader reader = new StringReader(declString); final IParseResult result = parser.parse(grammarAccess.getValuedVariableDeclarationRule(), reader); return !result.hasSyntaxErrors(); } public Var parseVariableDeclaration(final String declString) { final Reader reader = new StringReader(declString); final IParseResult result = parser.parse(grammarAccess.getValuedVariableDeclarationRule(), reader); if (result.hasSyntaxErrors()) { return null; } final Variable astResult = (Variable) result.getRootASTElement(); final EObject irResult = doSwitch(astResult); if (irResult instanceof Var) { return (Var) irResult; } return null; } public boolean isExpression(final String exprString) { final Reader reader = new StringReader(exprString); final IParseResult result = parser.parse(grammarAccess.getAstExpressionRule(), reader); return !result.hasSyntaxErrors(); } public Expression parseExpression(final String exprString) { final Reader reader = new StringReader(exprString); final IParseResult result = parser.parse(grammarAccess.getAstExpressionRule(), reader); if (result.hasSyntaxErrors()) { return null; } final AstExpression astResult = (AstExpression) result.getRootASTElement(); final EObject irResult = doSwitch(astResult); if (irResult instanceof Expression) { return (Expression) irResult; } return null; } public boolean isType(final String typeString) { final Reader reader = new StringReader(typeString); final IParseResult result = parser.parse(grammarAccess.getAstTypeRule(), reader); return !result.hasSyntaxErrors(); } public Type parseType(final String typeString) { final Reader reader = new StringReader(typeString); final IParseResult result = parser.parse(grammarAccess.getAstTypeRule(), reader); if (result.hasSyntaxErrors()) { return null; } final AstType astType = (AstType) result.getRootASTElement(); final Object irResult = doSwitch(astType); if (irResult instanceof Type) { return (Type) irResult; } return null; } @Override public Type caseAstTypeBool(AstTypeBool type) { return IrFactory.eINSTANCE.createTypeBool(); } @Override public Type caseAstTypeDouble(AstTypeDouble type) { return IrFactory.eINSTANCE.createTypeFloat(64); } @Override public Type caseAstTypeFloat(AstTypeFloat type) { return IrFactory.eINSTANCE.createTypeFloat(32); } @Override public Type caseAstTypeHalf(AstTypeHalf type) { return IrFactory.eINSTANCE.createTypeFloat(16); } @Override public Type caseAstTypeInt(AstTypeInt type) { AstExpression astSize = type.getSize(); int size; if (astSize == null) { size = 32; } else { size = new ExpressionEvaluator().evaluateAsInteger((Expression) doSwitch(astSize)); } return IrFactory.eINSTANCE.createTypeInt(size); } @Override public Type caseAstTypeList(AstTypeList listType) { Type type = (Type) doSwitch(listType.getType()); AstExpression expression = listType.getSize(); Expression size = (Expression) doSwitch(expression); return IrFactory.eINSTANCE.createTypeList(size, type); } @Override public Type caseAstTypeString(AstTypeString type) { return IrFactory.eINSTANCE.createTypeString(); } @Override public Type caseAstTypeUint(AstTypeUint type) { AstExpression astSize = type.getSize(); int size; if (astSize == null) { size = 32; } else { size = new ExpressionEvaluator().evaluateAsInteger((Expression) doSwitch(astSize)); } return IrFactory.eINSTANCE.createTypeUint(size); } @Override public Expression caseExpressionBinary(ExpressionBinary expression) { OpBinary op = OpBinary.getOperator(expression.getOperator()); Expression val1 = (Expression) doSwitch(expression.getLeft()); Expression val2 = (Expression) doSwitch(expression.getRight()); return IrFactory.eINSTANCE.createExprBinary(val1, op, val2, null); } @Override public Expression caseExpressionBoolean(ExpressionBoolean expression) { return IrFactory.eINSTANCE.createExprBool(expression.isValue()); } @Override public Expression caseExpressionFloat(ExpressionFloat expression) { return IrFactory.eINSTANCE.createExprFloat(expression.getValue()); } @Override public ExprInt caseExpressionInteger(ExpressionInteger expression) { return IrFactory.eINSTANCE.createExprInt(expression.getValue()); } @Override public ExprList caseExpressionList(ExpressionList list) { List<Expression> expressions = new ArrayList<Expression>(list.getExpressions().size()); for (AstExpression expression : list.getExpressions()) { expressions.add((Expression) doSwitch(expression)); } return IrFactory.eINSTANCE.createExprList(expressions); } @Override public Expression caseExpressionString(ExpressionString expression) { return IrFactory.eINSTANCE.createExprString(OrccUtil.getEscapedString(expression.getValue())); } @Override public Expression caseExpressionUnary(ExpressionUnary expression) { OpUnary op = OpUnary.getOperator(expression.getUnaryOperator()); Expression expr = (Expression) doSwitch(expression.getExpression()); return IrFactory.eINSTANCE.createExprUnary(op, expr, null); } @Override public Expression caseExpressionVariable(ExpressionVariable expression) { Variable variable = expression.getValue().getVariable(); String variableName = null; // This expression references a variable, but parser did not found // original variable declaration if (variable == null) { final ICompositeNode node = NodeModelUtils.getNode(expression); // Parse all node elements until a variable name is found for (ILeafNode leaf : node.getLeafNodes()) { variableName = leaf.getText(); if (!variableName.trim().isEmpty()) { break; } } } else { variableName = variable.getName(); } // Get the already declared variable with the given name final Var var = declaredVars.get(variableName); if (var == null) { throw new OrccRuntimeException("Unable to find declaration for variable \"" + variableName + "\"."); } return IrFactory.eINSTANCE.createExprVar(var); } @Override public Var caseVariable(Variable variable) { int lineNumber = Util.getLocation(variable); Type type = Typer.getType(variable); String name = variable.getName(); boolean assignable = Util.isAssignable(variable); final Var result = IrFactory.eINSTANCE.createVar(lineNumber, type, name, assignable); if (variable.getValue() != null) { result.setInitialValue((Expression) doSwitch(variable.getValue())); } return result; } }