1
0
mirror of https://github.com/dschmenk/PLASMA.git synced 2024-07-05 04:28:57 +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];
}
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;

View File

@ -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