1 // SPDX-FileCopyrightText: 1997 Altera Corporation
2 // SPDX-FileCopyrightText: 2022 Peter Poeschl <pp+ujt2208@nest-ai.de>
4 // SPDX-License-Identifier: GPL-2.0-or-later
21 /* ------------- LEXER DEFINITIONS -----------------------------------------*/
22 /****************************************************************************/
24 /* Operation of GET_FIRST_CH, GET_NEXT_CH, UNGET_CH, and DELETE_CH: */
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. */
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] = ? */
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. */
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] = ? */
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.) */
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] = ? */
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. */
58 /****************************************************************************/
60 #define MAX_BUFFER_LENGTH 1024
61 #define END_OF_STRING -1
65 /****************************************************************************/
67 /* Operation of BEGIN_MACHINE, END_MACHINE, and ACCEPT: */
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 */
80 /* if (whatever) goto next; */
81 /* else goto start; */
84 /* if (done) ACCEPT (a_token_id); */
85 /* else goto start; */
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. */
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 '>'
110 } static const jam_keyword_table
[] =
114 {"==", 2, EQUALITY_TOK
},
115 {"!=", 2, INEQUALITY_TOK
},
116 {">", 2, GREATER_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
},
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 */
146 #define YYMAXTLIST 25 /* Max valid next tokens for any state. */
147 /* If there are more, error reporting */
148 /* will be incomplete. */
190 typedef
enum OPERATOR_TYPE OPERATOR_TYPE
;
192 typedef
struct EXP_STACK
194 OPERATOR_TYPE child_otype
;
195 JAME_EXPRESSION_TYPE type
;
197 int32_t loper
; /* left and right operands for DIV */
198 int32_t roper
; /* we save it for CEIL/FLOOR's use */
201 #define URJ_JAM_YYSTYPE EXPN_STACK /* must be a #define for yacc */
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))
217 /* --- FUNCTION PROTOTYPES -------------------------------------------- */
219 int urj_jam_yyparse
(void);
220 int urj_jam_yylex
(void);
224 #ifdef DELME_OLD_TOKEN_VALUES
227 #define EQUALITY_TOK 259
228 #define INEQUALITY_TOK 260
229 #define GREATER_TOK 261
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
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
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
}
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
".."
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"
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
;
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;
325 static inline
void jam_unget_ch
(void)
328 urj_jam_token_buffer
[--urj_jam_token_buffer_index
] = '\0';
331 static inline
char jam_get_ch
(void)
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.
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;
349 for
(i
= lsb
; i
!= msb
; i
+= increment
)
351 if
(data
[i
>> 5] & (1L << (i
& 0x1f)))
360 /************************************************************************/
364 urj_jam_exp_eval
(OPERATOR_TYPE otype
, YYSTYPE op1
, YYSTYPE op2
)
365 /* Evaluate op1 OTYPE op2. op1, op2 are operands, OTYPE is operator */
367 /* Some sneaky things are done to implement CEIL and FLOOR. */
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!) */
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 */
383 JAMS_SYMBOL_RECORD
*symbol_rec
;
384 JAMS_HEAP_RECORD
*heap_rec
;
387 rtn.type
= JAM_ILLEGAL_EXPR_TYPE
;
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
;
402 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
422 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
442 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
463 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
)))
474 rtn.val
= op1.val
/ op2.val
;
477 rtn.child_otype
= DIV
; /* Save info needed by CEIL */
478 rtn.type
= JAM_INTEGER_EXPR
;
482 urj_jam_return_code
= JAMC_DIVIDE_BY_ZERO
;
486 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
499 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
510 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
523 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
536 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
547 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
560 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
573 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
586 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
599 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
612 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
)))
631 rtn.type
= JAM_BOOLEAN_EXPR
;
634 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
)))
653 rtn.type
= JAM_BOOLEAN_EXPR
;
656 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
669 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
682 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
695 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
708 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
719 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
724 rtn.type
= JAM_INTEGER_EXPR
;
728 if
((op1.type
== JAM_INTEGER_EXPR
) ||
729 (op1.type
== JAM_INT_OR_BOOL_EXPR
))
733 rtn.child_otype
= LOG2
;
734 rtn.type
= JAM_INTEGER_EXPR
;
739 while
(tmp_val
!= 1) /* ret_val = log2(left_val) */
741 tmp_val
= tmp_val
>> 1;
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 */
754 urj_jam_return_code
= JAMC_INTEGER_OVERFLOW
;
758 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
762 if
((op1.type
== JAM_INTEGER_EXPR
) ||
763 (op1.type
== JAM_INT_OR_BOOL_EXPR
))
767 rtn.child_otype
= SQRT
;
768 rtn.type
= JAM_INTEGER_EXPR
;
770 rtn.val
= sqrt
(op1.val
);
774 urj_jam_return_code
= JAMC_INTEGER_OVERFLOW
;
778 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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 */
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 */
813 rtn.type
= JAM_INTEGER_EXPR
;
816 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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;
840 rtn.type
= JAM_INTEGER_EXPR
;
843 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
;
864 case JAM_BOOLEAN_ARRAY_WRITABLE
:
865 case JAM_BOOLEAN_ARRAY_INITIALIZED
:
866 rtn.type
= JAM_BOOLEAN_EXPR
;
870 urj_jam_return_code
= JAMC_INTERNAL_ERROR
;
876 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
881 rtn.type
= JAM_INTEGER_EXPR
;
886 rtn.type
= JAM_INTEGER_EXPR
;
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
,
908 rtn.type
= JAM_INTEGER_EXPR
;
911 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
914 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
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
-
934 rtn.type
= JAM_INTEGER_EXPR
;
937 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
940 urj_jam_return_code
= JAMC_TYPE_MISMATCH
;
944 urj_jam_return_code
= JAMC_INTERNAL_ERROR
;
952 /****************************************************************************/
956 urj_jam_exp_lexer
(void)
958 /* Description: Lexical analyzer for expressions. */
960 /* Results are returned in the global variables */
961 /* urj_jam_token and urj_jam_token_buffer. */
963 /* References: Compilers: Principles, Techniques and Tools by ASU */
964 /* (the Green Dragon book), section 3.4, Recognition of */
967 /* Returns: Nothing */
969 /****************************************************************************/
976 ACCEPT
(END_OF_STRING
) /* Fake an EOF! */
977 else if
(CH
== ' ' || iscntrl
(CH
))
978 goto start
; /* white space */
979 else if
(isalpha
(CH
))
981 else if
(isdigit
(CH
))
1009 ACCEPT
(EQUALITY_TOK
)
1020 ACCEPT
(INEQUALITY_TOK
)
1031 ACCEPT
(GREATER_EQ_TOK
)
1034 ACCEPT
(RIGHT_SHIFT_TOK
)
1038 ACCEPT
(GREATER_TOK
)
1045 ACCEPT
(LESS_OR_EQ_TOK
)
1048 ACCEPT
(LEFT_SHIFT_TOK
)
1059 ACCEPT
(DOT_DOT_TOK
)
1067 ACCEPT
(CH
) /* single-chararcter token */
1072 else if
(isalpha
(CH
) || CH
== '_')
1082 if
(jam_is_name_char
(CH
))
1087 ACCEPT
(IDENTIFIER_TOK
)
1094 /************************************************************************/
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. */
1103 size_t ret
= strspn
(string, "-0123456789");
1104 return
string[ret
] == '\0' ? true
: false
;
1108 /************************************************************************/
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). */
1117 size_t ret
= strspn
(string, "10");
1118 return
string[ret
] == '\0' ? true
: false
;
1122 /************************************************************************/
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. */
1131 size_t ret
= strspn
(string, "0123456789ABCDEFabcdef");
1132 return
string[ret
] == '\0' ? true
: false
;
1136 urj_jam_atol_bin
(char *string)
1138 int32_t result
= 0L;
1141 while
((string[index
] == '0') ||
(string[index
] == '1'))
1143 result
= (result
<< 1) + (string[index
] - '0');
1151 urj_jam_atol_hex
(char *string)
1153 int32_t result
= 0L;
1155 sscanf
(string, "%x", &result
);
1161 /************************************************************************/
1165 urj_jam_constant_value
(char *string, int32_t *value
)
1167 /* This routine converts a string constant into its binary */
1170 /* Returns true for success, false if the string could not be */
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;
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;
1194 else if
(urj_jam_constant_is_ok
(string))
1196 if
(string[0] == '-')
1198 *value
= 0 - atol
(&string[1]);
1202 *value
= atol
(string);
1211 /************************************************************************/
1215 urj_jam_yyerror
(char *msg
)
1217 /* WARNING: When compiling for YACC 5.0 using err_skel.c, */
1218 /* this function needs to be modified to be: */
1220 /* urj_jam_yyerror(char *ms1, char *msg2) */
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. */
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 /************************************************************************/
1238 urj_jam_yylex
(void)
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 */
1244 JAMS_SYMBOL_RECORD
*symbol_rec
= NULL
;
1246 JAME_EXPRESSION_TYPE type
= JAM_ILLEGAL_EXPR_TYPE
;
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
)
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
;
1280 type
= JAM_INTEGER_EXPR
;
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
;
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
;
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
;
1324 urj_jam_return_code
= JAMC_SYNTAX_ERROR
;
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 /************************************************************************/
1351 JAM_RETURN_TYPE urj_jam_evaluate_expression
1352 (char *expression
, int32_t *result
, JAME_EXPRESSION_TYPE
*result_type
)
1354 /* THIS IS THE ENTRY POINT INTO THE EXPRESSION EVALUATOR. */
1356 /* s = a string representing the expression to be evaluated. */
1357 /* (e.g. "2+2+PARAMETER") */
1359 /* status = for returning true if evaluation was successful. */
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. */
1366 /* RETURNS: Value of the expression if success. 0 if FAIL. */
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 */
1373 strcpy
(urj_jam_parse_string
, expression
);
1375 urj_jam_token_buffer_index
= 0;
1376 urj_jam_return_code
= JAMC_SUCCESS
;
1380 if
(urj_jam_return_code
== JAMC_SUCCESS
)
1383 *result
= urj_jam_parse_value
;
1384 if
(result_type
!= 0)
1385 *result_type
= urj_jam_expr_type
;
1388 return urj_jam_return_code
;
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
] ')' {
1432 unary_expr: primary_expr
1433 |
/*P8*/ '+' unary_expr
[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);