/*
org.manalith.ircbot.plugin.calc/CalcParseTreeGenerator.java
ManalithBot - An open source IRC bot based on the PircBot Framework.
Copyright (C) 2011 Seong-ho, Cho <darkcircle.0426@gmail.com>
This program 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.
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, see <http://www.gnu.org/licenses/>.
*/
package org.manalith.ircbot.plugin.calc;
import org.manalith.ircbot.plugin.calc.TokenUnit.TokenSubtype;
import org.manalith.ircbot.plugin.calc.TokenUnit.TokenType;
import org.manalith.ircbot.plugin.calc.exceptions.InvalidSequenceTokenException;
import org.manalith.ircbot.plugin.calc.exceptions.ParenthesesMismatchException;
public class CalcParseTreeGenerator {
public static ParseTreeUnit generateParseTree(TokenArray sArray)
throws ParenthesesMismatchException, InvalidSequenceTokenException {
int size = sArray.getSize();
ParseTreeUnit pstu_root = new ParseTreeUnit();
int i = 0;
TokenUnit arg0 = null;
TokenUnit op = null;
TokenUnit arg1 = null;
int lparen_cnt = 0;
int rparen_cnt = 0;
// Check whether Pairs of parentheses are match or not.
for (; i < size; i++) {
if (sArray.getToken(i).getTokenSubtype()
.equals(TokenSubtype.Left_Parenthesis))
lparen_cnt++;
if (sArray.getToken(i).getTokenSubtype()
.equals(TokenSubtype.Righ_Parenthesis))
rparen_cnt++;
}
if (lparen_cnt != rparen_cnt)
throw new ParenthesesMismatchException();
i = 0;
while (i < size) {
if (i == 0) {
arg0 = sArray.getToken(i++);
if (arg0.getTokenSubtype().equals(TokenSubtype.Minus)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
pstu_root.setNode(arg0);
pstu_root.setLeftLeapNode(zero);
TokenArray subArray = new TokenArray();
do {
subArray.addToken(sArray.getToken(i++));
} while (i < size);
pstu_root.addRightSubtree(generateParseTree(subArray));
} else if (arg0.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray1 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray1.addToken(temp);
i++;
}
if (i == size || i == size - 1) {
if (subArray1.getSize() == 1) {
pstu_root.setNode(subArray1.getToken(0));
} else {
pstu_root = generateParseTree(subArray1);
}
} else {
op = sArray.getToken(i++);
if (!op.getTokenType().equals(TokenType.Operatr))
throw new InvalidSequenceTokenException(
"Missing Operator");
if (i == size)
throw new InvalidSequenceTokenException(
"Missing Operand.");
arg1 = sArray.getToken(i++);
pstu_root.setNode(op);
pstu_root.addLeftSubtree(generateParseTree(subArray1));
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType()
.equals(TokenType.FlPoint))
pstu_root.setRightLeapNode(arg1);
else if (arg1.getTokenType().equals(TokenType.Parents)
&& arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
pstu_root.setRightLeapNode(subArray2
.getToken(0));
} else {
pstu_root
.addRightSubtree(generateParseTree(subArray2));
}
}
}
} else if (arg0.getTokenType().equals(TokenType.Integer)
|| arg0.getTokenType().equals(TokenType.FlPoint)) {
if (size == 1) {
pstu_root.setNode(arg0);
break;
}
op = sArray.getToken(i++);
if (!op.getTokenType().equals(TokenType.Operatr))
throw new InvalidSequenceTokenException(
"Missing operator.");
if (i == size
&& !op.getTokenSubtype().equals(
TokenSubtype.Factorial))
throw new InvalidSequenceTokenException(
"Missing operand.");
if (op.getTokenSubtype().equals(TokenSubtype.Factorial)) {
arg1 = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
} else {
arg1 = sArray.getToken(i++);
}
pstu_root.setNode(op);
pstu_root.setLeftLeapNode(arg0);
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType().equals(TokenType.FlPoint))
pstu_root.setRightLeapNode(arg1);
else if (arg1.getTokenType().equals(TokenType.Parents)
&& arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
pstu_root.setRightLeapNode(subArray2.getToken(0));
} else {
pstu_root
.addRightSubtree(generateParseTree(subArray2));
}
}
// arg1.getTokenType().equals(TokenType.TriangleFunc)
else if (arg1.getTokenType().equals(TokenType.TriangleFunc)
|| arg1.getTokenType().equals(
TokenType.MathematFunc)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
ParseTreeUnit newSubtree2 = new ParseTreeUnit();
newSubtree2.setNode(arg1); // triangle function
newSubtree2.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
if (!arg1.getTokenType().equals(TokenType.Parents)) {
throw new InvalidSequenceTokenException(
"Left parenthesis is expected.");
}
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree2.setRightLeapNode(subArray2.getToken(0));
} else {
newSubtree2
.addRightSubtree(generateParseTree(subArray2));
}
pstu_root.addRightSubtree(newSubtree2);
} else if (arg1.getTokenType().equals(
TokenType.BaseConvFunc)) {
throw new InvalidSequenceTokenException(
"Base conversion function can be used for whole expression gets integer value.");
} else {
throw new InvalidSequenceTokenException(
"Missing operand.");
}
} else if ((arg0.getTokenType().equals(TokenType.TriangleFunc) || arg0
.getTokenType().equals(TokenType.BaseConvFunc))
|| arg0.getTokenType().equals(TokenType.MathematFunc)) {
pstu_root.setNode(arg0);
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
pstu_root.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
pstu_root.setRightLeapNode(subArray2.getToken(0));
} else {
pstu_root.addRightSubtree(generateParseTree(subArray2));
}
} else {
throw new InvalidSequenceTokenException("Missing operand.");
}
}
// if ( i != 0 )
else {
op = sArray.getToken(i++); // something operator
if (!op.getTokenType().equals(TokenType.Operatr))
throw new InvalidSequenceTokenException("Missing operator.");
if (i == size
&& !op.getTokenSubtype().equals(TokenSubtype.Factorial))
throw new InvalidSequenceTokenException("Missing operand.");
if (op.getTokenSubtype().equals(TokenSubtype.Factorial))
arg1 = sArray.getToken(i++); // can be integer, floating
// point, left parenthesis,
// or function
else {
arg1 = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
}
if (pstu_root.getNode().getTokenType()
.equals(TokenType.BaseConvFunc)) {
throw new InvalidSequenceTokenException(
"more tokens cannot be here.");
}
// The most priority
if (pstu_root.getNode().getTokenSubtype()
.equals(TokenSubtype.Factorial)) {
ParseTreeUnit newSubtree = new ParseTreeUnit();
newSubtree.setNode(op);
newSubtree.addLeftSubtree(pstu_root);
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType().equals(TokenType.FlPoint)) {
newSubtree.setRightLeapNode(arg1);
pstu_root = newSubtree;
} else if (arg1.getTokenType().equals(TokenType.Parents)
&& arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree.setRightLeapNode(subArray2.getToken(0));
} else {
newSubtree
.addRightSubtree(generateParseTree(subArray2));
}
pstu_root = newSubtree;
}
} else if (((pstu_root.getNode().getTokenSubtype() == TokenSubtype.Power || pstu_root
.getNode().getTokenSubtype() == TokenSubtype.Modulus) || (pstu_root
.getNode().getTokenSubtype() == TokenSubtype.Times || pstu_root
.getNode().getTokenSubtype() == TokenSubtype.Divide))
|| (pstu_root.getNode().getTokenType()
.equals(TokenType.TriangleFunc) || pstu_root
.getNode().getTokenType()
.equals(TokenType.MathematFunc))) {
ParseTreeUnit newSubtree = new ParseTreeUnit();
if (op.getTokenSubtype() == TokenSubtype.Power
|| op.getTokenSubtype() == TokenSubtype.Factorial) {
newSubtree.setNode(op);
newSubtree.addLeftSubtree(pstu_root.getRightSubtree());
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType()
.equals(TokenType.FlPoint)) {
newSubtree.setRightLeapNode(arg1);
pstu_root.addRightSubtree(newSubtree);
} else if (arg1.getTokenType()
.equals(TokenType.Parents)
&& arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree
.addRightSubtree(generateParseTree(subArray2));
}
} else if ((arg1.getTokenType().equals(
TokenType.TriangleFunc) || arg1.getTokenType()
.equals(TokenType.BaseConvFunc))
|| arg1.getTokenType().equals(
TokenType.MathematFunc)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
ParseTreeUnit newSubtree2 = new ParseTreeUnit();
newSubtree2.setNode(arg1); // triangle function
newSubtree2.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
if (!arg1.getTokenType().equals(TokenType.Parents)) {
throw new InvalidSequenceTokenException(
"Left parenthesis is expected.");
}
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree2.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree2
.addRightSubtree(generateParseTree(subArray2));
}
newSubtree.addRightSubtree(newSubtree2);
} else {
throw new InvalidSequenceTokenException(
"Missing operand.");
}
} else {
newSubtree.setNode(op);
newSubtree.addLeftSubtree(pstu_root);
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType()
.equals(TokenType.FlPoint)) {
newSubtree.setRightLeapNode(arg1);
pstu_root = newSubtree;
} else if (arg1.getTokenType()
.equals(TokenType.Parents)
|| arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree
.addRightSubtree(generateParseTree(subArray2));
}
pstu_root = newSubtree;
} else if (arg1.getTokenType().equals(
TokenType.TriangleFunc)
|| arg1.getTokenType().equals(
TokenType.MathematFunc)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
ParseTreeUnit newSubtree2 = new ParseTreeUnit();
newSubtree2.setNode(arg1); // triangle function
newSubtree2.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
if (!arg1.getTokenType().equals(TokenType.Parents)) {
throw new InvalidSequenceTokenException(
"Left parenthesis is expected.");
}
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree2.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree2
.addRightSubtree(generateParseTree(subArray2));
}
newSubtree.addRightSubtree(newSubtree2);
pstu_root = newSubtree;
} else if (arg1.getTokenType().equals(
TokenType.BaseConvFunc))
throw new InvalidSequenceTokenException(
"Base conversion function can be used for whole expression gets integer value.");
else {
throw new InvalidSequenceTokenException(
"Missing operand.");
}
}
}
// The least priority
else if (pstu_root.getNode().getTokenSubtype()
.equals(TokenSubtype.Plus)
|| pstu_root.getNode().getTokenSubtype()
.equals(TokenSubtype.Minus)) {
ParseTreeUnit newSubtree = new ParseTreeUnit();
if ((op.getTokenSubtype().equals(TokenSubtype.Power) || op
.getTokenSubtype().equals(TokenSubtype.Modulus))
|| (op.getTokenSubtype().equals(TokenSubtype.Times) || op
.getTokenSubtype().equals(
TokenSubtype.Divide))
|| op.getTokenSubtype().equals(
TokenSubtype.Factorial)) {
newSubtree.setNode(op);
newSubtree.addLeftSubtree(pstu_root.getRightSubtree());
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType()
.equals(TokenType.FlPoint)) {
newSubtree.setRightLeapNode(arg1);
pstu_root.addRightSubtree(newSubtree);
} else if (arg1.getTokenType()
.equals(TokenType.Parents)
|| arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree
.addRightSubtree(generateParseTree(subArray2));
}
} else if (arg1.getTokenType().equals(
TokenType.TriangleFunc)
|| arg1.getTokenType().equals(
TokenType.MathematFunc)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
ParseTreeUnit newSubtree2 = new ParseTreeUnit();
newSubtree2.setNode(arg1); // triangle function
newSubtree2.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
if (!arg1.getTokenType().equals(TokenType.Parents)) {
throw new InvalidSequenceTokenException(
"Left parenthesis is expected.");
}
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree2.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree2
.addRightSubtree(generateParseTree(subArray2));
}
newSubtree.addRightSubtree(newSubtree2);
} else if (arg1.getTokenType().equals(
TokenType.BaseConvFunc)) {
throw new InvalidSequenceTokenException(
"Base conversion function can be used for whole expression gets integer value.");
} else {
throw new InvalidSequenceTokenException(
"Missing operand.");
}
} else {
newSubtree.setNode(op);
newSubtree.addLeftSubtree(pstu_root);
if (arg1.getTokenType().equals(TokenType.Integer)
|| arg1.getTokenType()
.equals(TokenType.FlPoint)) {
newSubtree.setRightLeapNode(arg1);
pstu_root = newSubtree;
} else if (arg1.getTokenType()
.equals(TokenType.Parents)
|| arg1.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis)) {
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree
.addRightSubtree(generateParseTree(subArray2));
}
pstu_root = newSubtree;
} else if (arg1.getTokenType().equals(
TokenType.TriangleFunc)
|| arg1.getTokenType().equals(
TokenType.MathematFunc)) {
TokenUnit zero = new TokenUnit(TokenType.Integer,
TokenSubtype.Decimal, "0");
ParseTreeUnit newSubtree2 = new ParseTreeUnit();
newSubtree2.setNode(arg1); // triangle function
newSubtree2.setLeftLeapNode(zero);
arg1 = sArray.getToken(i++);
if (!arg1.getTokenType().equals(TokenType.Parents)) {
throw new InvalidSequenceTokenException(
"Left parenthesis is expected.");
}
TokenArray subArray2 = new TokenArray();
int skipPairofParentheses = 0;
while (true) {
TokenUnit temp = sArray.getToken(i);
if (temp.getTokenSubtype().equals(
TokenSubtype.Left_Parenthesis))
skipPairofParentheses++;
if (temp.getTokenSubtype().equals(
TokenSubtype.Righ_Parenthesis))
skipPairofParentheses--;
if (skipPairofParentheses == -1) {
i++;
break;
}
subArray2.addToken(temp);
i++;
}
if (subArray2.getSize() == 1) {
newSubtree2.setRightLeapNode(subArray2
.getToken(0));
} else {
newSubtree2
.addRightSubtree(generateParseTree(subArray2));
}
newSubtree.addRightSubtree(newSubtree2);
pstu_root = newSubtree;
} else if (arg1.getTokenType().equals(
TokenType.BaseConvFunc)) {
throw new InvalidSequenceTokenException(
"Base conversion function can be used for whole expression gets integer value.");
} else {
throw new InvalidSequenceTokenException(
"Missing operand.");
}
}
}
}
}
return pstu_root;
}
}