From 3a7a804f9bcd099265dc1fb0b6c1b0213490410b Mon Sep 17 00:00:00 2001 From: David Schmenk Date: Sun, 11 Jan 2015 17:07:31 -0800 Subject: [PATCH] First attempt to improve const value parsing --- src/toolsrc/parse.c | 244 ++++++++++++++++++++++++++------------------ src/toolsrc/sb.pla | 211 +++++++++++++++++++++----------------- 2 files changed, 264 insertions(+), 191 deletions(-) diff --git a/src/toolsrc/parse.c b/src/toolsrc/parse.c index e7aaeef..f85bc4c 100755 --- a/src/toolsrc/parse.c +++ b/src/toolsrc/parse.c @@ -67,22 +67,25 @@ int tos_op_prec(int tos) { return opsptr <= tos ? 100 : precstack[opsptr]; } -int parse_expr(void); -int parse_term(void) +/* + * Constant expression parsing + */ +int parse_constexpr(long *value, int *size); +int parse_constterm(long *value, int *size) { + int type; /* * Parse terminal tokens. */ - switch (scan()) + switch (type = scan()) { case CHAR_TOKEN: case INT_TOKEN: - case FLOAT_TOKEN: case ID_TOKEN: case STRING_TOKEN: break; case OPEN_PAREN_TOKEN: - if (!parse_expr()) + if (!(type = parse_constexpr(value, size))) { parse_error("Bad expression in parenthesis"); return (0); @@ -99,13 +102,13 @@ int parse_term(void) */ return (0); } - return (1); + return (type); } int parse_constval(long *value, int *size) { - int mod = 0, type = 0; - *value = 0; - while (!parse_term()) + int mod = 0, type; + + while (!(type = parse_constterm(value, size))) { switch (scantoken) { @@ -133,46 +136,46 @@ int parse_constval(long *value, int *size) /* * Determine which terminal type. */ - if (scantoken == STRING_TOKEN) + switch (scantoken) { - *value = constval; - *size = tokenlen - 1; - type = STRING_TYPE; - if (mod) - { - parse_error("Invalid string modifiers"); - return (0); - } - } - else if (scantoken == CHAR_TOKEN) - { - *value = constval; - *size = 1; - type = CONST_TYPE; - } - else if (scantoken == INT_TOKEN) - { - *value = constval; - *size = 2; - type = CONST_TYPE; - } - else if (scantoken == ID_TOKEN) - { - type = id_type(tokenstr, tokenlen); - if (type & CONST_TYPE) - *value = id_const(tokenstr, tokenlen); - else if ((type & (FUNC_TYPE | EXTERN_TYPE)) || ((type & ADDR_TYPE) && (mod & 8))) - *value = id_tag(tokenstr, tokenlen); - else - { + case STRING_TOKEN: + *size = tokenlen - 1; + *value = constval; + type = STRING_TYPE; + if (mod) + { + parse_error("Invalid string modifiers"); + return (0); + } + break; + case CHAR_TOKEN: + *size = 1; + *value = constval; + type = CONST_TYPE; + break; + case INT_TOKEN: + *size = 2; + *value = constval; + type = CONST_TYPE; + break; + case ID_TOKEN: + *size = 2; + type = id_type(tokenstr, tokenlen); + if (type & CONST_TYPE) + *value = id_const(tokenstr, tokenlen); + else if ((type & (FUNC_TYPE | EXTERN_TYPE)) || ((type & ADDR_TYPE) && (mod == 8))) + *value = id_tag(tokenstr, tokenlen); + else + { + parse_error("Invalid constant"); + return (0); + } + break; + case CLOSE_PAREN_TOKEN: + break; + default: parse_error("Invalid constant"); return (0); - } - } - else - { - parse_error("Invalid constant"); - return (0); } if (mod & 1) *value = -*value; @@ -182,6 +185,101 @@ int parse_constval(long *value, int *size) *value = *value ? 0 : -1; return (type); } +int parse_constexpr(long *value, int *size) +{ + long val1, val2; + int valtype, type, size1, size2; + + if (!(valtype = parse_constval(&val1, &size1))) + return (0); + do + { + size2 = 0; + switch (scan()) + { + case ADD_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 + val2; + break; + case SUB_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 - val2; + break; + case MUL_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 * val2; + break; + case DIV_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 / val2; + break; + case AND_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 & val2; + break; + case OR_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 | val2; + break; + case EOR_TOKEN: + if (!(type = parse_constval(&val2, &size2))) + return (0); + val1 = val1 ^ val2; + break; + } + if (size1 > size2) + *size = size1; + else + { + valtype = type; + *size = size2; + } + } while (size2); + *value = val1; + return (valtype); +} +/* + * Normal expression parsing + */ +int parse_expr(void); +int parse_term(void) +{ + /* + * Parse terminal tokens. + */ + switch (scan()) + { + case CHAR_TOKEN: + case INT_TOKEN: + case ID_TOKEN: + case STRING_TOKEN: + break; + case OPEN_PAREN_TOKEN: + if (!parse_expr()) + { + parse_error("Bad expression in parenthesis"); + return (0); + } + if (scantoken != CLOSE_PAREN_TOKEN) + { + parse_error("Missing closing parenthesis"); + return (0); + } + break; + default: + /* + * Non-terminal token. + */ + return (0); + } + return (1); +} int parse_value(int rvalue) { int cparams; @@ -503,60 +601,6 @@ int parse_value(int rvalue) } return (ref_type ? ref_type : WORD_TYPE); } -int parse_constexpr(long *value, int *size) -{ - long val1, val2; - int type, size1, size2 = 0; - - if (!(type = parse_constval(&val1, &size1))) - return (0); - if (scan() == ADD_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 + val2; - } - else if (scantoken == SUB_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 - val2; - } - else if (scantoken == MUL_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 * val2; - } - else if (scantoken == DIV_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 / val2; - } - else if (scantoken == AND_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 & val2; - } - else if (scantoken == OR_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 | val2; - } - else if (scantoken == EOR_TOKEN) - { - if (!parse_constval(&val2, &size2)) - return (0); - *value = val1 ^ val2; - } - else - *value = val1; - *size = size1 > size2 ? size1 : size2; - return (type); -} int parse_expr() { int prevmatch; diff --git a/src/toolsrc/sb.pla b/src/toolsrc/sb.pla index cf68626..bb3bab8 100644 --- a/src/toolsrc/sb.pla +++ b/src/toolsrc/sb.pla @@ -389,7 +389,7 @@ byte prevstmnt = 0 word retfunc_tag = 0 word break_tag = 0 word cont_tag = 0 -predef parse_expr, parse_module +predef parse_constexpr, parse_expr, parse_module // // ASM utility functions // @@ -2865,18 +2865,22 @@ end // // Parser // -def parse_term +// +// Constant expression parsing +// +def parse_constterm(valptr, sizeptr) + word type + when scan is OPEN_PAREN_TKN - if !parse_expr - return FALSE - fin + type = parse_constexpr(valptr, sizeptr) if token <> CLOSE_PAREN_TKN; return parse_err(@no_close_paren); fin + return type is ID_TKN is INT_TKN is CHR_TKN is STR_TKN - return TRUE + return token wend return FALSE end @@ -2884,52 +2888,57 @@ def parse_constval(valptr, sizeptr) byte mod, type word idptr, ctag - mod = 0 - type = 0 - while !parse_term - when token - is SUB_TKN - mod = mod | 1; break - is COMP_TKN - mod = mod | 2; break - is LOGIC_NOT_TKN - mod = mod | 4; break - is AT_TKN - mod = mod | 8; break - is ADD_TKN - break - otherwise - return 0 - wend - loop + mod = 0 + ^sizeptr = 0 + repeat + type = parse_constterm(valptr, sizeptr) + if !type + when token + is SUB_TKN + mod = mod | 1; break + is COMP_TKN + mod = mod | 2; break + is LOGIC_NOT_TKN + mod = mod | 4; break + is AT_TKN + mod = mod | 8; break + is ADD_TKN + break + otherwise + return 0 + wend + fin + until type when token is STR_TKN - *valptr = constval ^sizeptr = tknlen - 1 + *valptr = constval type = STR_TYPE if mod; return parse_err(@bad_op); fin - break + break is CHR_TKN - *valptr = constval ^sizeptr = 1 - type = BYTE_TYPE - break - is INT_TKN *valptr = constval + type = BYTE_TYPE + break + is INT_TKN ^sizeptr = 2 + *valptr = constval type = WORD_TYPE - break + break is ID_TKN ^sizeptr = 2 idptr = id_lookup(tknptr, tknlen) if !idptr; return parse_err(@bad_cnst); fin type = idptr->idtype if type & ADDR_TYPE - if mod <> 8; return parse_err(@bad_cnst); fin + if mod <> 8; return parse_err(@bad_cnst); fin type = CONSTADDR_TYPE fin - *valptr = idptr=>idval + *valptr = idptr=>idval break + is CLOSE_PAREN_TKN + break otherwise return parse_err(@bad_cnst) wend @@ -2944,6 +2953,69 @@ def parse_constval(valptr, sizeptr) fin return type end +def parse_constexpr(valptr, sizeptr) + byte valtype, type, size1, size2 + word val1, val2 + + valtype = parse_constval(@val1, @size1) + if !valtype; return 0; fin + repeat + size2 = 0 + when scan + is ADD_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 + val2 + break + is SUB_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 - val2 + break + is MUL_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 * val2 + break + is DIV_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 / val2 + break + is MOD_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 % val2 + break + is AND_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 & val2 + break + is OR_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 | val2 + break + is EOR_TKN + type = parse_constval(@val2, @size2) + if !type; return 0; fin + val1 = val1 ^ val2 + break + wend + if size1 > size2 + ^sizeptr = size1 + else + valtype = type + ^sizeptr = size2 + fin + until !size2 + *valptr = val1 + return valtype +end +// +// Normal expression parsing +// def ispostop when scan is OPEN_PAREN_TKN @@ -2956,6 +3028,21 @@ def ispostop wend return FALSE end +def parse_term + when scan + is OPEN_PAREN_TKN + if !parse_expr + return FALSE + fin + if token <> CLOSE_PAREN_TKN; return parse_err(@no_close_paren); fin + is ID_TKN + is INT_TKN + is CHR_TKN + is STR_TKN + return TRUE + wend + return FALSE +end def parse_value(rvalue) byte cparams, deref, type, emit_val word optos, idptr, value @@ -3275,64 +3362,6 @@ def parse_value(rvalue) fin return ref_type end -def parse_constexpr(valptr, sizeptr) - byte type, size1, size2 - word val1, val2 - - type = parse_constval(@val1, @size1) - if !type; return 0; fin - size2 = 0 - when scan - is ADD_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 + val2 - break - is SUB_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 - val2 - break - is MUL_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 * val2 - break - is DIV_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 / val2 - break - is MOD_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 % val2 - break - is AND_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 & val2 - break - is OR_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 | val2 - break - is EOR_TKN - type = parse_constval(@val2, @size2) - if !type; return 0; fin - *valptr = val1 ^ val2 - break - otherwise - *valptr = val1 - wend - if size1 > size2 - ^sizeptr = size1 - else - ^sizeptr = size2 - fin - return type -end def parse_expr byte prevmatch, matchop, i word optos