/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.antar.expr.parser;
import java.io.PushbackReader;
import java.io.StringReader;
import java.util.logging.Logger;
import org.openflexo.antar.expr.ArithmeticUnaryOperator;
import org.openflexo.antar.expr.Constant.ArithmeticConstant;
import org.openflexo.antar.expr.Constant.FloatConstant;
import org.openflexo.antar.expr.Constant.IntegerConstant;
import org.openflexo.antar.expr.Expression;
import org.openflexo.antar.expr.UnaryOperatorExpression;
import org.openflexo.antar.expr.parser.lexer.Lexer;
import org.openflexo.antar.expr.parser.node.Start;
import org.openflexo.antar.expr.parser.parser.Parser;
/**
* This class provides the parsing service for AnTAR expressions and bindings. This includes syntaxic and semantics analyzer.<br>
*
* SableCC is extensively used to perform this. To compile and generate the grammar, please invoke {@link CompileAntarExpressionParser}
* located in src/dev/java. The grammar is located in src/main/resources/antar_expr.grammar.<br>
* Generated code is located in org.openflexo.antar.expr.parser.analysis, org.openflexo.antar.expr.parser.lexer,
* org.openflexo.antar.expr.parser.node, org.openflexo.antar.expr.parser.parser
*
* @author sylvain
*/
public class ExpressionParser {
private static final Logger logger = Logger.getLogger(ExpressionParser.class.getPackage().getName());
/**
* This is the method to invoke to perform a parsing. Syntaxic and (some) semantics analyzer are performed and returned value is an
* Expression conform to AnTAR expression abstract syntaxic tree
*
* @param anExpression
* @return
* @throws ParseException
* if expression was not parsable
*/
public static Expression parse(String anExpression) throws ParseException {
try {
// System.out.println("Parsing: " + anExpression);
// Create a Parser instance.
Parser p = new Parser(new Lexer(new PushbackReader(new StringReader(anExpression))));
// Parse the input.
Start tree = p.parse();
// Apply the semantics analyzer.
ExpressionSemanticsAnalyzer t = new ExpressionSemanticsAnalyzer();
tree.apply(t);
return postSemanticAnalysisReduction(t.getExpression());
} catch (Exception e) {
throw new ParseException(e.getMessage() + " while parsing " + anExpression);
}
}
/**
* This method is invoked at the end of the parsing to perform some trivial reductions (eg, a combination of a minus and an arithmetic
* value results in a negative arithmetic value)
*
* @param e
* @return
*/
private static Expression postSemanticAnalysisReduction(Expression e) {
if (e instanceof UnaryOperatorExpression && ((UnaryOperatorExpression) e).getOperator() == ArithmeticUnaryOperator.UNARY_MINUS
&& ((UnaryOperatorExpression) e).getArgument() instanceof ArithmeticConstant) {
// In this case, we will reduce this into a negative single arithmetic constant
ArithmeticConstant<?> c = (ArithmeticConstant<?>) ((UnaryOperatorExpression) e).getArgument();
if (c instanceof IntegerConstant) {
return new IntegerConstant(-((IntegerConstant) c).getValue());
} else if (c instanceof FloatConstant) {
return new FloatConstant(-((FloatConstant) c).getValue());
} else {
logger.warning("Unexpected " + c);
}
}
return e;
}
}