Add GNU bison input file jamexp.y and unit test program for generated jamexp.c
[urjtag.git] / urjtag / src / stapl / jamexp.y
blob263362713c5cb9a97317a8646f43cda3515356c8
1 // SPDX-FileCopyrightText: 1997 Altera Corporation
2 // SPDX-FileCopyrightText: 2022 Peter Poeschl <pp+ujt2208@nest-ai.de>
3 //
4 // SPDX-License-Identifier: GPL-2.0-or-later
6 %code top {
7 #include <stdint.h>
8 #include <stdio.h>
9 #include <math.h>
10 #include "jamexprt.h"
11 #include "jamdefs.h"
12 #include "jamexp.h"
13 #include "jamsym.h"
14 #include "jamheap.h"
15 #include "jamarray.h"
16 #include "jamutil.h"
17 #include "jamytab.h"
20 %code {
21 /* ------------- LEXER DEFINITIONS -----------------------------------------*/
22 /****************************************************************************/
23 /* */
24 /* Operation of GET_FIRST_CH, GET_NEXT_CH, UNGET_CH, and DELETE_CH: */
25 /* */
26 /* Call GET_FIRST_CH to read a character from mdl_lexer_fp and put it into */
27 /* urj_jam_ch and urj_jam_token_buffer. */
28 /* */
29 /* urj_jam_ch = first char */
30 /* urj_jam_token_buffer[0] = first char */
31 /* urj_jam_token_buffer[1] = '\0'; */
32 /* urj_jam_token_buffer[2] = ? */
33 /* urj_jam_token_buffer[3] = ? */
34 /* */
35 /* Call GET_NEXT_CH to read a character from jam_lexer_fp, put it in */
36 /* urj_jam_ch, and append it to urj_jam_token_buffer. */
37 /* */
38 /* urj_jam_ch = second char */
39 /* urj_jam_token_buffer[0] = first char */
40 /* urj_jam_token_buffer[1] = second char */
41 /* urj_jam_token_buffer[2] = '\0'; */
42 /* urj_jam_token_buffer[3] = ? */
43 /* */
44 /* Call UNGET_CH remove the last character from the buffer but leave it in */
45 /* urj_jam_ch and set a flag. (The next call to GET_FIRST_CH will use */
46 /* urj_jam_ch as the first char of the token and clear the flag.) */
47 /* */
48 /* urj_jam_ch = second char */
49 /* urj_jam_token_buffer[0] = first char */
50 /* urj_jam_token_buffer[1] = '\0'; */
51 /* urj_jam_token_buffer[2] = ? */
52 /* urj_jam_token_buffer[3] = ? */
53 /* */
54 /* Call DELETE_CH to remove the last character from the buffer. Use this */
55 /* macro to discard the quotes surrounding a string, for example. Unlike */
56 /* UNGET_CH, the deleted character will not be reused. */
57 /* */
58 /****************************************************************************/
60 #define MAX_BUFFER_LENGTH 1024
61 #define END_OF_STRING -1
65 /****************************************************************************/
66 /* */
67 /* Operation of BEGIN_MACHINE, END_MACHINE, and ACCEPT: */
68 /* */
69 /* BEGIN_MACHINE and END_MACHINE should be at the beginning the end of an */
70 /* integer function. Inside the function, define states of the machine */
71 /* with normal C labels, and jump to states with normal C goto statements. */
72 /* Use ACCEPT(token) to return an integer value token to the calling */
73 /* routine. */
74 /* */
75 /* int foo (void) */
76 /* { */
77 /* BEGIN_MACHINE; */
78 /* */
79 /* start: */
80 /* if (whatever) goto next; */
81 /* else goto start; */
82 /* */
83 /* next: */
84 /* if (done) ACCEPT (a_token_id); */
85 /* else goto start; */
86 /* */
87 /* END_MACHINE; */
88 /* } */
89 /* */
90 /* Be sure that there is an ACCEPT() or goto at the end of every state. */
91 /* Otherwise, control will "flow" from one state to the next illegally. */
92 /* */
93 /****************************************************************************/
95 #define BEGIN_MACHINE {int ret
97 #define ACCEPT(token) {ret = (token); goto accept;}
99 #define END_MACHINE accept: urj_jam_token = ret; \
101 // need defines, single-chars cannot be %token
102 #define GREATER_TOK '>'
103 #define LESS_TOK '<'
105 struct
107 char *string;
108 int length;
109 int token;
110 } static const jam_keyword_table[] =
112 {"&&", 2, AND_TOK},
113 {"||", 2, OR_TOK},
114 {"==", 2, EQUALITY_TOK},
115 {"!=", 2, INEQUALITY_TOK},
116 {">", 2, GREATER_TOK},
117 {"<", 2, LESS_TOK},
118 {">=", 2, GREATER_EQ_TOK},
119 {"<=", 2, LESS_OR_EQ_TOK},
120 {"<<", 2, LEFT_SHIFT_TOK},
121 {">>", 2, RIGHT_SHIFT_TOK},
122 {"..", 2, DOT_DOT_TOK},
123 {"OR", 2, OR_TOK},
124 {"AND", 3, AND_TOK},
125 {"ABS", 3, ABS_TOK},
126 {"INT", 3, INT_TOK},
127 {"LOG2", 4, LOG2_TOK},
128 {"SQRT", 4, SQRT_TOK},
129 {"CEIL", 4, CIEL_TOK},
130 {"FLOOR", 5, FLOOR_TOK}
133 char urj_jam_ch = '\0'; /* next character from input file */
134 int urj_jam_strptr = 0;
135 int urj_jam_token = 0;
136 char urj_jam_token_buffer[MAX_BUFFER_LENGTH];
137 int urj_jam_token_buffer_index;
138 char urj_jam_parse_string[MAX_BUFFER_LENGTH];
139 int32_t urj_jam_parse_value = 0;
140 int urj_jam_expression_type = 0;
141 JAMS_SYMBOL_RECORD *urj_jam_array_symbol_rec = NULL;
143 #define YYMAXDEPTH 300 /* This fixes a stack depth problem on */
144 /* all platforms. */
146 #define YYMAXTLIST 25 /* Max valid next tokens for any state. */
147 /* If there are more, error reporting */
148 /* will be incomplete. */
152 %code requires {
153 enum OPERATOR_TYPE
155 ADD = 0,
156 SUB,
157 UMINUS,
158 MULT,
159 DIV,
160 MOD,
161 NOT,
162 AND,
164 BITWISE_NOT,
165 BITWISE_AND,
166 BITWISE_OR,
167 BITWISE_XOR,
168 LEFT_SHIFT,
169 RIGHT_SHIFT,
170 DOT_DOT,
171 EQUALITY,
172 INEQUALITY,
173 GREATER_THAN,
174 LESS_THAN,
175 GREATER_OR_EQUAL,
176 LESS_OR_EQUAL,
177 ABS,
178 INT,
179 LOG2,
180 SQRT,
181 CIEL,
182 FLOOR,
183 ARRAY,
184 POUND,
185 DOLLAR,
186 ARRAY_RANGE,
187 ARRAY_ALL
190 typedef enum OPERATOR_TYPE OPERATOR_TYPE;
192 typedef struct EXP_STACK
194 OPERATOR_TYPE child_otype;
195 JAME_EXPRESSION_TYPE type;
196 int32_t val;
197 int32_t loper; /* left and right operands for DIV */
198 int32_t roper; /* we save it for CEIL/FLOOR's use */
199 } EXPN_STACK;
201 #define URJ_JAM_YYSTYPE EXPN_STACK /* must be a #define for yacc */
204 %code {
205 YYSTYPE urj_jam_null_expression = { 0, 0, 0, 0, 0 };
207 JAM_RETURN_TYPE urj_jam_return_code = JAMC_SUCCESS;
209 JAME_EXPRESSION_TYPE urj_jam_expr_type = JAM_ILLEGAL_EXPR_TYPE;
211 #define NULL_EXP urj_jam_null_expression /* .. for 1 operand operators */
213 #define CALC(operator, lval, rval) urj_jam_exp_eval((operator), (lval), (rval))
216 %code provides {
217 /* --- FUNCTION PROTOTYPES -------------------------------------------- */
219 int urj_jam_yyparse (void);
220 int urj_jam_yylex (void);
223 %code {
224 #ifdef DELME_OLD_TOKEN_VALUES
225 #define AND_TOK 257
226 #define OR_TOK 258
227 #define EQUALITY_TOK 259
228 #define INEQUALITY_TOK 260
229 #define GREATER_TOK 261
230 #define LESS_TOK 262
231 #define GREATER_EQ_TOK 263
232 #define LESS_OR_EQ_TOK 264
233 #define LEFT_SHIFT_TOK 265
234 #define RIGHT_SHIFT_TOK 266
235 #define DOT_DOT_TOK 267
236 #define ABS_TOK 268
237 #define INT_TOK 269
238 #define LOG2_TOK 270
239 #define SQRT_TOK 271
240 #define CIEL_TOK 272
241 #define FLOOR_TOK 273
242 #define VALUE_TOK 274
243 #define IDENTIFIER_TOK 275
244 #define ARRAY_TOK 276
245 #define ERROR_TOK 277
246 #define UNARY_MINUS 278
247 #define UNARY_PLUS 279
248 #endif // DELME_OLD_TOKEN_VALUES
250 YYSTYPE urj_jam_yylval, urj_jam_yyval;
251 int32_t urj_jam_convert_bool_to_int (int32_t *data, int32_t msb, int32_t lsb);
252 EXPN_STACK urj_jam_exp_eval (OPERATOR_TYPE otype, EXPN_STACK op1, EXPN_STACK op2);
253 void urj_jam_exp_lexer (void);
254 bool urj_jam_constant_is_ok (const char *string);
255 bool urj_jam_binary_constant_is_ok (const char *string);
256 bool urj_jam_hex_constant_is_ok (const char *string);
257 int32_t urj_jam_atol_bin (char *string);
258 int32_t urj_jam_atol_hex (char *string);
259 int urj_jam_constant_value (char *string, int32_t *value);
260 void urj_jam_yyerror (char *msg);
261 int urj_jam_yylex (void);
262 int urj_jam_evaluate_expression (char *expression, int32_t *result,
263 JAME_EXPRESSION_TYPE *result_type);
264 int urj_jam_yyparse (void);
266 #define GET_FIRST_CH jam_get_first_ch()
267 #define GET_NEXT_CH jam_get_next_ch()
268 #define UNGET_CH jam_unget_ch()
269 #define CH jam_get_ch()
272 // Bison declarations
273 %language "C"
274 //always in current dir: %header "jamytab.h"
275 //fixed jamexp.h parallel to jamexp.c: %header
276 // ==> use --defines=$PATH_TO/jamytab.h
277 %define api.prefix {urj_jam_yy}
278 %define api.value.type {EXPN_STACK}
279 %start stapl_expr
281 %token AND_TOK "&&" // alias "AND"
282 %token OR_TOK "||" // alias "OR"
283 %token EQUALITY_TOK "=="
284 %token INEQUALITY_TOK "!="
285 // single-char cannot be %token
286 //%token GREATER_TOK '>'
287 //%token LESS_TOK '<'
288 %token GREATER_EQ_TOK ">="
289 %token LESS_OR_EQ_TOK "<="
290 %token LEFT_SHIFT_TOK "<<"
291 %token RIGHT_SHIFT_TOK ">>"
292 %token DOT_DOT_TOK ".."
293 %token ABS_TOK "ABS"
294 %token INT_TOK "INT"
295 %token LOG2_TOK "LOG2"
296 %token SQRT_TOK "SQRT"
297 %token CIEL_TOK "CEIL"
298 %token FLOOR_TOK "FLOOR"
299 %token VALUE_TOK "VALUE"
300 %token IDENTIFIER_TOK "IDENTIFIER"
301 %token ARRAY_TOK "ARRAY"
302 %token ERROR_TOK "ERROR"
303 %token UNARY_MINUS "UNARY_MINUS"
304 %token UNARY_PLUS "UNARY_PLUS"
306 %code {
307 static inline void jam_get_next_ch(void)
309 urj_jam_ch = urj_jam_parse_string[urj_jam_strptr++];
310 urj_jam_token_buffer [urj_jam_token_buffer_index++] = urj_jam_ch;
311 if (urj_jam_token_buffer_index >= MAX_BUFFER_LENGTH)
313 --urj_jam_token_buffer_index;
314 --urj_jam_strptr;
316 urj_jam_token_buffer [urj_jam_token_buffer_index] = '\0';
319 static inline void jam_get_first_ch(void)
321 urj_jam_token_buffer_index = 0;
322 jam_get_next_ch();
325 static inline void jam_unget_ch(void)
327 urj_jam_strptr--;
328 urj_jam_token_buffer[--urj_jam_token_buffer_index] = '\0';
331 static inline char jam_get_ch(void)
333 return urj_jam_ch;
337 * Used by INT() function to convert Boolean array data to integer. "msb"
338 * is the index of the most significant bit of the array, and "lsb" is the
339 * index of the least significant bit. Typically msb > lsb, otherwise the
340 * bit order will be reversed when converted into integer format.
342 int32_t
343 urj_jam_convert_bool_to_int (int32_t *data, int32_t msb, int32_t lsb)
345 int32_t i, increment = (msb > lsb) ? 1 : -1;
346 int32_t mask = 1L, result = 0L;
348 msb += increment;
349 for (i = lsb; i != msb; i += increment)
351 if (data[i >> 5] & (1L << (i & 0x1f)))
352 result |= mask;
353 mask <<= 1;
356 return result;
360 /************************************************************************/
361 /* */
363 YYSTYPE
364 urj_jam_exp_eval (OPERATOR_TYPE otype, YYSTYPE op1, YYSTYPE op2)
365 /* Evaluate op1 OTYPE op2. op1, op2 are operands, OTYPE is operator */
366 /* */
367 /* Some sneaky things are done to implement CEIL and FLOOR. */
368 /* */
369 /* We do CEIL of LOG2 by default, and FLOOR of a DIVIDE by default. */
370 /* Since we are lazy and we don't want to generate a parse tree, */
371 /* we use the parser's reduce actions to tell us when to perform */
372 /* an evaluation. But when CEIL and FLOOR are reduced, we know */
373 /* nothing about the expression tree beneath it (it's been reduced!) */
374 /* */
375 /* We keep this information around so we can calculate the CEIL or */
376 /* FLOOR. We save value of the operand(s) or a divide in loper and */
377 /* roper, then when CEIL/FLOOR get reduced, we just look at their */
378 /* values. */
379 /* */
381 YYSTYPE rtn;
382 int32_t tmp_val;
383 JAMS_SYMBOL_RECORD *symbol_rec;
384 JAMS_HEAP_RECORD *heap_rec;
386 rtn.child_otype = 0;
387 rtn.type = JAM_ILLEGAL_EXPR_TYPE;
388 rtn.val = 0;
389 rtn.loper = 0;
390 rtn.roper = 0;
392 switch (otype)
394 case UMINUS:
395 if ((op1.type == JAM_INTEGER_EXPR)
396 || (op1.type == JAM_INT_OR_BOOL_EXPR))
398 rtn.val = -1 * op1.val;
399 rtn.type = JAM_INTEGER_EXPR;
401 else
402 urj_jam_return_code = JAMC_TYPE_MISMATCH;
403 break;
405 case ADD:
406 if (((op1.type == JAM_INTEGER_EXPR)
407 || (op1.type == JAM_INT_OR_BOOL_EXPR))
408 && ((op2.type == JAM_INTEGER_EXPR)
409 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
411 rtn.val = op1.val + op2.val;
412 rtn.type = JAM_INTEGER_EXPR;
414 /* check for overflow */
415 if (((op1.val > 0) && (op2.val > 0) && (rtn.val < 0)) ||
416 ((op1.val < 0) && (op2.val < 0) && (rtn.val > 0)))
418 urj_jam_return_code = JAMC_INTEGER_OVERFLOW;
421 else
422 urj_jam_return_code = JAMC_TYPE_MISMATCH;
423 break;
425 case SUB:
426 if (((op1.type == JAM_INTEGER_EXPR)
427 || (op1.type == JAM_INT_OR_BOOL_EXPR))
428 && ((op2.type == JAM_INTEGER_EXPR)
429 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
431 rtn.val = op1.val - op2.val;
432 rtn.type = JAM_INTEGER_EXPR;
434 /* check for overflow */
435 if (((op1.val > 0) && (op2.val < 0) && (rtn.val < 0)) ||
436 ((op1.val < 0) && (op2.val > 0) && (rtn.val > 0)))
438 urj_jam_return_code = JAMC_INTEGER_OVERFLOW;
441 else
442 urj_jam_return_code = JAMC_TYPE_MISMATCH;
443 break;
445 case MULT:
446 if (((op1.type == JAM_INTEGER_EXPR)
447 || (op1.type == JAM_INT_OR_BOOL_EXPR))
448 && ((op2.type == JAM_INTEGER_EXPR)
449 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
451 rtn.val = op1.val * op2.val;
452 rtn.type = JAM_INTEGER_EXPR;
454 /* check for overflow */
455 if ((op1.val != 0) && (op2.val != 0) &&
456 (((rtn.val / op1.val) != op2.val) ||
457 ((rtn.val / op2.val) != op1.val)))
459 urj_jam_return_code = JAMC_INTEGER_OVERFLOW;
462 else
463 urj_jam_return_code = JAMC_TYPE_MISMATCH;
464 break;
466 case DIV:
467 if (((op1.type == JAM_INTEGER_EXPR)
468 || (op1.type == JAM_INT_OR_BOOL_EXPR))
469 && ((op2.type == JAM_INTEGER_EXPR)
470 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
472 if (op2.val != 0)
474 rtn.val = op1.val / op2.val;
475 rtn.loper = op1.val;
476 rtn.roper = op2.val;
477 rtn.child_otype = DIV; /* Save info needed by CEIL */
478 rtn.type = JAM_INTEGER_EXPR;
480 else
482 urj_jam_return_code = JAMC_DIVIDE_BY_ZERO;
485 else
486 urj_jam_return_code = JAMC_TYPE_MISMATCH;
487 break;
489 case MOD:
490 if (((op1.type == JAM_INTEGER_EXPR)
491 || (op1.type == JAM_INT_OR_BOOL_EXPR))
492 && ((op2.type == JAM_INTEGER_EXPR)
493 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
495 rtn.val = op1.val % op2.val;
496 rtn.type = JAM_INTEGER_EXPR;
498 else
499 urj_jam_return_code = JAMC_TYPE_MISMATCH;
500 break;
502 case NOT:
503 if ((op1.type == JAM_BOOLEAN_EXPR)
504 || (op1.type == JAM_INT_OR_BOOL_EXPR))
506 rtn.val = (op1.val == 0) ? 1 : 0;
507 rtn.type = JAM_BOOLEAN_EXPR;
509 else
510 urj_jam_return_code = JAMC_TYPE_MISMATCH;
511 break;
513 case AND:
514 if (((op1.type == JAM_BOOLEAN_EXPR)
515 || (op1.type == JAM_INT_OR_BOOL_EXPR))
516 && ((op2.type == JAM_BOOLEAN_EXPR)
517 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
519 rtn.val = (op1.val && op2.val) ? 1 : 0;
520 rtn.type = JAM_BOOLEAN_EXPR;
522 else
523 urj_jam_return_code = JAMC_TYPE_MISMATCH;
524 break;
526 case OR:
527 if (((op1.type == JAM_BOOLEAN_EXPR)
528 || (op1.type == JAM_INT_OR_BOOL_EXPR))
529 && ((op2.type == JAM_BOOLEAN_EXPR)
530 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
532 rtn.val = (op1.val || op2.val) ? 1 : 0;
533 rtn.type = JAM_BOOLEAN_EXPR;
535 else
536 urj_jam_return_code = JAMC_TYPE_MISMATCH;
537 break;
539 case BITWISE_NOT:
540 if ((op1.type == JAM_INTEGER_EXPR)
541 || (op1.type == JAM_INT_OR_BOOL_EXPR))
543 rtn.val = ~(uint32_t) op1.val;
544 rtn.type = JAM_INTEGER_EXPR;
546 else
547 urj_jam_return_code = JAMC_TYPE_MISMATCH;
548 break;
550 case BITWISE_AND:
551 if (((op1.type == JAM_INTEGER_EXPR)
552 || (op1.type == JAM_INT_OR_BOOL_EXPR))
553 && ((op2.type == JAM_INTEGER_EXPR)
554 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
556 rtn.val = op1.val & op2.val;
557 rtn.type = JAM_INTEGER_EXPR;
559 else
560 urj_jam_return_code = JAMC_TYPE_MISMATCH;
561 break;
563 case BITWISE_OR:
564 if (((op1.type == JAM_INTEGER_EXPR)
565 || (op1.type == JAM_INT_OR_BOOL_EXPR))
566 && ((op2.type == JAM_INTEGER_EXPR)
567 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
569 rtn.val = op1.val | op2.val;
570 rtn.type = JAM_INTEGER_EXPR;
572 else
573 urj_jam_return_code = JAMC_TYPE_MISMATCH;
574 break;
576 case BITWISE_XOR:
577 if (((op1.type == JAM_INTEGER_EXPR)
578 || (op1.type == JAM_INT_OR_BOOL_EXPR))
579 && ((op2.type == JAM_INTEGER_EXPR)
580 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
582 rtn.val = op1.val ^ op2.val;
583 rtn.type = JAM_INTEGER_EXPR;
585 else
586 urj_jam_return_code = JAMC_TYPE_MISMATCH;
587 break;
589 case LEFT_SHIFT:
590 if (((op1.type == JAM_INTEGER_EXPR)
591 || (op1.type == JAM_INT_OR_BOOL_EXPR))
592 && ((op2.type == JAM_INTEGER_EXPR)
593 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
595 rtn.val = op1.val << op2.val;
596 rtn.type = JAM_INTEGER_EXPR;
598 else
599 urj_jam_return_code = JAMC_TYPE_MISMATCH;
600 break;
602 case RIGHT_SHIFT:
603 if (((op1.type == JAM_INTEGER_EXPR)
604 || (op1.type == JAM_INT_OR_BOOL_EXPR))
605 && ((op2.type == JAM_INTEGER_EXPR)
606 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
608 rtn.val = op1.val >> op2.val;
609 rtn.type = JAM_INTEGER_EXPR;
611 else
612 urj_jam_return_code = JAMC_TYPE_MISMATCH;
613 break;
615 case EQUALITY:
616 if (((op1.type == JAM_INTEGER_EXPR)
617 || (op1.type == JAM_INT_OR_BOOL_EXPR))
618 && ((op2.type == JAM_INTEGER_EXPR)
619 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
621 rtn.val = (op1.val == op2.val) ? 1 : 0;
622 rtn.type = JAM_BOOLEAN_EXPR;
624 else if (((op1.type == JAM_BOOLEAN_EXPR)
625 || (op1.type == JAM_INT_OR_BOOL_EXPR))
626 && ((op2.type == JAM_BOOLEAN_EXPR)
627 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
629 rtn.val = ((op1.val && op2.val) || ((!op1.val) && (!op2.val)))
630 ? 1 : 0;
631 rtn.type = JAM_BOOLEAN_EXPR;
633 else
634 urj_jam_return_code = JAMC_TYPE_MISMATCH;
635 break;
637 case INEQUALITY:
638 if (((op1.type == JAM_INTEGER_EXPR)
639 || (op1.type == JAM_INT_OR_BOOL_EXPR))
640 && ((op2.type == JAM_INTEGER_EXPR)
641 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
643 rtn.val = (op1.val == op2.val) ? 0 : 1;
644 rtn.type = JAM_BOOLEAN_EXPR;
646 else if (((op1.type == JAM_BOOLEAN_EXPR)
647 || (op1.type == JAM_INT_OR_BOOL_EXPR))
648 && ((op2.type == JAM_BOOLEAN_EXPR)
649 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
651 rtn.val = ((op1.val && op2.val) || ((!op1.val) && (!op2.val)))
652 ? 0 : 1;
653 rtn.type = JAM_BOOLEAN_EXPR;
655 else
656 urj_jam_return_code = JAMC_TYPE_MISMATCH;
657 break;
659 case GREATER_THAN:
660 if (((op1.type == JAM_INTEGER_EXPR)
661 || (op1.type == JAM_INT_OR_BOOL_EXPR))
662 && ((op2.type == JAM_INTEGER_EXPR)
663 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
665 rtn.val = (op1.val > op2.val) ? 1 : 0;
666 rtn.type = JAM_BOOLEAN_EXPR;
668 else
669 urj_jam_return_code = JAMC_TYPE_MISMATCH;
670 break;
672 case LESS_THAN:
673 if (((op1.type == JAM_INTEGER_EXPR)
674 || (op1.type == JAM_INT_OR_BOOL_EXPR))
675 && ((op2.type == JAM_INTEGER_EXPR)
676 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
678 rtn.val = (op1.val < op2.val) ? 1 : 0;
679 rtn.type = JAM_BOOLEAN_EXPR;
681 else
682 urj_jam_return_code = JAMC_TYPE_MISMATCH;
683 break;
685 case GREATER_OR_EQUAL:
686 if (((op1.type == JAM_INTEGER_EXPR)
687 || (op1.type == JAM_INT_OR_BOOL_EXPR))
688 && ((op2.type == JAM_INTEGER_EXPR)
689 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
691 rtn.val = (op1.val >= op2.val) ? 1 : 0;
692 rtn.type = JAM_BOOLEAN_EXPR;
694 else
695 urj_jam_return_code = JAMC_TYPE_MISMATCH;
696 break;
698 case LESS_OR_EQUAL:
699 if (((op1.type == JAM_INTEGER_EXPR)
700 || (op1.type == JAM_INT_OR_BOOL_EXPR))
701 && ((op2.type == JAM_INTEGER_EXPR)
702 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
704 rtn.val = (op1.val <= op2.val) ? 1 : 0;
705 rtn.type = JAM_BOOLEAN_EXPR;
707 else
708 urj_jam_return_code = JAMC_TYPE_MISMATCH;
709 break;
711 case ABS:
712 if ((op1.type == JAM_INTEGER_EXPR) ||
713 (op1.type == JAM_INT_OR_BOOL_EXPR))
715 rtn.val = (op1.val < 0) ? (0 - op1.val) : op1.val;
716 rtn.type = JAM_INTEGER_EXPR;
718 else
719 urj_jam_return_code = JAMC_TYPE_MISMATCH;
720 break;
722 case INT:
723 rtn.val = op1.val;
724 rtn.type = JAM_INTEGER_EXPR;
725 break;
727 case LOG2:
728 if ((op1.type == JAM_INTEGER_EXPR) ||
729 (op1.type == JAM_INT_OR_BOOL_EXPR))
731 if (op1.val > 0)
733 rtn.child_otype = LOG2;
734 rtn.type = JAM_INTEGER_EXPR;
735 rtn.loper = op1.val;
736 tmp_val = op1.val;
737 rtn.val = 0;
739 while (tmp_val != 1) /* ret_val = log2(left_val) */
741 tmp_val = tmp_val >> 1;
742 ++rtn.val;
745 /* if 2^(return_val) isn't the left_val, then the log */
746 /* wasn't a perfect integer, so we increment it */
747 if (pow (2, rtn.val) != op1.val)
749 ++rtn.val; /* Assume ceil of log2 */
752 else
754 urj_jam_return_code = JAMC_INTEGER_OVERFLOW;
757 else
758 urj_jam_return_code = JAMC_TYPE_MISMATCH;
759 break;
761 case SQRT:
762 if ((op1.type == JAM_INTEGER_EXPR) ||
763 (op1.type == JAM_INT_OR_BOOL_EXPR))
765 if (op1.val >= 0)
767 rtn.child_otype = SQRT;
768 rtn.type = JAM_INTEGER_EXPR;
769 rtn.loper = op1.val;
770 rtn.val = sqrt (op1.val);
772 else
774 urj_jam_return_code = JAMC_INTEGER_OVERFLOW;
777 else
778 urj_jam_return_code = JAMC_TYPE_MISMATCH;
779 break;
781 case CIEL:
782 if ((op1.type == JAM_INTEGER_EXPR)
783 || (op1.type == JAM_INT_OR_BOOL_EXPR))
785 if (op1.child_otype == DIV)
787 /* Below is true if wasn't perfect divide */
788 if ((op1.loper * op1.roper) != op1.val)
790 rtn.val = op1.val + 1; /* add 1 to get CEIL */
792 else
794 rtn.val = op1.val;
797 else if (op1.child_otype == SQRT)
799 /* Below is true if wasn't perfect square-root */
800 if ((op1.val * op1.val) < op1.loper)
802 rtn.val = op1.val + 1; /* add 1 to get CEIL */
804 else
806 rtn.val = op1.val;
809 else
811 rtn.val = op1.val;
813 rtn.type = JAM_INTEGER_EXPR;
815 else
816 urj_jam_return_code = JAMC_TYPE_MISMATCH;
817 break;
819 case FLOOR:
820 if (((op1.type == JAM_INTEGER_EXPR)
821 || (op1.type == JAM_INT_OR_BOOL_EXPR))
822 && ((op2.type == JAM_INTEGER_EXPR)
823 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
825 if (op1.child_otype == LOG2)
827 if (pow (2, op1.val) != op1.loper)
829 rtn.val = op1.val - 1;
831 else
833 rtn.val = op1.val;
836 else
838 rtn.val = op1.val;
840 rtn.type = JAM_INTEGER_EXPR;
842 else
843 urj_jam_return_code = JAMC_TYPE_MISMATCH;
844 break;
846 case ARRAY:
847 if ((op1.type == JAM_ARRAY_REFERENCE) &&
848 ((op2.type == JAM_INTEGER_EXPR)
849 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
851 symbol_rec = (JAMS_SYMBOL_RECORD *) op1.val;
852 urj_jam_return_code =
853 urj_jam_get_array_value (symbol_rec, op2.val, &rtn.val);
855 if (urj_jam_return_code == JAMC_SUCCESS)
857 switch (symbol_rec->type)
859 case JAM_INTEGER_ARRAY_WRITABLE:
860 case JAM_INTEGER_ARRAY_INITIALIZED:
861 rtn.type = JAM_INTEGER_EXPR;
862 break;
864 case JAM_BOOLEAN_ARRAY_WRITABLE:
865 case JAM_BOOLEAN_ARRAY_INITIALIZED:
866 rtn.type = JAM_BOOLEAN_EXPR;
867 break;
869 default:
870 urj_jam_return_code = JAMC_INTERNAL_ERROR;
871 break;
875 else
876 urj_jam_return_code = JAMC_TYPE_MISMATCH;
877 break;
879 case POUND:
880 rtn.val = op1.val;
881 rtn.type = JAM_INTEGER_EXPR;
882 break;
884 case DOLLAR:
885 rtn.val = op1.val;
886 rtn.type = JAM_INTEGER_EXPR;
887 break;
889 case ARRAY_RANGE:
890 if (((op1.type == JAM_INTEGER_EXPR)
891 || (op1.type == JAM_INT_OR_BOOL_EXPR))
892 && ((op2.type == JAM_INTEGER_EXPR)
893 || (op2.type == JAM_INT_OR_BOOL_EXPR)))
895 symbol_rec = urj_jam_array_symbol_rec;
897 if ((symbol_rec != NULL) &&
898 ((symbol_rec->type == JAM_BOOLEAN_ARRAY_WRITABLE) ||
899 (symbol_rec->type == JAM_BOOLEAN_ARRAY_INITIALIZED)))
901 heap_rec = (JAMS_HEAP_RECORD *) symbol_rec->value;
903 if (heap_rec != NULL)
905 rtn.val = urj_jam_convert_bool_to_int (heap_rec->data,
906 op1.val, op2.val);
908 rtn.type = JAM_INTEGER_EXPR;
910 else
911 urj_jam_return_code = JAMC_TYPE_MISMATCH;
913 else
914 urj_jam_return_code = JAMC_TYPE_MISMATCH;
915 break;
917 case ARRAY_ALL:
918 if (op1.type == JAM_ARRAY_REFERENCE)
920 symbol_rec = (JAMS_SYMBOL_RECORD *) op1.val;
922 if ((symbol_rec != NULL) &&
923 ((symbol_rec->type == JAM_BOOLEAN_ARRAY_WRITABLE) ||
924 (symbol_rec->type == JAM_BOOLEAN_ARRAY_INITIALIZED)))
926 heap_rec = (JAMS_HEAP_RECORD *) symbol_rec->value;
928 if (heap_rec != NULL)
930 rtn.val = urj_jam_convert_bool_to_int (heap_rec->data,
931 heap_rec->dimension -
932 1, 0);
934 rtn.type = JAM_INTEGER_EXPR;
936 else
937 urj_jam_return_code = JAMC_TYPE_MISMATCH;
939 else
940 urj_jam_return_code = JAMC_TYPE_MISMATCH;
941 break;
943 default:
944 urj_jam_return_code = JAMC_INTERNAL_ERROR;
945 break;
948 return rtn;
952 /****************************************************************************/
953 /* */
955 void
956 urj_jam_exp_lexer (void)
957 /* */
958 /* Description: Lexical analyzer for expressions. */
959 /* */
960 /* Results are returned in the global variables */
961 /* urj_jam_token and urj_jam_token_buffer. */
962 /* */
963 /* References: Compilers: Principles, Techniques and Tools by ASU */
964 /* (the Green Dragon book), section 3.4, Recognition of */
965 /* tokens. */
966 /* */
967 /* Returns: Nothing */
968 /* */
969 /****************************************************************************/
971 BEGIN_MACHINE;
973 start:
974 GET_FIRST_CH;
975 if (CH == '\0')
976 ACCEPT (END_OF_STRING) /* Fake an EOF! */
977 else if (CH == ' ' || iscntrl (CH))
978 goto start; /* white space */
979 else if (isalpha (CH))
980 goto identifier;
981 else if (isdigit (CH))
982 goto number;
983 else if (CH == '&')
985 GET_NEXT_CH;
986 if (CH == '&')
987 ACCEPT (AND_TOK)
988 else
990 UNGET_CH;
991 ACCEPT ('&')
994 else if (CH == '|')
996 GET_NEXT_CH;
997 if (CH == '|')
998 ACCEPT (OR_TOK)
999 else
1001 UNGET_CH;
1002 ACCEPT ('|')
1005 else if (CH == '=')
1007 GET_NEXT_CH;
1008 if (CH == '=')
1009 ACCEPT (EQUALITY_TOK)
1010 else
1012 UNGET_CH;
1013 ACCEPT ('=')
1016 else if (CH == '!')
1018 GET_NEXT_CH;
1019 if (CH == '=')
1020 ACCEPT (INEQUALITY_TOK)
1021 else
1023 UNGET_CH;
1024 ACCEPT ('!')
1027 else if (CH == '>')
1029 GET_NEXT_CH;
1030 if (CH == '=')
1031 ACCEPT (GREATER_EQ_TOK)
1032 else
1033 if (CH == '>')
1034 ACCEPT (RIGHT_SHIFT_TOK)
1035 else
1037 UNGET_CH;
1038 ACCEPT (GREATER_TOK)
1041 else if (CH == '<')
1043 GET_NEXT_CH;
1044 if (CH == '=')
1045 ACCEPT (LESS_OR_EQ_TOK)
1046 else
1047 if (CH == '<')
1048 ACCEPT (LEFT_SHIFT_TOK)
1049 else
1051 UNGET_CH;
1052 ACCEPT (LESS_TOK)
1055 else if (CH == '.')
1057 GET_NEXT_CH;
1058 if (CH == '.')
1059 ACCEPT (DOT_DOT_TOK)
1060 else
1062 UNGET_CH;
1063 ACCEPT ('.')
1066 else
1067 ACCEPT (CH) /* single-chararcter token */
1068 number:
1069 GET_NEXT_CH;
1070 if (isdigit (CH))
1071 goto number;
1072 else if (isalpha (CH) || CH == '_')
1073 goto identifier;
1074 else
1076 UNGET_CH;
1077 ACCEPT (VALUE_TOK)
1080 identifier:
1081 GET_NEXT_CH;
1082 if (jam_is_name_char(CH))
1083 goto identifier;
1084 else
1086 UNGET_CH;
1087 ACCEPT (IDENTIFIER_TOK)
1090 END_MACHINE;
1094 /************************************************************************/
1095 /* */
1097 bool
1098 urj_jam_constant_is_ok (const char *string)
1099 /* This routine returns true if the value represented by string is */
1100 /* a valid signed decimal number. */
1101 /* */
1103 size_t ret = strspn (string, "-0123456789");
1104 return string[ret] == '\0' ? true : false;
1108 /************************************************************************/
1109 /* */
1111 bool
1112 urj_jam_binary_constant_is_ok (const char *string)
1113 /* This routine returns true if the value represented by string is */
1114 /* a valid binary number (containing only '0' and '1' characters). */
1115 /* */
1117 size_t ret = strspn (string, "10");
1118 return string[ret] == '\0' ? true : false;
1122 /************************************************************************/
1123 /* */
1125 bool
1126 urj_jam_hex_constant_is_ok (const char *string)
1127 /* This routine returns true if the value represented by string is */
1128 /* a valid hexadecimal number. */
1129 /* */
1131 size_t ret = strspn (string, "0123456789ABCDEFabcdef");
1132 return string[ret] == '\0' ? true : false;
1135 int32_t
1136 urj_jam_atol_bin (char *string)
1138 int32_t result = 0L;
1139 int index = 0;
1141 while ((string[index] == '0') || (string[index] == '1'))
1143 result = (result << 1) + (string[index] - '0');
1144 ++index;
1147 return result;
1150 int32_t
1151 urj_jam_atol_hex (char *string)
1153 int32_t result = 0L;
1155 sscanf (string, "%x", &result);
1157 return result;
1161 /************************************************************************/
1162 /* */
1165 urj_jam_constant_value (char *string, int32_t *value)
1166 /* */
1167 /* This routine converts a string constant into its binary */
1168 /* value. */
1169 /* */
1170 /* Returns true for success, false if the string could not be */
1171 /* converted. */
1172 /* */
1174 int status = false;
1176 if (urj_jam_expression_type == '#')
1178 if (urj_jam_binary_constant_is_ok (string))
1180 *value = urj_jam_atol_bin (string);
1181 urj_jam_expression_type = 0;
1182 status = true;
1185 else if (urj_jam_expression_type == '$')
1187 if (urj_jam_hex_constant_is_ok (string))
1189 *value = urj_jam_atol_hex (string);
1190 urj_jam_expression_type = 0;
1191 status = true;
1194 else if (urj_jam_constant_is_ok (string))
1196 if (string[0] == '-')
1198 *value = 0 - atol (&string[1]);
1200 else
1202 *value = atol (string);
1204 status = true;
1207 return status;
1211 /************************************************************************/
1212 /* */
1214 void
1215 urj_jam_yyerror (char *msg)
1216 /* */
1217 /* WARNING: When compiling for YACC 5.0 using err_skel.c, */
1218 /* this function needs to be modified to be: */
1219 /* */
1220 /* urj_jam_yyerror(char *ms1, char *msg2) */
1221 /* */
1222 /* urj_jam_yyerror() handles syntax error messages from the parser. */
1223 /* Since we don't care about anything else but reporting the error, */
1224 /* just flag the error in urj_jam_return_code. */
1225 /* */
1227 msg = msg; /* Avoid compiler warning about msg unused */
1229 if (urj_jam_return_code == JAMC_SUCCESS)
1230 urj_jam_return_code = JAMC_SYNTAX_ERROR;
1234 /************************************************************************/
1235 /* */
1238 urj_jam_yylex (void)
1239 /* */
1240 /* This is the lexer function called by urj_jam_yyparse(). It calls */
1241 /* urj_jam_exp_lexer() to run as the DFA to return a token in urj_jam_token */
1242 /* */
1244 JAMS_SYMBOL_RECORD *symbol_rec = NULL;
1245 int32_t val = 0L;
1246 JAME_EXPRESSION_TYPE type = JAM_ILLEGAL_EXPR_TYPE;
1247 int token_length;
1248 int i;
1250 urj_jam_exp_lexer ();
1252 token_length = strlen (urj_jam_token_buffer);
1254 if (token_length > 1)
1256 for (i = 0; i < ARRAY_SIZE(jam_keyword_table); i++)
1258 if (token_length == jam_keyword_table[i].length)
1260 if (!strcmp
1261 (urj_jam_token_buffer, jam_keyword_table[i].string))
1263 urj_jam_token = jam_keyword_table[i].token;
1269 if (urj_jam_token == VALUE_TOK)
1271 if (urj_jam_constant_value (urj_jam_token_buffer, &val))
1273 /* literal 0 and 1 may be interpreted as Integer or Boolean */
1274 if ((val == 0) || (val == 1))
1276 type = JAM_INT_OR_BOOL_EXPR;
1278 else
1280 type = JAM_INTEGER_EXPR;
1283 else
1285 urj_jam_return_code = JAMC_SYNTAX_ERROR;
1288 else if (urj_jam_token == IDENTIFIER_TOK)
1290 urj_jam_return_code =
1291 urj_jam_get_symbol_record (urj_jam_token_buffer, &symbol_rec);
1293 if (urj_jam_return_code == JAMC_SUCCESS)
1295 switch (symbol_rec->type)
1297 case JAM_INTEGER_SYMBOL:
1298 /* Success, swap token to be a VALUE */
1299 urj_jam_token = VALUE_TOK;
1300 val = symbol_rec->value;
1301 type = JAM_INTEGER_EXPR;
1302 break;
1304 case JAM_BOOLEAN_SYMBOL:
1305 /* Success, swap token to be a VALUE */
1306 urj_jam_token = VALUE_TOK;
1307 val = symbol_rec->value ? 1 : 0;
1308 type = JAM_BOOLEAN_EXPR;
1309 break;
1311 case JAM_INTEGER_ARRAY_WRITABLE:
1312 case JAM_BOOLEAN_ARRAY_WRITABLE:
1313 case JAM_INTEGER_ARRAY_INITIALIZED:
1314 case JAM_BOOLEAN_ARRAY_INITIALIZED:
1315 /* Success, swap token to be an ARRAY_TOK, */
1316 /* save pointer to symbol record in value field */
1317 urj_jam_token = ARRAY_TOK;
1318 val = (int32_t) symbol_rec;
1319 type = JAM_ARRAY_REFERENCE;
1320 urj_jam_array_symbol_rec = symbol_rec;
1321 break;
1323 default:
1324 urj_jam_return_code = JAMC_SYNTAX_ERROR;
1325 break;
1329 else if (urj_jam_token == '#')
1331 urj_jam_expression_type = '#';
1333 else if (urj_jam_token == '$')
1335 urj_jam_expression_type = '$';
1338 urj_jam_yylval.val = val;
1339 urj_jam_yylval.type = type;
1340 urj_jam_yylval.child_otype = 0;
1341 urj_jam_yylval.loper = 0;
1342 urj_jam_yylval.roper = 0;
1344 return urj_jam_token;
1348 /************************************************************************/
1349 /* */
1351 JAM_RETURN_TYPE urj_jam_evaluate_expression
1352 (char *expression, int32_t *result, JAME_EXPRESSION_TYPE *result_type)
1353 /* */
1354 /* THIS IS THE ENTRY POINT INTO THE EXPRESSION EVALUATOR. */
1355 /* */
1356 /* s = a string representing the expression to be evaluated. */
1357 /* (e.g. "2+2+PARAMETER") */
1358 /* */
1359 /* status = for returning true if evaluation was successful. */
1360 /* false if not. */
1361 /* */
1362 /* This routine sets up the global variables and then calls */
1363 /* urj_jam_yyparse() to do the parsing. The reduce actions of the */
1364 /* parser evaluate the expression. */
1365 /* */
1366 /* RETURNS: Value of the expression if success. 0 if FAIL. */
1367 /* */
1368 /* Note: One should not rely on the return val to det. success/fail */
1369 /* since it is possible for, say, "2-2" to be success and */
1370 /* return 0. */
1371 /* */
1373 strcpy (urj_jam_parse_string, expression);
1374 urj_jam_strptr = 0;
1375 urj_jam_token_buffer_index = 0;
1376 urj_jam_return_code = JAMC_SUCCESS;
1378 urj_jam_yyparse ();
1380 if (urj_jam_return_code == JAMC_SUCCESS)
1382 if (result != 0)
1383 *result = urj_jam_parse_value;
1384 if (result_type != 0)
1385 *result_type = urj_jam_expr_type;
1388 return urj_jam_return_code;
1392 %% // Grammar rules
1394 // grammar start symbol
1395 stapl_expr: /*P1*/ logical_or_expr {
1396 urj_jam_parse_value = $1.val;
1397 urj_jam_expr_type = $1.type;
1400 pound_expr: /*P2*/ '#' "VALUE"[right] {
1401 $$ = CALC (POUND, $right, NULL_EXP);
1404 dollar_expr: /*P3*/ '$' "VALUE"[right] {
1405 $$ = CALC (DOLLAR, $right, NULL_EXP);
1407 | '$' array_expr[right] {
1408 $$ = CALC (DOLLAR, $right, NULL_EXP);
1411 array_range: /*P4*/ "ARRAY" '[' logical_or_expr[left] ".." logical_or_expr[right] ']' {
1412 // ??: ARRAY seems to have been cached somewhere
1413 $$ = CALC (ARRAY_RANGE, $left, $right);
1416 array_all: /*P5*/ "ARRAY"[left] '[' ']' {
1417 $$ = CALC (ARRAY_ALL, $left, NULL_EXP);
1420 primary_expr: /*P6*/ "VALUE"
1421 | /*P7*/ '(' logical_or_expr[mid] ')' {
1422 $$ = $mid;
1424 | array_expr
1425 | abs_expr
1426 | ceil_expr
1427 | floor_expr
1428 | int_expr
1429 | log2_expr
1430 | sqrt_expr
1432 unary_expr: primary_expr
1433 | /*P8*/ '+' unary_expr[right] {
1434 $$ = $right;
1436 | /*P9*/ '-' unary_expr[right] {
1437 $$ = CALC (UMINUS, $right, NULL_EXP);
1439 | /*P10*/ '!' unary_expr[right] {
1440 $$ = CALC (NOT, $right, NULL_EXP);
1442 | /*P11*/ '~' unary_expr[right] {
1443 $$ = CALC (BITWISE_NOT, $right, NULL_EXP);
1446 additive_expr: multiplicative_expr
1447 | /*P12*/ additive_expr[left] '+' multiplicative_expr[right] {
1448 $$ = CALC (ADD, $left, $right);
1450 | /*P13*/ additive_expr[left] '-' multiplicative_expr[right] {
1451 $$ = CALC (SUB, $left, $right);
1454 multiplicative_expr: unary_expr
1455 | /*P14*/ multiplicative_expr[left] '*' unary_expr[right] {
1456 $$ = CALC (MULT, $left, $right);
1458 | /*P15*/ multiplicative_expr[left] '/' unary_expr[right] {
1459 $$ = CALC (DIV, $left, $right);
1461 | /*P16*/ multiplicative_expr[left] '%' unary_expr[right] {
1462 $$ = CALC (MOD, $left, $right);
1465 bitand_expr: equality_expr
1466 | /*P17*/ bitand_expr[left] '&' equality_expr[right] {
1467 $$ = CALC (BITWISE_AND, $left, $right);
1470 bitor_expr: bitxor_expr
1471 | /*P18*/ bitor_expr[left] '|' bitxor_expr[right] {
1472 $$ = CALC (BITWISE_OR, $left, $right);
1475 bitxor_expr: bitand_expr
1476 | /*P19*/ bitxor_expr[left] '^' bitand_expr[right] {
1477 $$ = CALC (BITWISE_XOR, $left, $right);
1480 logical_and_expr: bitor_expr
1481 | /*P20*/ logical_and_expr[left] "&&" bitor_expr[right] {
1482 $$ = CALC (AND, $left, $right);
1485 logical_or_expr: logical_and_expr
1486 | /*P21*/ logical_or_expr[left] "||" logical_and_expr[right] {
1487 $$ = CALC (OR, $left, $right);
1490 shift_expr: additive_expr
1491 | /*P22*/ shift_expr[left] "<<" additive_expr[right] {
1492 $$ = CALC (LEFT_SHIFT, $left, $right);
1494 | /*P23*/ shift_expr[left] ">>" additive_expr[right] {
1495 $$ = CALC (RIGHT_SHIFT, $left, $right);
1498 equality_expr: relational_expr
1499 | /*P24*/ equality_expr[left] "==" relational_expr[right] {
1500 $$ = CALC (EQUALITY, $left, $right);
1502 | /*P25*/ equality_expr[left] "!=" relational_expr[right] {
1503 $$ = CALC (INEQUALITY, $left, $right);
1506 relational_expr: shift_expr
1507 | /*P26*/ relational_expr[left] '>' shift_expr[right] {
1508 $$ = CALC (GREATER_THAN, $left, $right);
1510 | /*P27*/ relational_expr[left] '<' shift_expr[right] {
1511 $$ = CALC (LESS_THAN, $left, $right);
1513 | /*28*/ relational_expr[left] ">=" shift_expr[right] {
1514 $$ = CALC (GREATER_OR_EQUAL, $left, $right);
1516 | /*P29*/ relational_expr[left] "<=" shift_expr[right] {
1517 $$ = CALC (LESS_OR_EQUAL, $left, $right);
1520 abs_expr: /*P30*/ "ABS" '(' logical_or_expr[mid] ')' {
1521 $$ = CALC (ABS, $mid, NULL_EXP);
1524 int_expr: /*P31*/ "INT" '(' pound_expr[mid] ')' {
1525 $$ = CALC (INT, $mid, NULL_EXP);
1527 | "INT" '(' dollar_expr[mid] ')' {
1528 $$ = CALC (INT, $mid, NULL_EXP);
1530 | "INT" '(' array_range[mid] ')' {
1531 $$ = CALC (INT, $mid, NULL_EXP);
1533 | "INT" '(' array_all[mid] ')' {
1534 $$ = CALC (INT, $mid, NULL_EXP);
1537 log2_expr: /*P32*/ "LOG2" '(' logical_or_expr[mid] ')' {
1538 $$ = CALC (LOG2, $mid, NULL_EXP);
1541 sqrt_expr: /*P33*/ "SQRT" '(' logical_or_expr[mid] ')' {
1542 $$ = CALC (SQRT, $mid, NULL_EXP);
1545 ceil_expr: /*P34*/ "CEIL" '(' logical_or_expr[mid] ')' {
1546 $$ = CALC (CIEL, $mid, NULL_EXP);
1549 floor_expr: /*P35*/ "FLOOR" '(' logical_or_expr[mid] ')' {
1550 $$ = CALC (FLOOR, $mid, NULL_EXP);
1553 array_expr: /*P36*/ "ARRAY"[left] '[' logical_or_expr[right] ']' {
1554 $$ = CALC (ARRAY, $left, $right);