fix problem with casts immediately followed by operators

This commit is contained in:
pommicket 2022-01-27 18:00:31 -05:00
parent 539f23eaec
commit 09f3f9b450
4 changed files with 58 additions and 8 deletions

View file

@ -20,7 +20,7 @@
; b << >> ; b << >>
; c + - ; c + -
; d * / % ; d * / %
; e8 cast ; d8 cast
; e sizeof, unary prefixes ++ -- & * + - ~ ! ; e sizeof, unary prefixes ++ -- & * + - ~ !
; f . -> () [] postfix ++ -- ; f . -> () [] postfix ++ --
; highest ; highest

View file

@ -16,4 +16,4 @@ typedef struct A {
long f; long f;
} A; } A;
typedef int x[(int)&((struct A*)0)->e]; typedef int x[(unsigned)-3];

View file

@ -165,6 +165,32 @@ function token_skip_to_matching_rsquare
string Unmatched [ string Unmatched [
byte 0 byte 0
; *p_token should be on a ); this goes back to the corresponding (
; THERE MUST ACTUALLY BE A MATCHING BRACKET, OTHERWISE THIS WILL DO BAD THINGS
function token_reverse_to_matching_lparen
argument p_token
local token
local depth
token = *8p_token
depth = 0
:reverse_paren_loop
if *1token == SYMBOL_LPAREN goto reverse_paren_incdepth
if *1token == SYMBOL_RPAREN goto reverse_paren_decdepth
:reverse_paren_next
token -= 16
goto reverse_paren_loop
:reverse_paren_incdepth
depth += 1
if depth == 0 goto reverse_paren_ret
goto reverse_paren_next
:reverse_paren_decdepth
depth -= 1
goto reverse_paren_next
:reverse_paren_ret
*8p_token = token
return
; parse things like `int x` or `int f(void, int, char *)` ; parse things like `int x` or `int f(void, int, char *)`
; advances *p_token ; advances *p_token
; returns type ID, or 0, in which case you should look at parse_type_result ; returns type ID, or 0, in which case you should look at parse_type_result
@ -863,7 +889,7 @@ function parse_expression
local first_token local first_token
:parse_expression_top :parse_expression_top
print_tokens(tokens, tokens_end) ;print_tokens(tokens, tokens_end)
type = out + 4 type = out + 4
@ -929,6 +955,13 @@ function parse_expression
if n > best_precedence goto expr_findop_not_new_best if n > best_precedence goto expr_findop_not_new_best
; new best! ; new best!
best = p - 16 best = p - 16
;putc('O)
;putc(':)
;putn(*1best)
;putc(32)
;putc('P)
;putc(':)
;putnln(a)
best_precedence = a best_precedence = a
:expr_findop_not_new_best :expr_findop_not_new_best
if c == SYMBOL_LPAREN goto expr_findop_incdepth if c == SYMBOL_LPAREN goto expr_findop_incdepth
@ -1913,6 +1946,7 @@ function operator_precedence
argument token argument token
argument is_first argument is_first
local op local op
local b
if is_first != 0 goto operator_precedence_unary if is_first != 0 goto operator_precedence_unary
@ -1920,12 +1954,16 @@ function operator_precedence
; in 5 + *x, * is a unary operator ; in 5 + *x, * is a unary operator
op = token - 16 op = token - 16
op = *1op op = *1op
if op == SYMBOL_RPAREN goto figre_out_rparen_arity
op = is_operator(op) op = is_operator(op)
; if an operator is immediately followed by another (including lparen), the second must be
; unary.
if op != 0 goto operator_precedence_unary if op != 0 goto operator_precedence_unary
:operator_precedence_binary
op = *1token op = *1token
; see "C OPERATOR PRECEDENCE" in constants.b ; see "C OPERATOR PRECEDENCE" in constants.b
if op == SYMBOL_COMMA goto return_0x10 if op == SYMBOL_COMMA goto return_0x10
if op == SYMBOL_EQ goto return_0x20 if op == SYMBOL_EQ goto return_0x20
@ -1989,10 +2027,22 @@ function operator_precedence
; and - (int)x->something ; and - (int)x->something
; correctly (in the first case, the arrow is the top-level operator, but in the second, the cast is) ; correctly (in the first case, the arrow is the top-level operator, but in the second, the cast is)
token += 16 token += 16
local b
b = token_is_type(token) b = token_is_type(token)
if b == 0 goto return_0xffff if b == 0 goto return_0xffff
goto return_0xe8 ; it's a cast goto return_0xd8 ; it's a cast
:figre_out_rparen_arity
; given that the token before this one is a right-parenthesis, figure out if
; this is a unary or binary operator. this is (annoyingly) necessary, because:
; (int)-x; /* cast processed first */
; (y)-x; /* subtraction processed first */
local p
p = token - 16
token_reverse_to_matching_lparen(&p)
p += 16
b = token_is_type(p)
if b != 0 goto operator_precedence_unary ; e.g. (int)-x;
goto operator_precedence_binary ; e.g. (y)-x;
function unary_op_to_expression_type function unary_op_to_expression_type
argument op argument op

View file

@ -728,10 +728,10 @@ function leftmost_1bit
return 0xc0 return 0xc0
:return_0xd0 :return_0xd0
return 0xd0 return 0xd0
:return_0xd8
return 0xd8
:return_0xe0 :return_0xe0
return 0xe0 return 0xe0
:return_0xe8
return 0xe8
:return_0xf0 :return_0xf0
return 0xf0 return 0xf0
:return_0xffff :return_0xffff