Operator precedence grammar - infix expression into postfix notation and evaluation
According compiler theory of knowledge, we can be the entire program is divided into three parts, lexical analysis, grammar analysis, postfix expression computing, in grammar analysis will involve operator precedence judgment. Next, I will explain the code sub-module, the reader may wish to understand operator precedence grammar, lexical analysis and have postfix expression help.
Code may identify four basic arithmetic exponentiation and comprising brackets, a float can be identified, the error handling operation is not performed when an error.
Operator Precedence
As shown in Array sp, 1 denotes the outer stack higher priority than the priority of the stack, the stack -1 represents the priority lower than the priority of the stack outside, 0 indicates equal priority, require special handling, 99 denotes an input error, the symbol is not or unrecognized input character matches.
For +, -, *, / four operators, since priority in the binding of the left operator, the same reference numerals stack higher than the priority of the external stack; and exponentiation with a right binding, therefore, two an outer ^ compared to stack higher priority than the priority of the stack.
For two different operators, the highest priority, exponentiation () is higher than multiplication and division, subtraction, multiplication and division above.
int SignPriority(char in, char out) {
int sp[9][9] = {{ 1, 1, -1, -1, -1, -1, 1, 1, 99}, //'+'
{ 1, 1, -1, -1, -1, -1, 1, 1, 99}, //'-'
{ 1, 1, 1, 1, -1, -1, 1, 1, 99}, //'*'
{ 1, 1, 1, 1, -1, -1, 1, 1, 99}, //'/'
{ 1, 1, 1, 1, -1, -1, 1, 1, 99}, //'^'
{-1, -1, -1, -1, -1, -1, 0, 99, 99}, //'('
{ 1, 1, 1, 1, 1, 99, 1, 1, 99}, //')'
{-1, -1, -1, -1, -1, -1, 99, 0, 99}, //'#'
{99, 99, 99, 99, 99, 99, 99, 99, 99}}; //other
// +, -, *, /, ^, (, ), #, other
return sp[Sign2Num(in)][Sign2Num(out)];
}
Necessary data structures
struct Word denotes a lexical analysis of the recognized word, flag = true is represented by a digital word, flag = false word is expressed operator.
struct Word {
bool flag;
double num;
char sign;
};
lexical analysis
Lexical analysis, the floating-point number can be identified, it can be used for negative zero by subtracting the number. The formula reads as a string, and at the end to add "#" as the end. Identifying a first character from the beginning, if the identification number, identification continues backwards until the operator identification, as a digital word pushed into the container, a fallback character. If it is identified to the operator, as a primary pressure directly into the container until the identification "#" so far.
vector<Word> LexicalAnalysis(string func) {
func = func+ "#";
int l = func.length();
vector<Word> ans;
for (int i = 0; i < l; i++) {
if (func[i] >= '0' && func[i] <= '9') {
double num = 0;
bool df = false;
double mi = 0;
for ( ; i < l; i++) {
if (!df) {
if (func[i] >= '0' && func[i] <= '9') {
num = num * 10 + static_cast<double>(func[i] - '0');
}
else if (func[i] == '.') {
df = true;
mi = 10.0;
}
}
else {
if (func[i] >= '0' && func[i] <= '9') {
num = num + (func[i] - '0') / mi;
mi *= 10;
}
}
if (!(func[i] >= '0' && func[i] <= '9') && (func[i] != '.')){
Word n;
n.flag = true;
n.num = num;
ans.push_back(n);
num = 0;
break;
}
}
i--;
}
else {
Word s;
s.flag = false;
s.sign = func[i];
if (s.sign != '#') {
ans.push_back(s);
}
}
}
return ans;
}
Parsing
In the syntax analysis, we used a container for storing the postfix expression, sequentially reads out the postfix expression container of operation is also desired. Reading a word from the lexical container, if the digital word, the container pushed into the postfix expression; If the word is the operator, the comparison operator pressed the stack, the stack operators, previously pressed into "# ", to facilitate comparison operator precedence.
Each read an operator, comparing the priority of the operator and the operator of the top of the stack, the stack is read operator Sinotrans operator, operator stack within a stack operator. If the operator stacks a higher priority than the priority of operator sinotrans stack, the top element from the stack, the stack is read into the operator; below the contrary, the operator is read directly into the stack. When reading the right parenthesis ")", all the operator stacks the stack until it encounters the left bracket "(."
After reading unit complete words, all operations Operators symbol stack the stack. All the stack postfix operators into the container.
vector<Word> ParseAnalysis(vector<Word> lpword) {
stack<Word> SignStack;
vector<Word> ans;
Word fst;
fst.flag = false;
fst.sign = '#';
SignStack.push(fst);
for (Word w : lpword) {
if (w.flag) {
ans.push_back(w);
}
else {
if (w.sign == ')') {
while (!SignStack.empty()) {
if (SignStack.top().sign == '(') {
SignStack.pop();
break;
}
ans.push_back(SignStack.top());
SignStack.pop();
}
}
else if (SignPriority(SignStack.top().sign, w.sign) > 0) {
ans.push_back(SignStack.top());
SignStack.pop();
SignStack.push(w);
}
else {
SignStack.push(w);
}
}
}
while (!SignStack.empty()) {
if (SignStack.top().sign != '#') {
ans.push_back(SignStack.top());
}
SignStack.pop();
}
return ans;
}
Postfix expression computing
In the postfix expression calculation, pressed into a digital reading to a digital stack, read the operator, two elements removed from the data stack is calculated, the calculated result onto the stack back to digital, after the element portion is completely read, is the number of elements in the stack operation result.
double Calculatoin(vector<Word> paword) {
stack<double> ans;
for (Word w : paword) {
if (w.flag) {
ans.push(w.num);
}
else {
double a, b;
b = ans.top(); ans.pop();
a = ans.top(); ans.pop();
switch (w.sign) {
case '+':
ans.push(a + b);
break;
case '-':
ans.push(a - b);
break;
case '*':
ans.push(a * b);
break;
case '/':
ans.push(a / b);
break;
case '^':
ans.push(pow(a, b));
break;
}
}
}
return ans.top();
}
Please click on the link below the complete code:
complete code Github link