package ro.infoiasi.donald.compiler.lexer;
import ro.infoiasi.donald.compiler.lexer.exceptions.*;
import ro.infoiasi.donald.compiler.simple.*;
import java.util.*;
public class ExpTree extends BinTree {
private Alphabet alpha = new Alphabet();
public ExpTree() {
super();
}
public ExpTree(ExpList el) throws ExpParseError {
super();
alpha = el.getAlphabet();
addRootSubTree(create(el));
}
private static ExpTree create(AbstractList el) throws ExpParseError {
el = removeParenthesis(el);
ExpTree et = new ExpTree();
if (!el.isEmpty()) {
OperatorToken minOpToken = null;
int minI = 0;
for (int i = 0; i<el.size(); i++) {
Class c = el.get(i).getClass();
if (c == OperatorToken.class) {
OperatorToken opToken = (OperatorToken)el.get(i);
if (minOpToken == null ||
(minOpToken.compareTo(opToken)>0)) {
minOpToken = opToken;
minI = i;
}
} else if (c == ParenthesisLeft.class) {
// skip paranthesis
ParenthesisLeft paraLeft = (ParenthesisLeft)el.get(i);
ParenthesisRight paraRight = paraLeft.pair();
i += paraRight.tokenNo() - paraLeft.tokenNo();
}
}
//System.out.println("[["+minI+"]]");
if (minOpToken == null) {
if (el.size()>1 || el.get(0).getClass() != SymbolToken.class) {
throw new ExpParseError("No operator found",
((ExpToken)el.get(0)).strIndex(),
((ExpToken)el.get(el.size()-1)).strIndex());
} else {
et.addRoot(el.get(0));
}
} else {
et.addRoot(minOpToken);
if (minOpToken.operator().isUnaryLeft()) {
if (minI != el.size()-1) {
throw new ExpParseError("Operator is unary and binds to the left only",
minOpToken.strIndex());
}
ExpTree et1 = create((AbstractList)(el.subList(0,minI)));
if (et1.IsEmpty()) {
throw new ExpParseError("Operator is unary and binds to the left only",
minOpToken.strIndex());
}
et.addLeftSubTree(et1, et.root());
} else if (minOpToken.operator().isUnaryRight()) {
} else if (minOpToken.operator().isBinary()) {
ExpTree et1 = create((AbstractList)(el.subList(0,minI)));
ExpTree et2 = create((AbstractList)(el.subList(minI+1,el.size())));
if (et1.IsEmpty() || et2.IsEmpty()) {
//??? I still have some doubts - the | operator allows an empty operand
throw new ExpParseError("Operator is binary", minOpToken.strIndex());
}
et.addLeftSubTree(et1, et.root());
et.addRightSubTree(et2, et.root());
} else {
throw new ExpParseError("Operator is not unary or binary",
((ExpToken)el.get(0)).strIndex());
}
}
}
return et;
}
private static AbstractList removeParenthesis(AbstractList el) {
boolean over = false;
while (!el.isEmpty() && !over) {
over = true;
if (el.get(0).getClass() == ParenthesisLeft.class &&
el.get(el.size()-1).getClass() == ParenthesisRight.class) {
ParenthesisLeft paraLeft = (ParenthesisLeft)el.get(0);
ParenthesisRight paraRight = (ParenthesisRight)el.get(el.size()-1);
if (paraLeft.pair() == paraRight) {
el = (AbstractList)el.subList(1,el.size()-1);
over = false;
}
}
}
return el;
}
public Alphabet getAlphabet() {
return alpha;
}
}
|