blob: ec904787dd77dfedf90ad8b46a00235ce1337e11 [file] [log] [blame]
Michal Krol3bb446b2009-06-26 10:59:25 +02001/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28#include <stdlib.h>
Michal Krol7a95a3c2009-09-24 10:56:46 +020029#include <string.h>
Michal Krol3bb446b2009-06-26 10:59:25 +020030#include "sl_pp_expression.h"
Michal Krol1ed1dc82009-09-23 09:40:24 +020031#include "sl_pp_public.h"
Michal Krol3bb446b2009-06-26 10:59:25 +020032
33
34struct parse_context {
35 struct sl_pp_context *context;
36 const struct sl_pp_token_info *input;
37};
38
39static int
40_parse_or(struct parse_context *ctx,
41 int *result);
42
43static int
44_parse_primary(struct parse_context *ctx,
45 int *result)
46{
Michal Krol0481e852009-09-22 12:51:08 +020047 if (ctx->input->token == SL_PP_UINT) {
48 *result = atoi(sl_pp_context_cstr(ctx->context, ctx->input->data._uint));
Michal Krol3bb446b2009-06-26 10:59:25 +020049 ctx->input++;
50 } else {
51 if (ctx->input->token != SL_PP_LPAREN) {
Michal Krol0ddf41d2009-09-17 11:51:35 +020052 strcpy(ctx->context->error_msg, "expected `('");
Michal Krol3bb446b2009-06-26 10:59:25 +020053 return -1;
54 }
55 ctx->input++;
56 if (_parse_or(ctx, result)) {
57 return -1;
58 }
59 if (ctx->input->token != SL_PP_RPAREN) {
Michal Krol0ddf41d2009-09-17 11:51:35 +020060 strcpy(ctx->context->error_msg, "expected `)'");
Michal Krol3bb446b2009-06-26 10:59:25 +020061 return -1;
62 }
63 ctx->input++;
64 }
65 return 0;
66}
67
68static int
69_parse_unary(struct parse_context *ctx,
70 int *result)
71{
72 if (!_parse_primary(ctx, result)) {
73 return 0;
74 }
75
76 switch (ctx->input->token) {
77 case SL_PP_PLUS:
78 ctx->input++;
79 if (_parse_unary(ctx, result)) {
80 return -1;
81 }
82 *result = +*result;
83 break;
84
85 case SL_PP_MINUS:
86 ctx->input++;
87 if (_parse_unary(ctx, result)) {
88 return -1;
89 }
90 *result = -*result;
91 break;
92
93 case SL_PP_NOT:
94 ctx->input++;
95 if (_parse_unary(ctx, result)) {
96 return -1;
97 }
98 *result = !*result;
99 break;
100
101 case SL_PP_BITNOT:
102 ctx->input++;
103 if (_parse_unary(ctx, result)) {
104 return -1;
105 }
106 *result = ~*result;
107 break;
108
109 default:
110 return -1;
111 }
112
113 return 0;
114}
115
116static int
117_parse_multiplicative(struct parse_context *ctx,
118 int *result)
119{
120 if (_parse_unary(ctx, result)) {
121 return -1;
122 }
123 for (;;) {
124 int right;
125
126 switch (ctx->input->token) {
127 case SL_PP_STAR:
128 ctx->input++;
129 if (_parse_unary(ctx, &right)) {
130 return -1;
131 }
132 *result = *result * right;
133 break;
134
135 case SL_PP_SLASH:
136 ctx->input++;
137 if (_parse_unary(ctx, &right)) {
138 return -1;
139 }
140 *result = *result / right;
141 break;
142
143 case SL_PP_MODULO:
144 ctx->input++;
145 if (_parse_unary(ctx, &right)) {
146 return -1;
147 }
148 *result = *result % right;
149 break;
150
151 default:
152 return 0;
153 }
154 }
155}
156
157static int
158_parse_additive(struct parse_context *ctx,
159 int *result)
160{
161 if (_parse_multiplicative(ctx, result)) {
162 return -1;
163 }
164 for (;;) {
165 int right;
166
167 switch (ctx->input->token) {
168 case SL_PP_PLUS:
169 ctx->input++;
170 if (_parse_multiplicative(ctx, &right)) {
171 return -1;
172 }
173 *result = *result + right;
174 break;
175
176 case SL_PP_MINUS:
177 ctx->input++;
178 if (_parse_multiplicative(ctx, &right)) {
179 return -1;
180 }
181 *result = *result - right;
182 break;
183
184 default:
185 return 0;
186 }
187 }
188}
189
190static int
191_parse_shift(struct parse_context *ctx,
192 int *result)
193{
194 if (_parse_additive(ctx, result)) {
195 return -1;
196 }
197 for (;;) {
198 int right;
199
200 switch (ctx->input->token) {
201 case SL_PP_LSHIFT:
202 ctx->input++;
203 if (_parse_additive(ctx, &right)) {
204 return -1;
205 }
206 *result = *result << right;
207 break;
208
209 case SL_PP_RSHIFT:
210 ctx->input++;
211 if (_parse_additive(ctx, &right)) {
212 return -1;
213 }
214 *result = *result >> right;
215 break;
216
217 default:
218 return 0;
219 }
220 }
221}
222
223static int
224_parse_relational(struct parse_context *ctx,
225 int *result)
226{
227 if (_parse_shift(ctx, result)) {
228 return -1;
229 }
230 for (;;) {
231 int right;
232
233 switch (ctx->input->token) {
234 case SL_PP_LESSEQUAL:
235 ctx->input++;
236 if (_parse_shift(ctx, &right)) {
237 return -1;
238 }
239 *result = *result <= right;
240 break;
241
242 case SL_PP_GREATEREQUAL:
243 ctx->input++;
244 if (_parse_shift(ctx, &right)) {
245 return -1;
246 }
247 *result = *result >= right;
248 break;
249
250 case SL_PP_LESS:
251 ctx->input++;
252 if (_parse_shift(ctx, &right)) {
253 return -1;
254 }
255 *result = *result < right;
256 break;
257
258 case SL_PP_GREATER:
259 ctx->input++;
260 if (_parse_shift(ctx, &right)) {
261 return -1;
262 }
263 *result = *result > right;
264 break;
265
266 default:
267 return 0;
268 }
269 }
270}
271
272static int
273_parse_equality(struct parse_context *ctx,
274 int *result)
275{
276 if (_parse_relational(ctx, result)) {
277 return -1;
278 }
279 for (;;) {
280 int right;
281
282 switch (ctx->input->token) {
283 case SL_PP_EQUAL:
284 ctx->input++;
285 if (_parse_relational(ctx, &right)) {
286 return -1;
287 }
288 *result = *result == right;
289 break;
290
291 case SL_PP_NOTEQUAL:
292 ctx->input++;
293 if (_parse_relational(ctx, &right)) {
294 return -1;
295 }
296 *result = *result != right;
297 break;
298
299 default:
300 return 0;
301 }
302 }
303}
304
305static int
306_parse_bitand(struct parse_context *ctx,
307 int *result)
308{
309 if (_parse_equality(ctx, result)) {
310 return -1;
311 }
312 while (ctx->input->token == SL_PP_BITAND) {
313 int right;
314
315 ctx->input++;
316 if (_parse_equality(ctx, &right)) {
317 return -1;
318 }
319 *result = *result & right;
320 }
321 return 0;
322}
323
324static int
325_parse_xor(struct parse_context *ctx,
326 int *result)
327{
328 if (_parse_bitand(ctx, result)) {
329 return -1;
330 }
331 while (ctx->input->token == SL_PP_XOR) {
332 int right;
333
334 ctx->input++;
335 if (_parse_bitand(ctx, &right)) {
336 return -1;
337 }
338 *result = *result ^ right;
339 }
340 return 0;
341}
342
343static int
344_parse_bitor(struct parse_context *ctx,
345 int *result)
346{
347 if (_parse_xor(ctx, result)) {
348 return -1;
349 }
350 while (ctx->input->token == SL_PP_BITOR) {
351 int right;
352
353 ctx->input++;
354 if (_parse_xor(ctx, &right)) {
355 return -1;
356 }
357 *result = *result | right;
358 }
359 return 0;
360}
361
362static int
363_parse_and(struct parse_context *ctx,
364 int *result)
365{
366 if (_parse_bitor(ctx, result)) {
367 return -1;
368 }
369 while (ctx->input->token == SL_PP_AND) {
370 int right;
371
372 ctx->input++;
373 if (_parse_bitor(ctx, &right)) {
374 return -1;
375 }
376 *result = *result && right;
377 }
378 return 0;
379}
380
381static int
382_parse_or(struct parse_context *ctx,
383 int *result)
384{
385 if (_parse_and(ctx, result)) {
386 return -1;
387 }
388 while (ctx->input->token == SL_PP_OR) {
389 int right;
390
391 ctx->input++;
392 if (_parse_and(ctx, &right)) {
393 return -1;
394 }
395 *result = *result || right;
396 }
397 return 0;
398}
399
400int
401sl_pp_execute_expression(struct sl_pp_context *context,
402 const struct sl_pp_token_info *input,
403 int *result)
404{
405 struct parse_context ctx;
406
407 ctx.context = context;
408 ctx.input = input;
409
410 return _parse_or(&ctx, result);
411}