/*
* xtc - The eXTensible Compiler
* Copyright (C) 2009-2012 New York University
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.lang.cpp;
import java.util.LinkedList;
import java.util.List;
import java.util.Iterator;
import java.io.StringReader;
import xtc.lang.cpp.Syntax.Kind;
import xtc.parser.Result;
import xtc.tree.GNode;
import xtc.tree.Node;
import xtc.tree.Token;
/**
* A static factory class for expression parsers.
*
* @author Paul Gazzillo
*/
public abstract class ExpressionParser {
/** The SuperC version of the expression parser. */
private static ExpressionParser superc = null;
/** The Rats! version of the expression parser. */
private static ExpressionParser rats = null;
/** A parser that compares the SuperC and Rats! ASTs. */
private static ExpressionParser comparator;
/** Please use static factory methods. */
private ExpressionParser() {
}
/**
* Parse a list of tokens.
*
* @param expression The list of tokens.
* @return The AST.
*/
public abstract Node parse(Iterator<Syntax> expression);
/**
* Return the instance of the expression parser implemented with
* SuperC. This expression parser will only work when preprocessing
* C, since the expression parser takes tokens already lexed as C
* tokens.
*
* @param presenceConditionManager The presence condition manager.
* @return An expression parser implemented with SuperC.
*/
public static ExpressionParser
fromSuperC(final PresenceConditionManager presenceConditionManager) {
if (null == superc) {
superc = new ExpressionParser() {
public Node parse(Iterator<Syntax> expression) {
ForkMergeParser expressionParser
= new ForkMergeParser(ExpressionParseTables.getInstance(),
ExpressionValues.getInstance(),
ExpressionActions.getInstance(), null,
expression, presenceConditionManager);
return (Node) expressionParser.parse();
}
};
}
return superc;
}
/**
* Return the instance of the expression parser implemented with
* Rats.
*
* @return An expression parser implemented with Rats!
*/
public static ExpressionParser fromRats() {
if (null == rats) {
rats = new ExpressionParser() {
public Node parse(Iterator<Syntax> expression) {
StringBuilder string = new StringBuilder();
while (expression.hasNext()) {
Syntax syntax = expression.next();
if (syntax.kind() != Kind.EOF) {
string.append(syntax);
string.append(" ");
}
}
String str = string.toString();
StringReader reader = new StringReader(str);;
ExpressionRats parser
= new ExpressionRats(reader, "EXPRESSION", str.length());
Result result;
Node tree;
try {
result = parser.pConstantExpression(0);
// tree = (Node) parser.value(result);
if (! result.hasValue()) {
tree = null;
System.err.println(parser.format(result.parseError()));
} else {
tree = result.semanticValue();
}
} catch (java.io.IOException e ) {
e.printStackTrace();
throw new RuntimeException("couldn't parse expression");
}
return tree;
}
};
}
return rats;
}
/**
* Compare the two parsers, but return the Rats! parser's AST.
*
* @param presenceConditionManager The presence condition manager.
* @return An expression parser that compares the SuperC and Rats!
* parser.
*/
public static ExpressionParser
comparator(PresenceConditionManager presenceConditionManager) {
final ExpressionParser superc = fromSuperC(presenceConditionManager);
final ExpressionParser rats = fromRats();
if (null == comparator) {
comparator = new ExpressionParser() {
public Node parse(Iterator<Syntax> expression) {
LinkedList<Syntax> list = new LinkedList<Syntax>();
while (expression.hasNext()) {
list.add(expression.next());
}
Node sAST = superc.parse(list.iterator());
Node rAST = rats.parse(list.iterator());
if (! TreeComparator.compare(sAST, rAST)) {
System.err.println("superc: " + sAST);
System.err.println("rats: " + rAST);
throw new RuntimeException("asts are different");
}
return rAST;
}
};
}
return comparator;
}
}