34 InfixToPostfix::InfixToPostfix() {
38 InfixToPostfix::~InfixToPostfix() {
46 void InfixToPostfix::initialize() {
104 void InfixToPostfix::uninitialize() {
105 for(
int i = 0; i < p_operators.size(); i ++) {
106 delete p_operators[i];
124 QString InfixToPostfix::cleanSpaces(QString equation) {
125 IString equationIStr = equation;
127 while(!equationIStr.empty()) {
154 QString InfixToPostfix::convert(
const QString &infix) {
156 IString equation = tokenizeEquation(infix);
160 std::stack<InfixOperator> theStack;
164 int numConsecutiveOperands = 0;
168 int numConsecutiveOperators = 0;
173 while(!equation.empty()) {
177 QString data = equation.
Token(
" ").
ToQt();
179 if(data.compare(
"(") == 0) {
180 theStack.push(*findOperator(data));
182 else if(data.compare(
")") == 0) {
183 QString postfixQStr = postfix.
ToQt();
184 closeParenthesis(postfixQStr, theStack);
185 postfix = postfixQStr;
187 else if(isKnownSymbol(data)) {
188 QString postfixQStr = postfix.
ToQt();
189 addOperator(postfixQStr, *findOperator(data), theStack);
190 postfix = postfixQStr;
192 if(isFunction(data)) {
195 if(((
InfixFunction *)findOperator(data))->argumentCount() == 0) {
196 numConsecutiveOperators = 0;
197 numConsecutiveOperands ++;
201 numConsecutiveOperators = 1;
202 numConsecutiveOperands = 0;
207 numConsecutiveOperators ++;
208 numConsecutiveOperands = 0;
218 "The operator '" + data +
"' is not recognized.",
223 numConsecutiveOperators = 0;
224 numConsecutiveOperands ++;
226 postfix +=
IString(
' ' + data +
' ');
230 if(numConsecutiveOperators > 1) {
231 throw IException(IException::User,
"Missing an operand near the operator '" + data +
"'.",
_FILEINFO_);
233 else if(numConsecutiveOperands > 1) {
238 while(!theStack.empty()) {
239 IString op = theStack.top().outputString();
244 "There are too many opening parentheses ('(') in the equation.",
248 postfix +=
' ' + op +
' ';
254 postfix = postfix.
Remove(
",");
257 return cleanSpaces(postfix.
ToQt());
268 bool InfixToPostfix::isKnownSymbol(QString representation) {
269 for(
int i = 0; i < p_operators.size(); i++) {
270 if(representation.compare(p_operators[i]->inputString()) == 0) {
285 bool InfixToPostfix::isFunction(QString representation) {
286 if(isKnownSymbol(representation)) {
287 return findOperator(representation)->isFunction();
302 void InfixToPostfix::addOperator(QString &postfix,
const InfixOperator &op, std::stack<InfixOperator> &theStack) {
303 while(!theStack.empty()) {
307 if(top.inputString().compare(
"(") == 0) {
312 if(top.precedence() < op.precedence()) {
317 postfix +=
' ' + top.outputString() +
' ';
331 void InfixToPostfix::closeParenthesis(QString &postfix, std::stack<InfixOperator> &theStack) {
332 bool openingFound =
false;
333 while(!theStack.empty()) {
337 if(op.inputString().compare(
"(") == 0) {
342 postfix +=
' ' + op.outputString() +
' ';
348 "There are too many closing parentheses (')') in the equation.",
363 for(
int i = 0; i < p_operators.size(); i++) {
364 if(representation.compare(p_operators[i]->inputString()) == 0) {
365 return p_operators[i];
370 throw IException(IException::User,
"The operator '" + representation +
"' is not recognized.",
_FILEINFO_);
384 QString InfixToPostfix::tokenizeEquation(
const QString &equation) {
389 for(
int i = 0; i < equation.size(); i++) {
391 if(!equation[i].isLetterOrNumber() && !equation[i].isSpace() &&
392 equation[i] !=
'.' && equation[i] !=
'_') {
394 if(equation[i] ==
'[' || equation[i] ==
'{') {
397 else if(equation[i] ==
']' || equation[i] ==
'}') {
401 else if(i < equation.size() - 1 && equation[i] ==
'-' && equation[i+1] ==
'-') {
405 else if(i < equation.size() - 1 && equation[i] ==
'<' && equation[i+1] ==
'<') {
409 else if(i < equation.size() - 1 && equation[i] ==
'>' && equation[i+1] ==
'>') {
413 else if(i < equation.size() - 1 && equation[i] ==
'>' && equation[i+1] ==
'=') {
417 else if(i < equation.size() - 1 && equation[i] ==
'<' && equation[i+1] ==
'=') {
421 else if(i < equation.size() - 1 && equation[i] ==
'=' && equation[i+1] ==
'=') {
425 else if(i < equation.size() - 1 && equation[i] ==
'!' && equation[i+1] ==
'=') {
430 else if((i > 1) && equation[i] ==
'-' && equation[i-1].toLower() ==
'e' && equation[i-2].isLetterOrNumber()) {
431 output += equation[i].toLatin1();
434 else if(equation[i] ==
'-') {
435 bool isNegative =
true;
438 for(
int index = i - 1; index >= 0; index --) {
439 if(equation[index] ==
' ') {
443 if(equation[index] !=
'(' && equation[index] !=
'/' &&
444 equation[index] !=
'*' && equation[index] !=
'+') {
461 output += equation[i].toLatin1();
466 output += equation[i].toLatin1();
470 QString cleanedEquation = cleanSpaces(formatFunctionCalls(output.
DownCase().
ToQt()));
472 return cleanedEquation;
486 QString InfixToPostfix::formatFunctionCalls(QString equation) {
488 equation = cleanSpaces(equation);
493 while(!equation.isEmpty()) {
497 equation = tmp.
ToQt();
500 if(isFunction(element)) {
507 output +=
" ( " + func->inputString() +
" (";
510 if(func->argumentCount() == 0) {
513 equation = tmp.
ToQt();
522 equation = next +
" " + equation;
528 if(tmp.
Token(
" ") !=
")") {
530 "The function " + func->inputString() +
" should not have any arguments.",
533 equation = tmp.
ToQt();
545 if (func->argumentCount() > 1 && tmp.
Token(
" ") !=
"(") {
547 "Missing parenthesis after " + func->inputString(),
551 equation = tmp.
ToQt();
554 if(func->argumentCount() == 1) {
557 QString argument = tmp.
Token(
" ").
ToQt();
558 equation = tmp.
ToQt();
560 if(argument !=
"(") {
564 if(func->inputString() !=
"--") {
566 "Missing parenthesis after " + func->inputString(),
571 if(!isFunction(argument)) {
573 output +=
" " + formatFunctionCalls(argument) +
" ) ) ";
579 QString functionName = argument;
582 QString openParen = tmp.
Token(
" ").
ToQt();
583 equation = tmp.
ToQt();
586 if(openParen !=
"(") {
587 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
588 equation = openParen +
" " + equation;
592 functionName +=
" (";
598 while(numParens > -1) {
601 equation = tmp.
ToQt();
605 "Missing closing parentheses after '" + argument +
"'.",
609 if(newElem ==
"(") numParens++;
610 else if(newElem ==
")") numParens--;
612 functionName +=
" " + newElem;
615 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
630 QString argument =
"";
633 while(argNum < func->argumentCount()) {
636 equation = tmp.
ToQt();
641 "The definition of '" + func->inputString() +
"' is not complete.",
649 else if(elem ==
")") {
653 if(numParens != -1) {
657 else if(elem ==
"," && numParens == 0) {
658 checkArgument(func->inputString(), argNum, argument);
659 argument = formatFunctionCalls(argument);
660 output +=
" ( " + argument +
" ) , ";
665 if(argNum == func->argumentCount()) {
667 "There were too many arguments supplied to the function '" + func->inputString() +
"'.",
672 argument +=
" " + elem;
675 if(argNum == func->argumentCount() - 1 && numParens == -1) {
676 checkArgument(func->inputString(), argNum, argument);
677 argument = formatFunctionCalls(argument);
679 output +=
" " + argument +
" ) ) ";
684 else if(numParens == -1) {
686 "There were not enough arguments supplied to the function '" + func->inputString() +
"'.",
694 output = output +
" " + element;
701 void InfixToPostfix::checkArgument(QString funcName,
int argNum, QString argument) {
702 argument = argument.remove(QRegExp(
"[ ()]"));
706 "Argument " +
toString(argNum + 1) +
" in function " + funcName +
" must not be empty.",
QString ToQt() const
Retuns the object string as a QString.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
double toDouble(const QString &string)
Global function to convert from a string to a double.
IString Token(const IString &separator)
Returns the first token in the IString.
InfixOperator and InfixFunction are helper classes for InfixToPostfix.
InfixOperator and InfixFunction are helper classes for InfixToPostfix.
#define _FILEINFO_
Macro for the filename and line number.
IString Remove(const std::string &del)
Remove all instances of any character in the string from the IString.
IString DownCase()
Converts all upper case letters in the object IString into lower case characters. ...
Adds specific functionality to C++ strings.