2024-01-05 12:04
BullseyeCoverage 9.6.4
expr/ Parser.cpp
1 // Expression evaluator parser implementation
2 #include <cassert>
3 #include "Parser.h"
4
5 void Parser::unitTest()
6 {
7 assert(Parser("1+2*3").expression() == 7);
8 assert(Parser("9/4").expression() == 2);
9 assert(Parser("5%4").expression() == 1);
10 assert(Parser("-(1 || 0)").expression() == -1);
11 assert(Parser("7-6").expression() == 1);
12 assert(Parser("8<<2").expression() == 32);
13 assert(Parser("32>>2").expression() == 8);
14 assert(Parser("8<9").expression() == 1);
15 assert(Parser("1<1").expression() == 0);
16 assert(Parser("1<=1").expression() == 1);
17 assert(Parser("1<=0").expression() == 0);
18 assert(Parser("1>=1").expression() == 1);
19 assert(Parser("0>=1").expression() == 0);
20 assert(Parser("1>1").expression() == 0);
21 assert(Parser("1>0").expression() == 1);
22 try {
23 Parser("1/0").expression();
24 assert(false);
25 }
26 catch (const char*) {
27 }
28 }
29
30 Parser::Parser(const char* string)
31 : m_lexer(string)
32 {
33 }
34
35 int64_t Parser::primary_expression()
36 {
37 int64_t n;
38 switch (m_token.kind) {
39 case Token::Kind::minus:
40 m_lexer.read(m_token);
41 n = -primary_expression();
42 break;
43 case Token::Kind::number:
44 n = m_token.value;
45 m_lexer.read(m_token);
46 break;
47 case Token::Kind::parenLeft:
48 m_lexer.read(m_token);
49 n = logical_or_expression();
50 m_lexer.read(m_token);
51 if (m_token.kind != Token::Kind::parenRight) {
52 throw "expected ')'";
53 }
54 m_lexer.read(m_token);
55 break;
56 default:
57 throw "syntax error";
58 }
59 return n;
60 }
61
62 int64_t Parser::multiplicative_expression()
63 {
64 int64_t n = primary_expression();
65 for (;;) {
66 if (m_token.kind == Token::Kind::multiply) {
67 m_lexer.read(m_token);
68 n = n * primary_expression();
69 } else if (m_token.kind == Token::Kind::divide) {
70 m_lexer.read(m_token);
71 const int64_t n2 = primary_expression();;
72 if (n2 == 0) {
73 throw "divide by zero";
74 }
75 n = n / n2;
76 } else if (m_token.kind == Token::Kind::modulus) {
77 m_lexer.read(m_token);
78 const int64_t n2 = primary_expression();;
79 if (n2 == 0) {
80 throw "divide by zero";
81 }
82 n = n % n2;
83 } else {
84 break;
85 }
86 }
87 return n;
88 }
89
90 int64_t Parser::additive_expression()
91 {
92 int64_t n = multiplicative_expression();
93 for (;;) {
94 if (m_token.kind == Token::Kind::plus) {
95 m_lexer.read(m_token);
96 n = n + multiplicative_expression();
97 } else if (m_token.kind == Token::Kind::minus) {
98 m_lexer.read(m_token);
99 n = n - multiplicative_expression();
100 } else {
101 break;
102 }
103 }
104 return n;
105 }
106
107 int64_t Parser::shift_expression()
108 {
109 int64_t n = additive_expression();
110 for (;;) {
111 if (m_token.kind == Token::Kind::shiftLeft) {
112 m_lexer.read(m_token);
113 n = n << additive_expression();
114 } else if (m_token.kind == Token::Kind::shiftRight) {
115 m_lexer.read(m_token);
116 n = n >> additive_expression();
117 } else {
118 break;
119 }
120 }
121 return n;
122 }
123
124 int64_t Parser::relational_expression()
125 {
126 int64_t n = shift_expression();
127 for (;;) {
128 if (m_token.kind == Token::Kind::lessThan) {
129 m_lexer.read(m_token);
130 n = n < shift_expression();
131 } else if (m_token.kind == Token::Kind::lessThanEq) {
132 m_lexer.read(m_token);
133 n = n <= shift_expression();
134 } else if (m_token.kind == Token::Kind::greaterThan) {
135 m_lexer.read(m_token);
136 n = n > shift_expression();
137 } else if (m_token.kind == Token::Kind::greaterThanEq) {
138 m_lexer.read(m_token);
139 n = n >= shift_expression();
140 } else {
141 break;
142 }
143 }
144 return n;
145 }
146
147 int64_t Parser::equality_expression()
148 {
149 int64_t n = relational_expression();
150 for (;;) {
151 if (m_token.kind == Token::Kind::equal) {
152 m_lexer.read(m_token);
153 n = n == relational_expression();
154 } else if (m_token.kind == Token::Kind::notEqual) {
155 m_lexer.read(m_token);
156 n = n != relational_expression();
157 } else {
158 break;
159 }
160 }
161 return n;
162 }
163
164 int64_t Parser::and_expression()
165 {
166 int64_t n = equality_expression();
167 while (m_token.kind == Token::Kind::bitwiseAnd) {
168 m_lexer.read(m_token);
169 n = n & equality_expression();
170 }
171 return n;
172 }
173
174 int64_t Parser::exclusive_or_expression()
175 {
176 int64_t n = and_expression();
177 while (m_token.kind == Token::Kind::bitwiseOr) {
178 m_lexer.read(m_token);
179 n = n | and_expression();
180 }
181 return n;
182 }
183
184 int64_t Parser::inclusive_or_expression()
185 {
186 int64_t n = exclusive_or_expression();
187 while (m_token.kind == Token::Kind::logicalAnd) {
188 m_lexer.read(m_token);
189 n = n ^ exclusive_or_expression();
190 }
191 return n;
192 }
193
194 int64_t Parser::logical_and_expression()
195 {
196 int64_t n = inclusive_or_expression();
197 while (m_token.kind == Token::Kind::logicalAnd) {
198 m_lexer.read(m_token);
199a n =
199b n &&
199c inclusive_or_expression();
200 }
201 return n;
202 }
203
204 int64_t Parser::logical_or_expression()
205 {
206 int64_t n = logical_and_expression();
207 while (m_token.kind == Token::Kind::logicalOr) {
208 m_lexer.read(m_token);
209a n =
209b n ||
209c logical_and_expression();
210 }
211 return n;
212 }
213
214 int64_t Parser::expression()
215 {
216 m_lexer.read(m_token);
217 const int64_t n = logical_or_expression();
218 if (m_token.kind != Token::Kind::endOfInput) {
219 throw "syntax error";
220 }
221 return n;
222 }