static bool shunting_yard(const TCHAR *input, TCHAR *output) { const TCHAR *strpos = input, *strend = input + _tcslen(input); TCHAR c, *outpos = output; TCHAR stack[STACK_SIZE]; // operator stack unsigned int sl = 0; // stack length TCHAR sc; // used for record stack element while(strpos < strend) { if (sl >= STACK_SIZE) return false; // read one token from the input stream c = *strpos; if(c != ' ') { // If the token is a number (identifier), then add it to the output queue. if(is_ident(c)) { *outpos = c; ++outpos; } // If the token is a function token, then push it onto the stack. else if(is_function(c)) { stack[sl] = c; ++sl; } // If the token is a function argument separator (e.g., a comma): else if(c == ',') { bool pe = false; while(sl > 0) { sc = stack[sl - 1]; if(sc == '(') { pe = true; break; } else { // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue. *outpos = sc; ++outpos; sl--; } } // If no left parentheses are encountered, either the separator was misplaced // or parentheses were mismatched. if(!pe) { calc_log ((_T("Error: separator or parentheses mismatched\n"))); return false; } } // If the token is an operator, op1, then: else if(is_operator(c)) { while(sl > 0) { sc = stack[sl - 1]; // While there is an operator token, o2, at the top of the stack // op1 is left-associative and its precedence is less than or equal to that of op2, // or op1 is right-associative and its precedence is less than that of op2, if(is_operator(sc) && ((op_left_assoc(c) && (op_preced(c) <= op_preced(sc))) || (!op_left_assoc(c) && (op_preced(c) < op_preced(sc))))) { // Pop o2 off the stack, onto the output queue; *outpos = sc; ++outpos; sl--; } else { break; } } // push op1 onto the stack. stack[sl] = c; ++sl; } // If the token is a left parenthesis, then push it onto the stack. else if(c == '(') { stack[sl] = c; ++sl; } // If the token is a right parenthesis: else if(c == ')') { bool pe = false; // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue while(sl > 0) { sc = stack[sl - 1]; if(sc == '(') { pe = true; break; } else { *outpos = sc; ++outpos; sl--; } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if(!pe) { calc_log ((_T("Error: parentheses mismatched\n"))); return false; } // Pop the left parenthesis from the stack, but not onto the output queue. sl--; // If the token at the top of the stack is a function token, pop it onto the output queue. if(sl > 0) { sc = stack[sl - 1]; if(is_function(sc)) { *outpos = sc; ++outpos; sl--; } } } else { calc_log ((_T("Unknown token %c\n"), c)); return false; // Unknown token } } ++strpos; } // When there are no more tokens to read: // While there are still operator tokens in the stack: while(sl > 0) { sc = stack[sl - 1]; if(sc == '(' || sc == ')') { printf("Error: parentheses mismatched\n"); return false; } *outpos = sc; ++outpos; --sl; } *outpos = 0; // Null terminator return true; }
bool shunting_yard(const char *input, char *output) { const char *strpos = input, *strend = input + strlen(input); char c, *outpos = output; char stack[512]; // operator stack unsigned int sl = 0; // stack length char sc; // used for record stack element while(strpos < strend) { // read one token from the input stream c = *strpos; if(c != ' ') { // If the token is a number (identifier), then add it to the output queue. if(is_ident(c)) { *outpos = c; ++outpos; } // If the token is a function token, then push it onto the stack. else if(is_function(c)) { stack[sl] = c; ++sl; } // If the token is a function argument separator (e.g., a comma): else if(c == ',') { bool pe = false; while(sl > 0) { sc = stack[sl - 1]; if(sc == '(') { pe = true; break; } else { // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue. *outpos = sc; ++outpos; sl--; } } // If no left parentheses are encountered, either the separator was misplaced // or parentheses were mismatched. if(!pe) { printf("Error: separator or parentheses mismatched\n"); return false; } } // If the token is an operator, op1, then: else if(is_operator(c)) { while(sl > 0) { sc = stack[sl - 1]; if(is_operator(sc) && ((op_left_assoc(c) && (op_preced(c) >= op_preced(sc))) || (op_preced(c) > op_preced(sc)))) { // Pop op2 off the stack, onto the output queue; *outpos = sc; ++outpos; sl--; } else { break; } } // push op1 onto the stack. stack[sl] = c; ++sl; } // If the token is a left parenthesis, then push it onto the stack. else if(c == '(') { stack[sl] = c; ++sl; } // If the token is a right parenthesis: else if(c == ')') { bool pe = false; // Until the token at the top of the stack is a left parenthesis, // pop operators off the stack onto the output queue while(sl > 0) { sc = stack[sl - 1]; if(sc == '(') { pe = true; break; } else { *outpos = sc; ++outpos; sl--; } } // If the stack runs out without finding a left parenthesis, then there are mismatched parentheses. if(!pe) { printf("Error: parentheses mismatched\n"); return false; } // Pop the left parenthesis from the stack, but not onto the output queue. sl--; // If the token at the top of the stack is a function token, pop it onto the output queue. if(sl > 0) { sc = stack[sl - 1]; if(is_function(sc)) { *outpos = sc; ++outpos; sl--; } } } else { printf("Unknown token <%c>\n", c); return false; // Unknown token } } ++strpos; } // When there are no more tokens to read: // While there are still operator tokens in the stack: while(sl > 0) { sc = stack[sl - 1]; if(sc == '(' || sc == ')') { printf("Error: parentheses mismatched\n"); return false; } *outpos = sc; ++outpos; --sl; } *outpos = 0; // Null terminator return true; }