1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2025-01-11 13:29:44 +00:00

First attempt to improve const value parsing

This commit is contained in:
David Schmenk 2015-01-11 17:07:31 -08:00
parent 352bf0439c
commit 3a7a804f9b
2 changed files with 264 additions and 191 deletions

View File

@ -67,22 +67,25 @@ int tos_op_prec(int tos)
{ {
return opsptr <= tos ? 100 : precstack[opsptr]; 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. * Parse terminal tokens.
*/ */
switch (scan()) switch (type = scan())
{ {
case CHAR_TOKEN: case CHAR_TOKEN:
case INT_TOKEN: case INT_TOKEN:
case FLOAT_TOKEN:
case ID_TOKEN: case ID_TOKEN:
case STRING_TOKEN: case STRING_TOKEN:
break; break;
case OPEN_PAREN_TOKEN: case OPEN_PAREN_TOKEN:
if (!parse_expr()) if (!(type = parse_constexpr(value, size)))
{ {
parse_error("Bad expression in parenthesis"); parse_error("Bad expression in parenthesis");
return (0); return (0);
@ -99,13 +102,13 @@ int parse_term(void)
*/ */
return (0); return (0);
} }
return (1); return (type);
} }
int parse_constval(long *value, int *size) int parse_constval(long *value, int *size)
{ {
int mod = 0, type = 0; int mod = 0, type;
*value = 0;
while (!parse_term()) while (!(type = parse_constterm(value, size)))
{ {
switch (scantoken) switch (scantoken)
{ {
@ -133,46 +136,46 @@ int parse_constval(long *value, int *size)
/* /*
* Determine which terminal type. * Determine which terminal type.
*/ */
if (scantoken == STRING_TOKEN) switch (scantoken)
{ {
*value = constval; case STRING_TOKEN:
*size = tokenlen - 1; *size = tokenlen - 1;
type = STRING_TYPE; *value = constval;
if (mod) type = STRING_TYPE;
{ if (mod)
parse_error("Invalid string modifiers"); {
return (0); parse_error("Invalid string modifiers");
} return (0);
} }
else if (scantoken == CHAR_TOKEN) break;
{ case CHAR_TOKEN:
*value = constval; *size = 1;
*size = 1; *value = constval;
type = CONST_TYPE; type = CONST_TYPE;
} break;
else if (scantoken == INT_TOKEN) case INT_TOKEN:
{ *size = 2;
*value = constval; *value = constval;
*size = 2; type = CONST_TYPE;
type = CONST_TYPE; break;
} case ID_TOKEN:
else if (scantoken == ID_TOKEN) *size = 2;
{ type = id_type(tokenstr, tokenlen);
type = id_type(tokenstr, tokenlen); if (type & CONST_TYPE)
if (type & CONST_TYPE) *value = id_const(tokenstr, tokenlen);
*value = id_const(tokenstr, tokenlen); else if ((type & (FUNC_TYPE | EXTERN_TYPE)) || ((type & ADDR_TYPE) && (mod == 8)))
else if ((type & (FUNC_TYPE | EXTERN_TYPE)) || ((type & ADDR_TYPE) && (mod & 8))) *value = id_tag(tokenstr, tokenlen);
*value = id_tag(tokenstr, tokenlen); else
else {
{ parse_error("Invalid constant");
return (0);
}
break;
case CLOSE_PAREN_TOKEN:
break;
default:
parse_error("Invalid constant"); parse_error("Invalid constant");
return (0); return (0);
}
}
else
{
parse_error("Invalid constant");
return (0);
} }
if (mod & 1) if (mod & 1)
*value = -*value; *value = -*value;
@ -182,6 +185,101 @@ int parse_constval(long *value, int *size)
*value = *value ? 0 : -1; *value = *value ? 0 : -1;
return (type); 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 parse_value(int rvalue)
{ {
int cparams; int cparams;
@ -503,60 +601,6 @@ int parse_value(int rvalue)
} }
return (ref_type ? ref_type : WORD_TYPE); 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 parse_expr()
{ {
int prevmatch; int prevmatch;

View File

@ -389,7 +389,7 @@ byte prevstmnt = 0
word retfunc_tag = 0 word retfunc_tag = 0
word break_tag = 0 word break_tag = 0
word cont_tag = 0 word cont_tag = 0
predef parse_expr, parse_module predef parse_constexpr, parse_expr, parse_module
// //
// ASM utility functions // ASM utility functions
// //
@ -2865,18 +2865,22 @@ end
// //
// Parser // Parser
// //
def parse_term //
// Constant expression parsing
//
def parse_constterm(valptr, sizeptr)
word type
when scan when scan
is OPEN_PAREN_TKN is OPEN_PAREN_TKN
if !parse_expr type = parse_constexpr(valptr, sizeptr)
return FALSE
fin
if token <> CLOSE_PAREN_TKN; return parse_err(@no_close_paren); fin if token <> CLOSE_PAREN_TKN; return parse_err(@no_close_paren); fin
return type
is ID_TKN is ID_TKN
is INT_TKN is INT_TKN
is CHR_TKN is CHR_TKN
is STR_TKN is STR_TKN
return TRUE return token
wend wend
return FALSE return FALSE
end end
@ -2884,52 +2888,57 @@ def parse_constval(valptr, sizeptr)
byte mod, type byte mod, type
word idptr, ctag word idptr, ctag
mod = 0 mod = 0
type = 0 ^sizeptr = 0
while !parse_term repeat
when token type = parse_constterm(valptr, sizeptr)
is SUB_TKN if !type
mod = mod | 1; break when token
is COMP_TKN is SUB_TKN
mod = mod | 2; break mod = mod | 1; break
is LOGIC_NOT_TKN is COMP_TKN
mod = mod | 4; break mod = mod | 2; break
is AT_TKN is LOGIC_NOT_TKN
mod = mod | 8; break mod = mod | 4; break
is ADD_TKN is AT_TKN
break mod = mod | 8; break
otherwise is ADD_TKN
return 0 break
wend otherwise
loop return 0
wend
fin
until type
when token when token
is STR_TKN is STR_TKN
*valptr = constval
^sizeptr = tknlen - 1 ^sizeptr = tknlen - 1
*valptr = constval
type = STR_TYPE type = STR_TYPE
if mod; return parse_err(@bad_op); fin if mod; return parse_err(@bad_op); fin
break break
is CHR_TKN is CHR_TKN
*valptr = constval
^sizeptr = 1 ^sizeptr = 1
type = BYTE_TYPE
break
is INT_TKN
*valptr = constval *valptr = constval
type = BYTE_TYPE
break
is INT_TKN
^sizeptr = 2 ^sizeptr = 2
*valptr = constval
type = WORD_TYPE type = WORD_TYPE
break break
is ID_TKN is ID_TKN
^sizeptr = 2 ^sizeptr = 2
idptr = id_lookup(tknptr, tknlen) idptr = id_lookup(tknptr, tknlen)
if !idptr; return parse_err(@bad_cnst); fin if !idptr; return parse_err(@bad_cnst); fin
type = idptr->idtype type = idptr->idtype
if type & ADDR_TYPE 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 type = CONSTADDR_TYPE
fin fin
*valptr = idptr=>idval *valptr = idptr=>idval
break break
is CLOSE_PAREN_TKN
break
otherwise otherwise
return parse_err(@bad_cnst) return parse_err(@bad_cnst)
wend wend
@ -2944,6 +2953,69 @@ def parse_constval(valptr, sizeptr)
fin fin
return type return type
end 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 def ispostop
when scan when scan
is OPEN_PAREN_TKN is OPEN_PAREN_TKN
@ -2956,6 +3028,21 @@ def ispostop
wend wend
return FALSE return FALSE
end 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) def parse_value(rvalue)
byte cparams, deref, type, emit_val byte cparams, deref, type, emit_val
word optos, idptr, value word optos, idptr, value
@ -3275,64 +3362,6 @@ def parse_value(rvalue)
fin fin
return ref_type return ref_type
end 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 def parse_expr
byte prevmatch, matchop, i byte prevmatch, matchop, i
word optos word optos