binop parsing working

This commit is contained in:
pommicket 2022-01-13 23:20:45 -05:00
parent 251c25cbad
commit 05cbc58299
3 changed files with 84 additions and 10 deletions

View file

@ -133,7 +133,7 @@
; - for string literals, a 64-bit pointer to the string (for the executable, not for the compiler)
; - for unary operators, the operand
; - for binary operators, the first operand followed by the second
; - for the operators . and ->, the first operand is an expression and the second is just a pointer to the name of the member
; - for the operators . and ->, the first argument is a 64-bit pointer to the name of the member and the second is the left hand side of the . / ->
; - for the ternary operator ? :, the first followed by the second followed by the third
; - for function calls, the function, followed by each of the arguments to the function — info indicates the number of arguments
; Note that file/line number are not stored in expressions.

View file

@ -1 +1 @@
(3+5)*6-8
(3+6).c*5---8--/3l->blah++

View file

@ -53,7 +53,10 @@ function parse_expression
p = tokens
best = 0
best_precedence = 1000
goto expr_find_operator_loop_first
:expr_find_operator_loop
b = 0
:expr_find_operator_loop_first
if p >= tokens_end goto expr_find_operator_loop_end
c = *1p
p += 16
@ -66,7 +69,7 @@ function parse_expression
a = operator_precedence(c, b)
n = a
n -= operator_right_associative(c) ; ensure that the leftmost += / -= / etc. is processed first
if n >= best_precedence goto expr_find_operator_loop
if n > best_precedence goto expr_find_operator_loop
; new best!
best = p - 16
best_precedence = a
@ -90,9 +93,9 @@ function parse_expression
if c == SYMBOL_QUESTION goto parse_conditional
*1out = binop_symbol_to_expression_type(c)
out += 8
out = parse_expression(tokens, best, out) ; first operand
if c == SYMBOL_DOT goto parse_expr_member
if c == SYMBOL_ARROW goto parse_expr_member
out = parse_expression(tokens, best, out) ; first operand
p = best + 16
out = parse_expression(p, tokens_end, out) ; second operand
return out
@ -107,15 +110,34 @@ function parse_expression
byte 0xcc ; @TODO
:parse_expr_member ; -> or .
byte 0xcc ; @TODO
p = best + 16
if *1p != TOKEN_IDENTIFIER goto bad_expression
p += 8
*8out = *8p ; copy identifier name
p += 8
if p != tokens_end goto bad_expression ; e.g. foo->bar hello
out += 8
out = parse_expression(tokens, best, out)
return out
:parse_conditional
byte 0xcc ; @TODO
:parse_postincrement
byte 0xcc ; @TODO
*1out = EXPRESSION_POST_INCREMENT
out += 8
p = tokens_end - 16
if *1p != SYMBOL_PLUS_PLUS goto bad_expression ; e.g. a ++ b
out = parse_expression(tokens, p, out)
return out
:parse_postdecrement
byte 0xcc ; @TODO
*1out = EXPRESSION_POST_DECREMENT
out += 8
p = tokens_end - 16
if *1p != SYMBOL_MINUS_MINUS goto bad_expression ; e.g. a -- b
out = parse_expression(tokens, p, out)
return out
:single_token_expression
in = tokens
@ -124,7 +146,7 @@ function parse_expression
if c == TOKEN_CONSTANT_CHAR goto expression_integer ; character constants are basically the same as integer constants
if c == TOKEN_CONSTANT_FLOAT goto expression_float
if c == TOKEN_STRING_LITERAL goto expression_string_literal
byte 0xcc
goto unrecognized_expression
:expression_integer
*1out = EXPRESSION_CONSTANT_INT
@ -183,6 +205,11 @@ function parse_expression
:str_empty_expression
string Empty expression.
byte 0
:bad_expression
token_error(tokens, .str_bad_expression)
:str_bad_expression
string Bad expression.
byte 0
:unrecognized_expression
token_error(tokens, .str_unrecognized_expression)
:str_unrecognized_expression
@ -409,9 +436,21 @@ function print_expression
if c == EXPRESSION_CONSTANT_INT goto print_expr_int
if c == EXPRESSION_CONSTANT_FLOAT goto print_expr_float
if c == EXPRESSION_STRING_LITERAL goto print_expr_str
if c == EXPRESSION_POST_INCREMENT goto print_post_increment
if c == EXPRESSION_POST_DECREMENT goto print_post_decrement
if c == EXPRESSION_DOT goto print_expr_dot
if c == EXPRESSION_ARROW goto print_expr_arrow
b = binop_expression_type_to_symbol(c)
if b != 0 goto print_expr_binop
byte 0xcc
puts(.str_print_bad_expr)
exit(1)
:str_print_bad_expr
string Bad expression passed to print_expression.
byte 10
byte 0
:print_expr_int
expression += 8
putn(*8expression)
@ -438,7 +477,42 @@ function print_expression
expression = print_expression(expression) ; 2nd operand
putc(41)
return expression
:print_expr_dot
putc(40)
expression += 8
p = *8expression
expression += 8
expression = print_expression(expression)
putc('.)
puts(p)
putc(41)
return expression
:print_expr_arrow
putc(40)
expression += 8
p = *8expression
expression += 8
expression = print_expression(expression)
puts(.str_arrow)
puts(p)
putc(41)
return expression
:print_post_increment
putc(40)
expression += 8
expression = print_expression(expression)
putc('+)
putc('+)
putc(41)
return expression
:print_post_decrement
putc(40)
expression += 8
expression = print_expression(expression)
putc('-)
putc('-)
putc(41)
return expression
; NOTE: to make things easier, the format which this outputs isn't the same as C's, specifically we have
; *int for pointer to int and [5]int for array of 5 ints