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];
|
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;
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user