fix problem with casts immediately followed by operators
This commit is contained in:
parent
539f23eaec
commit
09f3f9b450
4 changed files with 58 additions and 8 deletions
|
@ -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
|
||||||
|
|
|
@ -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];
|
||||||
|
|
58
05/parse.b
58
05/parse.b
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue