LogiXpr
Loading...
Searching...
No Matches
parser.cpp
Go to the documentation of this file.
1
6#include "../include/parser.h"
7
8std::vector<std::string> tokenize(std::string expression)
9{
10 std::vector<std::string> tokens;
11 for (int i = 0; i < expression.length(); i++)
12 {
13 if (i + 1 < expression.length() && expression.substr(i, 2) == IMPLIES)
14 {
15 tokens.push_back(IMPLIES);
16 i++;
17 }
18 else if (i + 2 < expression.length() && expression.substr(i, 3) == IFF)
19 {
20 tokens.push_back(IFF);
21 i += 2;
22 }
23 else if (expression[i] != ' ')
24 {
25 tokens.push_back(std::string(1, expression[i]));
26 }
27 }
28 return tokens;
29}
30
31bool parse(std::string expression, std::shared_ptr<Expression> &root)
32{
33 // implement the shunting yard algorithm to convert to abstract syntax tree
34
35 std::stack<std::shared_ptr<Expression>> outputStack; // output queue
36 std::stack<std::string> operatorStack; // operator stack
37
38 std::vector<std::string> tokens = tokenize(expression);
39
40 for (auto token : tokens)
41 {
42 if (token.length() == 1 && islower(token[0]) || token == TRUE ||
43 token == FALSE)
44 {
45 // This is a leaf node. It is either a variable or a constant (True or
46 // False)
47
48 std::shared_ptr<Expression> leaf(new Expression(token));
49 outputStack.push(leaf);
50
51 // special case - NOT
52 if (!operatorStack.empty() && operatorStack.top() == NOT)
53 {
54 while (!operatorStack.empty() && operatorStack.top() == NOT)
55 {
56 std::string operatorStr = operatorStack.top();
57 operatorStack.pop();
58
59 std::shared_ptr<Expression> operand = outputStack.top();
60 outputStack.pop();
61
62 std::shared_ptr<Expression> operatorPtr(new Expression(operatorStr));
63
64 operatorPtr->setLeft(operand, operatorPtr);
65 outputStack.push(operatorPtr);
66 }
67 continue;
68 }
69 }
70 else if (token == NOT)
71 {
72 // Operator
73 // special case - NOT is unary
74 operatorStack.push(token);
75 }
76 else if (token == AND || token == OR || token == XOR || token == IFF ||
77 token == IMPLIES)
78 {
79 while (!operatorStack.empty() && operatorStack.top() != OPEN &&
80 precedence.at(operatorStack.top()) >= precedence.at(token))
81 {
82 // This is where it differs from the original algorithm
83 // Every time we pop an operator from the stack, we need to pop two
84 // operands from the output stack and create a new expression with the
85 // operator and the operands as children
86 std::string operatorStr = operatorStack.top();
87 operatorStack.pop();
88
89 std::shared_ptr<Expression> operatorPtr(new Expression(operatorStr));
90
91 if (outputStack.size() < 2)
92 return false;
93 std::shared_ptr<Expression> right = outputStack.top();
94 outputStack.pop();
95
96 std::shared_ptr<Expression> left = outputStack.top();
97 outputStack.pop();
98
99 operatorPtr->setLeft(left, operatorPtr);
100 operatorPtr->setRight(right, operatorPtr);
101
102 outputStack.push(operatorPtr);
103 }
104 operatorStack.push(token);
105 }
106 else if (token == OPEN)
107 operatorStack.push(token);
108 else if (token == CLOSE)
109 {
110 while (!operatorStack.empty() && operatorStack.top() != OPEN)
111 {
112 // Same as line 47
113 std::string operatorStr = operatorStack.top();
114 operatorStack.pop();
115
116 std::shared_ptr<Expression> operatorPtr(new Expression(operatorStr));
117
118 if (outputStack.size() < 1)
119 return false;
120 std::shared_ptr<Expression> right = outputStack.top();
121 outputStack.pop();
122 if (operatorStr == NOT)
123 {
124 operatorPtr->setLeft(right, operatorPtr);
125 outputStack.push(operatorPtr);
126 continue;
127 }
128
129 if (outputStack.size() < 1)
130 return false;
131 std::shared_ptr<Expression> left = outputStack.top();
132 outputStack.pop();
133
134 operatorPtr->setLeft(left, operatorPtr);
135 operatorPtr->setRight(right, operatorPtr);
136
137 outputStack.push(operatorPtr);
138 }
139 operatorStack.pop();
140
141 // special case - NOT
142 if (!operatorStack.empty() && operatorStack.top() == NOT)
143 {
144 while (!operatorStack.empty() && operatorStack.top() == NOT)
145 {
146 std::string operatorStr = operatorStack.top();
147 operatorStack.pop();
148
149 if (outputStack.size() < 1)
150 return false;
151
152 std::shared_ptr<Expression> operand = outputStack.top();
153 outputStack.pop();
154
155 std::shared_ptr<Expression> operatorPtr(new Expression(operatorStr));
156
157 operatorPtr->setLeft(operand, operatorPtr);
158 outputStack.push(operatorPtr);
159 }
160 }
161 }
162 }
163 while (!operatorStack.empty())
164 {
165 std::string operatorStr = operatorStack.top();
166 operatorStack.pop();
167
168 std::shared_ptr<Expression> operatorPtr(new Expression(operatorStr));
169
170 if (outputStack.size() < 1)
171 return false;
172 std::shared_ptr<Expression> right = outputStack.top();
173 outputStack.pop();
174 if (operatorStr == NOT)
175 {
176 operatorPtr->setLeft(right, operatorPtr);
177 outputStack.push(operatorPtr);
178 continue;
179 }
180
181 if (outputStack.size() < 1)
182 return false;
183 std::shared_ptr<Expression> left = outputStack.top();
184 outputStack.pop();
185
186 operatorPtr->setLeft(left, operatorPtr);
187 operatorPtr->setRight(right, operatorPtr);
188
189 outputStack.push(operatorPtr);
190 }
191
192 // assuming the expression is valid, there should be only one element in the
193 // output stack
194 if (outputStack.size() != 1)
195 return false;
196 root = outputStack.top();
197 return true;
198}
Abstract syntax tree for logic expressions.
Definition expression.h:42
bool parse(std::string expression, std::shared_ptr< Expression > &root)
Parse the expression and convert it to an abstract syntax tree.
Definition parser.cpp:31
std::vector< std::string > tokenize(std::string expression)
Tokenize the expression.
Definition parser.cpp:8
#define CLOSE
Definition expression.h:28
#define OPEN
Definition expression.h:27
#define IMPLIES
Definition expression.h:25
#define IFF
Definition expression.h:26
#define OR
Definition expression.h:22
#define XOR
Definition expression.h:24
#define TRUE
Definition expression.h:29
#define FALSE
Definition expression.h:30
#define AND
Definition expression.h:21
#define NOT
Definition expression.h:23