8#include "InfixToPostfix.h"
12#include "IException.h"
23 InfixToPostfix::~InfixToPostfix() {
90 for(
int i = 0; i < p_operators.size(); i ++) {
91 delete p_operators[i];
110 IString equationIStr = equation;
112 while(!equationIStr.empty()) {
113 IString data = equationIStr.Token(
" ");
142 IString postfix =
"";
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) {
167 else if(data.compare(
")") == 0) {
168 QString postfixQStr = postfix.ToQt();
170 postfix = postfixQStr;
173 QString postfixQStr = postfix.ToQt();
175 postfix = postfixQStr;
181 numConsecutiveOperators = 0;
182 numConsecutiveOperands ++;
186 numConsecutiveOperators = 1;
187 numConsecutiveOperands = 0;
192 numConsecutiveOperators ++;
193 numConsecutiveOperands = 0;
201 catch(IException &) {
202 throw IException(IException::User,
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();
228 throw IException(IException::User,
229 "There are too many opening parentheses ('(') in the equation.",
233 postfix +=
' ' + op +
' ';
239 postfix = postfix.Remove(
",");
254 for(
int i = 0; i < p_operators.size(); i++) {
255 if(representation.compare(p_operators[i]->inputString()) == 0) {
288 while(!theStack.empty()) {
292 if(top.inputString().compare(
"(") == 0) {
297 if(top.precedence() < op.precedence()) {
302 postfix +=
' ' + top.outputString() +
' ';
317 bool openingFound =
false;
318 while(!theStack.empty()) {
322 if(op.inputString().compare(
"(") == 0) {
327 postfix +=
' ' + op.outputString() +
' ';
332 throw IException(IException::User,
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_);
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();
465 return cleanedEquation;
486 while(!equation.isEmpty()) {
487 IString tmp = equation;
489 QString element = tmp.Token(
" ").ToQt();
490 equation = tmp.ToQt();
500 output +=
" ( " + func->inputString() +
" (";
503 if(func->argumentCount() == 0) {
504 IString tmp = equation;
505 QString next = tmp.Token(
" ").ToQt();
506 equation = tmp.ToQt();
515 equation = next +
" " + equation;
518 IString tmp = equation;
521 if(tmp.Token(
" ") !=
")") {
522 throw IException(IException::User,
523 "The function " + func->inputString() +
" should not have any arguments.",
526 equation = tmp.ToQt();
535 IString tmp = equation;
538 if (func->argumentCount() > 1 && tmp.Token(
" ") !=
"(") {
539 throw IException(IException::User,
540 "Missing parenthesis after " + func->inputString(),
544 equation = tmp.ToQt();
547 if(func->argumentCount() == 1) {
549 IString tmp = equation;
550 QString argument = tmp.Token(
" ").ToQt();
551 equation = tmp.ToQt();
553 if(argument !=
"(") {
557 if(func->inputString() !=
"--") {
558 throw IException(IException::User,
559 "Missing parenthesis after " + func->inputString(),
572 QString functionName = argument;
574 IString tmp = equation;
575 QString openParen = tmp.Token(
" ").ToQt();
576 equation = tmp.ToQt();
579 if(openParen !=
"(") {
581 equation = openParen +
" " + equation;
585 functionName +=
" (";
591 while(numParens > -1) {
592 IString tmp = equation;
593 QString newElem = tmp.Token(
" ").ToQt();
594 equation = tmp.ToQt();
597 throw IException(IException::User,
598 "Missing closing parentheses after '" + argument +
"'.",
602 if(newElem ==
"(") numParens++;
603 else if(newElem ==
")") numParens--;
605 functionName +=
" " + newElem;
623 QString argument =
"";
626 while(argNum < func->argumentCount()) {
627 IString tmp = equation;
628 QString elem = tmp.Token(
" ").ToQt();
629 equation = tmp.ToQt();
633 throw IException(IException::User,
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);
653 output +=
" ( " + argument +
" ) , ";
658 if(argNum == func->argumentCount()) {
659 throw IException(IException::User,
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);
672 output +=
" " + argument +
" ) ) ";
677 else if(numParens == -1) {
678 throw IException(IException::User,
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(QRegularExpression(
"[ ()]"));
698 throw IException(IException::User,
699 "Argument " +
toString(argNum + 1) +
" in function " + funcName +
" must not be empty.",
InfixOperator and InfixFunction are helper classes for InfixToPostfix.
InfixOperator and InfixFunction are helper classes for InfixToPostfix.
virtual InfixOperator * findOperator(QString representation)
This method will return a pointer to the operator represented by 'representation.
QString convert(const QString &infix)
This method converts infix to postfix.
bool isFunction(QString representation)
This method will return true if 'representation' is a known function.
QString cleanSpaces(QString equation)
This function takes a space-delimited string and removes empty delimiters.
void initialize()
This populates the known operators/functions list.
virtual bool isKnownSymbol(QString representation)
This method will return true if it believes the argument represents a valid function or operator.
void uninitialize()
This cleans the known operators/functions list.
InfixToPostfix()
Constructor.
QString tokenizeEquation(const QString &equation)
This method will add spaces between all operators and numbers, making it possible to get each element...
void closeParenthesis(QString &postfix, std::stack< InfixOperator > &theStack)
This is straight from the algorithm found on page 159 of "Data Structures & Algorithms in Java" Secon...
void addOperator(QString &postfix, const InfixOperator &op, std::stack< InfixOperator > &theStack)
This is straight from the algorithm found on page 159 of "Data Structures & Algorithms in Java" Secon...
QString formatFunctionCalls(QString equation)
This method looks through equation for function calls, parenthesizes them, and calls itself again wit...
This is free and unencumbered software released into the public domain.
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.
Namespace for the standard library.