parsing break, continue, return
This commit is contained in:
parent
d1167f03d0
commit
dfce9118b9
6 changed files with 196 additions and 13 deletions
173
05/parse.b
173
05/parse.b
|
@ -173,13 +173,13 @@ function parse_tokens
|
|||
global function_stmt_data ; initialized in main
|
||||
global function_stmt_data_bytes_used
|
||||
|
||||
n = function_stmt_data_bytes_used
|
||||
out = function_stmt_data + function_stmt_data_bytes_used
|
||||
p = function_stmt_data + function_stmt_data_bytes_used
|
||||
out = p
|
||||
parse_statement(&token, &out)
|
||||
if parse_stmt_depth != 0 goto stmtdepth_internal_err
|
||||
function_stmt_data_bytes_used = out - function_stmt_data
|
||||
|
||||
ident_list_add(function_statements, name, n)
|
||||
ident_list_add(function_statements, name, p)
|
||||
print_statement(p)
|
||||
goto parse_tokens_loop
|
||||
|
||||
:stmtdepth_internal_err
|
||||
|
@ -304,6 +304,9 @@ function parse_statement
|
|||
c = *1token
|
||||
if c == SYMBOL_SEMICOLON goto stmt_empty
|
||||
if c == SYMBOL_LBRACE goto stmt_block
|
||||
if c == KEYWORD_BREAK goto stmt_break
|
||||
if c == KEYWORD_CONTINUE goto stmt_continue
|
||||
if c == KEYWORD_RETURN goto stmt_return
|
||||
|
||||
token_error(token, .str_unrecognized_statement)
|
||||
:str_unrecognized_statement
|
||||
|
@ -313,6 +316,42 @@ function parse_statement
|
|||
*8p_token = token
|
||||
*8p_out = out
|
||||
return
|
||||
:stmt_break
|
||||
token += 16
|
||||
if *1token != SYMBOL_SEMICOLON goto break_no_semicolon
|
||||
token += 16
|
||||
write_statement_header(out, STATEMENT_BREAK, token)
|
||||
out += 40
|
||||
goto parse_statement_ret
|
||||
:break_no_semicolon
|
||||
token_error(token, .str_break_no_semicolon)
|
||||
:str_break_no_semicolon
|
||||
string No semicolon after break.
|
||||
byte 0
|
||||
:stmt_continue
|
||||
token += 16
|
||||
if *1token != SYMBOL_SEMICOLON goto continue_no_semicolon
|
||||
token += 16
|
||||
write_statement_header(out, STATEMENT_CONTINUE, token)
|
||||
out += 40
|
||||
goto parse_statement_ret
|
||||
:continue_no_semicolon
|
||||
token_error(token, .str_continue_no_semicolon)
|
||||
:str_continue_no_semicolon
|
||||
string No semicolon after continue.
|
||||
byte 0
|
||||
:stmt_return
|
||||
write_statement_header(out, STATEMENT_RETURN, token)
|
||||
out += 8
|
||||
token += 16
|
||||
if *1token == SYMBOL_SEMICOLON goto return_no_expr
|
||||
n = token_next_semicolon_not_in_brackets(token)
|
||||
*8out = expressions_end
|
||||
expressions_end = parse_expression(token, n, expressions_end)
|
||||
token = n + 16
|
||||
:return_no_expr
|
||||
out += 32
|
||||
goto parse_statement_ret
|
||||
:stmt_block
|
||||
local block_p_out
|
||||
; find the appropriate statement data to use for this block's body
|
||||
|
@ -356,6 +395,92 @@ function parse_statement
|
|||
token += 16 ; skip semicolon
|
||||
goto parse_statement_ret
|
||||
|
||||
function print_statement
|
||||
argument statement
|
||||
print_statement_with_depth(statement, 0)
|
||||
return
|
||||
|
||||
function print_statement_with_depth
|
||||
argument statement
|
||||
argument depth
|
||||
local c
|
||||
local dat1
|
||||
local dat2
|
||||
local dat3
|
||||
local dat4
|
||||
|
||||
c = depth
|
||||
:print_stmt_indent_loop
|
||||
if c == 0 goto print_stmt_indent_loop_end
|
||||
putc(9) ; tab
|
||||
c -= 1
|
||||
goto print_stmt_indent_loop
|
||||
:print_stmt_indent_loop_end
|
||||
|
||||
c = *1statement
|
||||
dat1 = statement + 8
|
||||
dat1 = *8dat1
|
||||
dat2 = statement + 16
|
||||
dat2 = *8dat2
|
||||
dat3 = statement + 24
|
||||
dat3 = *8dat3
|
||||
dat4 = statement + 32
|
||||
dat4 = *8dat4
|
||||
|
||||
if c == STATEMENT_LABEL goto print_stmt_label
|
||||
if c == STATEMENT_BLOCK goto print_stmt_block
|
||||
if c == STATEMENT_CONTINUE goto print_stmt_continue
|
||||
if c == STATEMENT_BREAK goto print_stmt_break
|
||||
if c == STATEMENT_RETURN goto print_stmt_return
|
||||
|
||||
die(.pristmtNI)
|
||||
:pristmtNI
|
||||
string print_statement not implemented.
|
||||
byte 0
|
||||
:str_semicolon_newline
|
||||
byte 59
|
||||
byte 10
|
||||
byte 0
|
||||
:print_stmt_label
|
||||
puts(dat1)
|
||||
putcln(':)
|
||||
return
|
||||
:print_stmt_break
|
||||
puts(.str_stmt_break)
|
||||
return
|
||||
:str_stmt_break
|
||||
string break
|
||||
byte 59 ; semicolon
|
||||
byte 10
|
||||
byte 0
|
||||
:print_stmt_continue
|
||||
puts(.str_stmt_continue)
|
||||
return
|
||||
:str_stmt_continue
|
||||
string continue
|
||||
byte 59 ; semicolon
|
||||
byte 10
|
||||
byte 0
|
||||
:print_stmt_return
|
||||
puts(.str_return)
|
||||
if dat1 == 0 goto print_ret_noexpr
|
||||
putc(32)
|
||||
print_expression(dat1)
|
||||
:print_ret_noexpr
|
||||
puts(.str_semicolon_newline)
|
||||
return
|
||||
:print_stmt_block
|
||||
putcln('{)
|
||||
depth += 1
|
||||
:print_block_loop
|
||||
if *1dat1 == 0 goto print_block_loop_end
|
||||
print_statement_with_depth(dat1, depth)
|
||||
dat1 += 40
|
||||
goto print_block_loop
|
||||
:print_block_loop_end
|
||||
putcln('})
|
||||
return
|
||||
|
||||
; parse a global variable's initializer
|
||||
; e.g. int x[5] = {1+8, 2, 3, 4, 5};
|
||||
; advances *p_token to the token right after the initializer
|
||||
|
@ -741,6 +866,43 @@ function token_reverse_to_matching_lparen
|
|||
return
|
||||
|
||||
|
||||
; return the next semicolon not in parentheses, square brackets, or braces.
|
||||
function token_next_semicolon_not_in_brackets
|
||||
argument token0
|
||||
|
||||
local token
|
||||
local depth
|
||||
local c
|
||||
|
||||
depth = 0
|
||||
token = token0
|
||||
:next_semicolon_loop
|
||||
c = *1token
|
||||
if c == TOKEN_EOF goto next_semicolon_eof
|
||||
if depth != 0 goto next_semicolon_nocheck
|
||||
if c == SYMBOL_SEMICOLON goto next_semicolon_loop_end
|
||||
:next_semicolon_nocheck
|
||||
token += 16
|
||||
if c == SYMBOL_LPAREN goto next_semicolon_incdepth
|
||||
if c == SYMBOL_RPAREN goto next_semicolon_decdepth
|
||||
if c == SYMBOL_LSQUARE goto next_semicolon_incdepth
|
||||
if c == SYMBOL_RSQUARE goto next_semicolon_decdepth
|
||||
if c == SYMBOL_LBRACE goto next_semicolon_incdepth
|
||||
if c == SYMBOL_RBRACE goto next_semicolon_decdepth
|
||||
goto next_semicolon_loop
|
||||
:next_semicolon_incdepth
|
||||
depth += 1
|
||||
goto next_semicolon_loop
|
||||
:next_semicolon_decdepth
|
||||
depth -= 1
|
||||
goto next_semicolon_loop
|
||||
:next_semicolon_loop_end
|
||||
return token
|
||||
:next_semicolon_eof
|
||||
token_error(token0, .str_next_semicolon_eof)
|
||||
:str_next_semicolon_eof
|
||||
string End of file found while searching for semicolon.
|
||||
byte 0
|
||||
; we split types into base (B), prefix (P) and suffix (S)
|
||||
; struct Thing (*things[5])(void), *something_else[3];
|
||||
; BBBBBBBBBBBB PP SSSSSSSSSS P SSS
|
||||
|
@ -1426,7 +1588,8 @@ function type_create_pointer
|
|||
p = id + 1
|
||||
types_bytes_used += type_copy_ids(p, type)
|
||||
return id
|
||||
|
||||
|
||||
; returns pointer to end of expression data
|
||||
function parse_expression
|
||||
argument tokens
|
||||
argument tokens_end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue