-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.h
142 lines (116 loc) · 3.85 KB
/
parser.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <utility>
#include <iostream>
#include <cmath>
#include "utils.h"
struct AstNode {
string val;
AstNode* left{};
AstNode* right{};
static AstNode* newNode(string val){
auto node = new AstNode();
node->val = move(val);
node->left = nullptr;
node->right = nullptr;
return node;
}
};
class Parser {
string assignment_var;
vector<Token> tmp_expr;
bool assignment_chain = false;
bool comment_chain = false;
static AstNode* constructTree(const vector<string> &expression){
stack<AstNode *> st;
AstNode *t, *t1, *t2;
bool noConsider = false;
// Traverse through every string of
// input vector
for (int j=0; j < int(expression.size()) ; j++){
if(noConsider){
noConsider = false;
continue;
}
string i = expression[j];
if(i == "-"){
st.push(AstNode::newNode(i + expression[j+1]));
noConsider = true;
}
// If operand, simply push into stack
if (!Utils::isOperator(i)){
t = AstNode::newNode(i);
st.push(t);
}
else {
t = AstNode::newNode(i);
// Pop two top nodes
t1 = st.top(); // Store top
st.pop(); // Remove top
t2 = st.top();
st.pop();
// make them children
t->right = t1;
t->left = t2;
// Add this subexpression to stack
st.push(t);
}
}
// only element will be root of expression
// tree
t = st.top();
st.pop();
return t;
}
static int evalAST(AstNode* root){
// empty tree
if (!root)
return 0;
// leaf node i.e, an integer
if (!root->left && !root->right)
return Utils::toInt(root->val);
// Evaluate left subtree
int l_val = evalAST(root->left);
// Evaluate right subtree
int r_val = evalAST(root->right);
// Check which operator to apply
if (root->val=="+")
return l_val+r_val;
if (root->val=="-")
return l_val-r_val;
if (root->val=="*")
return l_val*r_val;
if(root->val=="^")
return (int) pow(l_val, r_val);
return l_val/r_val;
}
public:
void parse(vector<Token> tokens, map<string, string> &variables) {
for (int i = 0; i < int(tokens.size()); i++) {
auto tok = tokens[i];
if(comment_chain){
if(tok.type == NEWLINE){
comment_chain = false; continue;
} else continue;
}
// print handling
if (tok.type == IDENTIFIER && tokens[i + 1].type == NEWLINE) {
cout << variables[tok.val];
}
// assignment handling
if (tok.type == ASSIGNMENT && !assignment_chain) {
assignment_chain = true;
assignment_var = tokens[i - 1].val;
} else if (assignment_chain && tok.type == NEWLINE) {
assignment_chain = false;
vector<string> postfix = Utils::infixToPostfix(tmp_expr);
//for(const string& str: postfix) cout << str << ' ';
auto root = constructTree(postfix);
int answer = evalAST(root);
variables[assignment_var] = to_string(answer);
tmp_expr.clear();
assignment_var = "";
} else if (assignment_chain) {
tmp_expr.emplace_back(tok);
} else if (tok.type == HASHTAG && tokens[i - 1].type == NEWLINE) comment_chain = true;
}
}
};