8 #include "InfixToPostfix.h"
12 #include "IException.h"
19 InfixToPostfix::InfixToPostfix() {
23 InfixToPostfix::~InfixToPostfix() {
31 void InfixToPostfix::initialize() {
89 void InfixToPostfix::uninitialize() {
90 for(
int i = 0; i < p_operators.size(); i ++) {
91 delete p_operators[i];
109 QString InfixToPostfix::cleanSpaces(QString equation) {
110 IString equationIStr = equation;
112 while(!equationIStr.empty()) {
139 QString InfixToPostfix::convert(
const QString &infix) {
141 IString equation = tokenizeEquation(infix);
145 std::stack<InfixOperator> theStack;
149 int numConsecutiveOperands = 0;
153 int numConsecutiveOperators = 0;
158 while(!equation.empty()) {
162 QString data = equation.
Token(
" ").
ToQt();
164 if(data.compare(
"(") == 0) {
165 theStack.push(*findOperator(data));
167 else if(data.compare(
")") == 0) {
168 QString postfixQStr = postfix.
ToQt();
169 closeParenthesis(postfixQStr, theStack);
170 postfix = postfixQStr;
172 else if(isKnownSymbol(data)) {
173 QString postfixQStr = postfix.
ToQt();
174 addOperator(postfixQStr, *findOperator(data), theStack);
175 postfix = postfixQStr;
177 if(isFunction(data)) {
180 if(((
InfixFunction *)findOperator(data))->argumentCount() == 0) {
181 numConsecutiveOperators = 0;
182 numConsecutiveOperands ++;
186 numConsecutiveOperators = 1;
187 numConsecutiveOperands = 0;
192 numConsecutiveOperators ++;
193 numConsecutiveOperands = 0;
203 "The operator '" + data +
"' is not recognized.",
208 numConsecutiveOperators = 0;
209 numConsecutiveOperands ++;
211 postfix +=
IString(
' ' + data +
' ');
215 if(numConsecutiveOperators > 1) {
216 throw IException(IException::User,
"Missing an operand near the operator '" + data +
"'.", _FILEINFO_);
218 else if(numConsecutiveOperands > 1) {
219 throw IException(IException::User,
"Missing an operator before " + data +
".", _FILEINFO_);
223 while(!theStack.empty()) {
224 IString op = theStack.top().outputString();
229 "There are too many opening parentheses ('(') in the equation.",
233 postfix +=
' ' + op +
' ';
239 postfix = postfix.
Remove(
",");
242 return cleanSpaces(postfix.
ToQt());
253 bool InfixToPostfix::isKnownSymbol(QString representation) {
254 for(
int i = 0; i < p_operators.size(); i++) {
255 if(representation.compare(p_operators[i]->inputString()) == 0) {
270 bool InfixToPostfix::isFunction(QString representation) {
271 if(isKnownSymbol(representation)) {
272 return findOperator(representation)->isFunction();
287 void InfixToPostfix::addOperator(QString &postfix,
const InfixOperator &op, std::stack<InfixOperator> &theStack) {
288 while(!theStack.empty()) {
292 if(top.inputString().compare(
"(") == 0) {
297 if(top.precedence() < op.precedence()) {
302 postfix +=
' ' + top.outputString() +
' ';
316 void InfixToPostfix::closeParenthesis(QString &postfix, std::stack<InfixOperator> &theStack) {
317 bool openingFound =
false;
318 while(!theStack.empty()) {
322 if(op.inputString().compare(
"(") == 0) {
327 postfix +=
' ' + op.outputString() +
' ';
333 "There are too many closing parentheses (')') in the equation.",
348 for(
int i = 0; i < p_operators.size(); i++) {
349 if(representation.compare(p_operators[i]->inputString()) == 0) {
350 return p_operators[i];
355 throw IException(IException::User,
"The operator '" + representation +
"' is not recognized.", _FILEINFO_);
369 QString InfixToPostfix::tokenizeEquation(
const QString &equation) {
374 for(
int i = 0; i < equation.size(); i++) {
376 if(!equation[i].isLetterOrNumber() && !equation[i].isSpace() &&
377 equation[i] !=
'.' && equation[i] !=
'_') {
379 if(equation[i] ==
'[' || equation[i] ==
'{') {
382 else if(equation[i] ==
']' || equation[i] ==
'}') {
386 else if(i < equation.size() - 1 && equation[i] ==
'-' && equation[i+1] ==
'-') {
390 else if(i < equation.size() - 1 && equation[i] ==
'<' && equation[i+1] ==
'<') {
394 else if(i < equation.size() - 1 && equation[i] ==
'>' && equation[i+1] ==
'>') {
398 else if(i < equation.size() - 1 && equation[i] ==
'>' && equation[i+1] ==
'=') {
402 else if(i < equation.size() - 1 && equation[i] ==
'<' && equation[i+1] ==
'=') {
406 else if(i < equation.size() - 1 && equation[i] ==
'=' && equation[i+1] ==
'=') {
410 else if(i < equation.size() - 1 && equation[i] ==
'!' && equation[i+1] ==
'=') {
414 else if(i < equation.size() - 1 && equation[i] ==
'|' && equation[i+1] ==
'|') {
418 else if(i < equation.size() - 1 && equation[i] ==
'&' && equation[i+1] ==
'&') {
423 else if((i > 1) && equation[i] ==
'-' && equation[i-1].toLower() ==
'e' && equation[i-2].isLetterOrNumber()) {
424 output += equation[i].toLatin1();
427 else if(equation[i] ==
'-') {
428 bool isNegative =
true;
431 for(
int index = i - 1; index >= 0; index --) {
432 if(equation[index] ==
' ') {
436 if(equation[index] !=
'(' && equation[index] !=
'/' &&
437 equation[index] !=
'*' && equation[index] !=
'+') {
454 output += equation[i].toLatin1();
459 output += equation[i].toLatin1();
463 QString cleanedEquation = cleanSpaces(formatFunctionCalls(output.
DownCase().
ToQt()));
465 return cleanedEquation;
479 QString InfixToPostfix::formatFunctionCalls(QString equation) {
481 equation = cleanSpaces(equation);
486 while(!equation.isEmpty()) {
490 equation = tmp.
ToQt();
493 if(isFunction(element)) {
500 output +=
" ( " + func->inputString() +
" (";
503 if(func->argumentCount() == 0) {
506 equation = tmp.
ToQt();
515 equation = next +
" " + equation;
521 if(tmp.
Token(
" ") !=
")") {
523 "The function " + func->inputString() +
" should not have any arguments.",
526 equation = tmp.
ToQt();
538 if (func->argumentCount() > 1 && tmp.
Token(
" ") !=
"(") {
540 "Missing parenthesis after " + func->inputString(),
544 equation = tmp.
ToQt();
547 if(func->argumentCount() == 1) {
550 QString argument = tmp.
Token(
" ").
ToQt();
551 equation = tmp.
ToQt();
553 if(argument !=
"(") {
557 if(func->inputString() !=
"--") {
559 "Missing parenthesis after " + func->inputString(),
564 if(!isFunction(argument)) {
566 output +=
" " + formatFunctionCalls(argument) +
" ) ) ";
572 QString functionName = argument;
575 QString openParen = tmp.
Token(
" ").
ToQt();
576 equation = tmp.
ToQt();
579 if(openParen !=
"(") {
580 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
581 equation = openParen +
" " + equation;
585 functionName +=
" (";
591 while(numParens > -1) {
594 equation = tmp.
ToQt();
598 "Missing closing parentheses after '" + argument +
"'.",
602 if(newElem ==
"(") numParens++;
603 else if(newElem ==
")") numParens--;
605 functionName +=
" " + newElem;
608 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
623 QString argument =
"";
626 while(argNum < func->argumentCount()) {
629 equation = tmp.
ToQt();
634 "The definition of '" + func->inputString() +
"' is not complete.",
642 else if(elem ==
")") {
646 if(numParens != -1) {
650 else if(elem ==
"," && numParens == 0) {
651 checkArgument(func->inputString(), argNum, argument);
652 argument = formatFunctionCalls(argument);
653 output +=
" ( " + argument +
" ) , ";
658 if(argNum == func->argumentCount()) {
660 "There were too many arguments supplied to the function '" + func->inputString() +
"'.",
665 argument +=
" " + elem;
668 if(argNum == func->argumentCount() - 1 && numParens == -1) {
669 checkArgument(func->inputString(), argNum, argument);
670 argument = formatFunctionCalls(argument);
672 output +=
" " + argument +
" ) ) ";
677 else if(numParens == -1) {
679 "There were not enough arguments supplied to the function '" + func->inputString() +
"'.",
687 output = output +
" " + element;
694 void InfixToPostfix::checkArgument(QString funcName,
int argNum, QString argument) {
695 argument = argument.remove(QRegExp(
"[ ()]"));
699 "Argument " +
toString(argNum + 1) +
" in function " + funcName +
" must not be empty.",