structs mostly working
This commit is contained in:
parent
d036dcc5ac
commit
539f23eaec
4 changed files with 84 additions and 37 deletions
|
@ -134,7 +134,8 @@
|
||||||
; - for unary operators, the operand
|
; - for unary operators, the operand
|
||||||
; - for casts, the operand (type is given by type member)
|
; - for casts, the operand (type is given by type member)
|
||||||
; - for binary operators, the first operand followed by the second
|
; - for binary operators, the first operand followed by the second
|
||||||
; - 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 operators . and ->, the first argument is the expression on the left-hand side, and the second argument is a 64-bit offset.
|
||||||
|
; we could use a 32-bit offset but that would cause things to be unaligned.
|
||||||
; - for the ternary operator ? :, the first followed by the second followed by the third
|
; - 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
|
; - 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.
|
; Note that file/line number are not stored in expressions.
|
||||||
|
@ -685,3 +686,6 @@
|
||||||
:str_union
|
:str_union
|
||||||
string union
|
string union
|
||||||
byte 0
|
byte 0
|
||||||
|
:str_typedef ; currently only used for nice debug output
|
||||||
|
string typedef
|
||||||
|
byte 0
|
||||||
|
|
|
@ -13,7 +13,7 @@ typedef struct A {
|
||||||
long double c;
|
long double c;
|
||||||
unsigned long d;
|
unsigned long d;
|
||||||
char e[3];
|
char e[3];
|
||||||
char c[2];
|
|
||||||
char d;
|
|
||||||
long f;
|
long f;
|
||||||
} A;
|
} A;
|
||||||
|
|
||||||
|
typedef int x[(int)&((struct A*)0)->e];
|
||||||
|
|
109
05/parse.b
109
05/parse.b
|
@ -61,20 +61,22 @@ function parse_tokens
|
||||||
suffix = prefix_end + 16
|
suffix = prefix_end + 16
|
||||||
suffix_end = type_get_suffix_end(prefix)
|
suffix_end = type_get_suffix_end(prefix)
|
||||||
|
|
||||||
putc('B)
|
;putc('B)
|
||||||
putc(':)
|
;putc(':)
|
||||||
print_tokens(base_type, base_type_end)
|
;print_tokens(base_type, base_type_end)
|
||||||
putc('P)
|
;putc('P)
|
||||||
putc(':)
|
;putc(':)
|
||||||
print_tokens(prefix, prefix_end)
|
;print_tokens(prefix, prefix_end)
|
||||||
putc('S)
|
;putc('S)
|
||||||
putc(':)
|
;putc(':)
|
||||||
print_tokens(suffix, suffix_end)
|
;print_tokens(suffix, suffix_end)
|
||||||
|
|
||||||
type = types_bytes_used
|
type = types_bytes_used
|
||||||
parse_type_declarators(prefix, prefix_end, suffix, suffix_end)
|
parse_type_declarators(prefix, prefix_end, suffix, suffix_end)
|
||||||
parse_base_type(base_type)
|
parse_base_type(base_type)
|
||||||
|
|
||||||
|
puts(.str_typedef)
|
||||||
|
putc(32)
|
||||||
print_type(type)
|
print_type(type)
|
||||||
putc(10)
|
putc(10)
|
||||||
|
|
||||||
|
@ -322,14 +324,11 @@ function parse_type_declarators
|
||||||
*1out = TYPE_ARRAY
|
*1out = TYPE_ARRAY
|
||||||
types_bytes_used += 1
|
types_bytes_used += 1
|
||||||
|
|
||||||
local prev_types
|
|
||||||
local prev_types_bytes_used
|
|
||||||
; little hack to avoid screwing up types like double[sizeof(int)]
|
; little hack to avoid screwing up types like double[sizeof(int)]
|
||||||
; temporarily switch out types array to parse the cast's type
|
; temporarily pretend we're using a lot more of types
|
||||||
prev_types = types
|
local prev_types_bytes_used
|
||||||
prev_types_bytes_used = types_bytes_used
|
prev_types_bytes_used = types_bytes_used
|
||||||
types = malloc(4000)
|
types_bytes_used += 4000
|
||||||
types_init(types, &types_bytes_used)
|
|
||||||
|
|
||||||
expr = malloc(4000)
|
expr = malloc(4000)
|
||||||
p = suffix
|
p = suffix
|
||||||
|
@ -341,8 +340,7 @@ function parse_type_declarators
|
||||||
evaluate_constant_expression(prefix, expr, &n)
|
evaluate_constant_expression(prefix, expr, &n)
|
||||||
if n < 0 goto bad_array_size
|
if n < 0 goto bad_array_size
|
||||||
free(expr)
|
free(expr)
|
||||||
free(types)
|
|
||||||
types = prev_types
|
|
||||||
types_bytes_used = prev_types_bytes_used
|
types_bytes_used = prev_types_bytes_used
|
||||||
|
|
||||||
out = types + types_bytes_used
|
out = types + types_bytes_used
|
||||||
|
@ -606,6 +604,10 @@ function parse_base_type
|
||||||
if *1member_prefix_end != TOKEN_IDENTIFIER goto member_no_identifier
|
if *1member_prefix_end != TOKEN_IDENTIFIER goto member_no_identifier
|
||||||
member_name = member_prefix_end + 8
|
member_name = member_prefix_end + 8
|
||||||
member_name = *8member_name
|
member_name = *8member_name
|
||||||
|
|
||||||
|
c = ident_list_lookup_check(struct, member_name, 0)
|
||||||
|
if c == 1 goto duplicate_member
|
||||||
|
|
||||||
member_suffix = member_prefix_end + 16
|
member_suffix = member_prefix_end + 16
|
||||||
member_suffix_end = type_get_suffix_end(member_prefix)
|
member_suffix_end = type_get_suffix_end(member_prefix)
|
||||||
member_type = types_bytes_used
|
member_type = types_bytes_used
|
||||||
|
@ -635,6 +637,11 @@ function parse_base_type
|
||||||
if *1p != SYMBOL_COMMA goto struct_bad_declaration
|
if *1p != SYMBOL_COMMA goto struct_bad_declaration
|
||||||
p += 16 ; skip comma
|
p += 16 ; skip comma
|
||||||
goto struct_defn_decl_loop
|
goto struct_defn_decl_loop
|
||||||
|
:duplicate_member
|
||||||
|
token_error(p, .str_duplicate_member)
|
||||||
|
:str_duplicate_member
|
||||||
|
string Duplicate member in struct/union.
|
||||||
|
byte 0
|
||||||
:struct_defn_decl_loop_end
|
:struct_defn_decl_loop_end
|
||||||
p += 16 ; skip semicolon
|
p += 16 ; skip semicolon
|
||||||
goto struct_defn_loop
|
goto struct_defn_loop
|
||||||
|
@ -856,7 +863,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
|
||||||
|
|
||||||
|
@ -944,7 +951,7 @@ function parse_expression
|
||||||
n = best - tokens
|
n = best - tokens
|
||||||
|
|
||||||
c = *1best
|
c = *1best
|
||||||
|
|
||||||
if best == tokens goto parse_expr_unary
|
if best == tokens goto parse_expr_unary
|
||||||
|
|
||||||
; it's a binary expression.
|
; it's a binary expression.
|
||||||
|
@ -1206,16 +1213,41 @@ function parse_expression
|
||||||
:parse_expr_member ; -> or .
|
:parse_expr_member ; -> or .
|
||||||
p = best + 16
|
p = best + 16
|
||||||
if *1p != TOKEN_IDENTIFIER goto bad_expression
|
if *1p != TOKEN_IDENTIFIER goto bad_expression
|
||||||
|
|
||||||
|
a = out + 4 ; pointer to type ID
|
||||||
|
out = parse_expression(tokens, best, out)
|
||||||
|
a = types + *4a
|
||||||
|
if c == EXPRESSION_DOT goto type_dot
|
||||||
|
if *1a != TYPE_POINTER goto arrow_non_pointer
|
||||||
|
a += 1
|
||||||
|
:type_dot
|
||||||
|
if *1a != TYPE_STRUCT goto member_non_struct
|
||||||
|
a += 1
|
||||||
|
a = *8a ; pointer to struct data
|
||||||
p += 8
|
p += 8
|
||||||
*8out = *8p ; copy identifier name
|
c = ident_list_lookup(a, *8p)
|
||||||
|
if c == 0 goto member_not_in_struct
|
||||||
|
*8out = c & 0xffffffff ; offset
|
||||||
|
*4type = c > 32 ; type
|
||||||
|
out += 8
|
||||||
p += 8
|
p += 8
|
||||||
if p != tokens_end goto bad_expression ; e.g. foo->bar hello
|
if p != tokens_end goto bad_expression ; e.g. foo->bar hello
|
||||||
out += 8
|
|
||||||
out = parse_expression(tokens, best, out)
|
|
||||||
; @TODO: typing
|
|
||||||
return out
|
return out
|
||||||
|
:arrow_non_pointer
|
||||||
|
token_error(p, .str_arrow_non_pointer)
|
||||||
|
:str_arrow_non_pointer
|
||||||
|
string Trying to use -> operator on a non-pointer type.
|
||||||
|
byte 0
|
||||||
|
:member_non_struct
|
||||||
|
token_error(p, .str_member_non_struct)
|
||||||
|
:str_member_non_struct
|
||||||
|
string Trying to access member of something other than a (complete) structure/union.
|
||||||
|
byte 0
|
||||||
|
:member_not_in_struct
|
||||||
|
token_error(p, .str_member_not_in_struct)
|
||||||
|
:str_member_not_in_struct
|
||||||
|
string Trying to access non-existent member of structure or union.
|
||||||
|
byte 0
|
||||||
:parse_conditional
|
:parse_conditional
|
||||||
depth = 0 ; bracket depth
|
depth = 0 ; bracket depth
|
||||||
n = 0 ; ? : depth
|
n = 0 ; ? : depth
|
||||||
|
@ -1947,10 +1979,21 @@ function operator_precedence
|
||||||
if op == SYMBOL_MINUS goto return_0xe0
|
if op == SYMBOL_MINUS goto return_0xe0
|
||||||
if op == SYMBOL_TILDE goto return_0xe0
|
if op == SYMBOL_TILDE goto return_0xe0
|
||||||
if op == SYMBOL_NOT goto return_0xe0
|
if op == SYMBOL_NOT goto return_0xe0
|
||||||
if op == SYMBOL_LPAREN goto return_0xe8 ; casts
|
if op == SYMBOL_LPAREN goto cast_precedence
|
||||||
|
|
||||||
return 0xffff
|
return 0xffff
|
||||||
|
:cast_precedence
|
||||||
|
; make sure this actually is a cast
|
||||||
|
; this is necessary to handle both
|
||||||
|
; - (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)
|
||||||
|
token += 16
|
||||||
|
local b
|
||||||
|
b = token_is_type(token)
|
||||||
|
if b == 0 goto return_0xffff
|
||||||
|
goto return_0xe8 ; it's a cast
|
||||||
|
|
||||||
function unary_op_to_expression_type
|
function unary_op_to_expression_type
|
||||||
argument op
|
argument op
|
||||||
if op == SYMBOL_PLUS_PLUS goto return_EXPRESSION_PRE_INCREMENT
|
if op == SYMBOL_PLUS_PLUS goto return_EXPRESSION_PRE_INCREMENT
|
||||||
|
@ -2194,21 +2237,19 @@ function print_expression
|
||||||
:print_expr_dot
|
:print_expr_dot
|
||||||
putc(40)
|
putc(40)
|
||||||
expression += 8
|
expression += 8
|
||||||
p = *8expression
|
|
||||||
expression += 8
|
|
||||||
expression = print_expression(expression)
|
expression = print_expression(expression)
|
||||||
putc('.)
|
puts(.str_dot)
|
||||||
puts(p)
|
putn(*8expression)
|
||||||
|
expression += 8
|
||||||
putc(41)
|
putc(41)
|
||||||
return expression
|
return expression
|
||||||
:print_expr_arrow
|
:print_expr_arrow
|
||||||
putc(40)
|
putc(40)
|
||||||
expression += 8
|
expression += 8
|
||||||
p = *8expression
|
|
||||||
expression += 8
|
|
||||||
expression = print_expression(expression)
|
expression = print_expression(expression)
|
||||||
puts(.str_arrow)
|
puts(.str_arrow)
|
||||||
puts(p)
|
putn(*8expression)
|
||||||
|
expression += 8
|
||||||
putc(41)
|
putc(41)
|
||||||
return expression
|
return expression
|
||||||
:print_post_increment
|
:print_post_increment
|
||||||
|
|
|
@ -734,6 +734,8 @@ function leftmost_1bit
|
||||||
return 0xe8
|
return 0xe8
|
||||||
:return_0xf0
|
:return_0xf0
|
||||||
return 0xf0
|
return 0xf0
|
||||||
|
:return_0xffff
|
||||||
|
return 0xffff
|
||||||
|
|
||||||
function syscall
|
function syscall
|
||||||
; I've done some testing, and this should be okay even if
|
; I've done some testing, and this should be okay even if
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue