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] ==
'=') {
429 else if(i < equation.size() - 1 && equation[i] ==
'|' && equation[i+1] ==
'|') {
433 else if(i < equation.size() - 1 && equation[i] ==
'&' && equation[i+1] ==
'&') {
438 else if((i > 1) && equation[i] ==
'-' && equation[i-1].toLower() ==
'e' && equation[i-2].isLetterOrNumber()) {
439 output += equation[i].toLatin1();
442 else if(equation[i] ==
'-') {
443 bool isNegative =
true;
446 for(
int index = i - 1; index >= 0; index --) {
447 if(equation[index] ==
' ') {
451 if(equation[index] !=
'(' && equation[index] !=
'/' &&
452 equation[index] !=
'*' && equation[index] !=
'+') {
469 output += equation[i].toLatin1();
474 output += equation[i].toLatin1();
478 QString cleanedEquation = cleanSpaces(formatFunctionCalls(output.
DownCase().
ToQt()));
480 return cleanedEquation;
494 QString InfixToPostfix::formatFunctionCalls(QString equation) {
496 equation = cleanSpaces(equation);
501 while(!equation.isEmpty()) {
505 equation = tmp.
ToQt();
508 if(isFunction(element)) {
515 output +=
" ( " + func->inputString() +
" (";
518 if(func->argumentCount() == 0) {
521 equation = tmp.
ToQt();
530 equation = next +
" " + equation;
536 if(tmp.
Token(
" ") !=
")") {
538 "The function " + func->inputString() +
" should not have any arguments.",
541 equation = tmp.
ToQt();
553 if (func->argumentCount() > 1 && tmp.
Token(
" ") !=
"(") {
555 "Missing parenthesis after " + func->inputString(),
559 equation = tmp.
ToQt();
562 if(func->argumentCount() == 1) {
565 QString argument = tmp.
Token(
" ").
ToQt();
566 equation = tmp.
ToQt();
568 if(argument !=
"(") {
572 if(func->inputString() !=
"--") {
574 "Missing parenthesis after " + func->inputString(),
579 if(!isFunction(argument)) {
581 output +=
" " + formatFunctionCalls(argument) +
" ) ) ";
587 QString functionName = argument;
590 QString openParen = tmp.
Token(
" ").
ToQt();
591 equation = tmp.
ToQt();
594 if(openParen !=
"(") {
595 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
596 equation = openParen +
" " + equation;
600 functionName +=
" (";
606 while(numParens > -1) {
609 equation = tmp.
ToQt();
613 "Missing closing parentheses after '" + argument +
"'.",
617 if(newElem ==
"(") numParens++;
618 else if(newElem ==
")") numParens--;
620 functionName +=
" " + newElem;
623 output +=
" " + formatFunctionCalls(functionName) +
" ) ) ";
638 QString argument =
"";
641 while(argNum < func->argumentCount()) {
644 equation = tmp.
ToQt();
649 "The definition of '" + func->inputString() +
"' is not complete.",
657 else if(elem ==
")") {
661 if(numParens != -1) {
665 else if(elem ==
"," && numParens == 0) {
666 checkArgument(func->inputString(), argNum, argument);
667 argument = formatFunctionCalls(argument);
668 output +=
" ( " + argument +
" ) , ";
673 if(argNum == func->argumentCount()) {
675 "There were too many arguments supplied to the function '" + func->inputString() +
"'.",
680 argument +=
" " + elem;
683 if(argNum == func->argumentCount() - 1 && numParens == -1) {
684 checkArgument(func->inputString(), argNum, argument);
685 argument = formatFunctionCalls(argument);
687 output +=
" " + argument +
" ) ) ";
692 else if(numParens == -1) {
694 "There were not enough arguments supplied to the function '" + func->inputString() +
"'.",
702 output = output +
" " + element;
709 void InfixToPostfix::checkArgument(QString funcName,
int argNum, QString argument) {
710 argument = argument.remove(QRegExp(
"[ ()]"));
714 "Argument " +
toString(argNum + 1) +
" in function " + funcName +
" must not be empty.",
Namespace for the standard library.
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.
QString ToQt() const
Retuns the object string as a QString.
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.
Namespace for ISIS/Bullet specific routines.