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:
parent
352bf0439c
commit
3a7a804f9b
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user