diff options
-rw-r--r-- | 05/constants.b | 2 | ||||
-rw-r--r-- | 05/main.c | 4 | ||||
-rw-r--r-- | 05/parse.b | 79 |
3 files changed, 85 insertions, 0 deletions
diff --git a/05/constants.b b/05/constants.b index 73e321a..730aff0 100644 --- a/05/constants.b +++ b/05/constants.b @@ -275,6 +275,7 @@ ; - STATEMENT_BREAK - data1,2,3,4 are unused ; - STATEMENT_RETURN - data1 is a pointer to the expression, or 0 if there is none; data2,3,4 are unused ; - STATEMENT_CASE - data1 is the value; data2,3,4 are unused +; - STATEMENT_NOOP - data1,2,3,4 are unused #define STATEMENT_EXPRESSION 1 #define STATEMENT_LOCAL_DECLARATION 2 #define STATEMENT_LABEL 3 @@ -289,6 +290,7 @@ #define STATEMENT_BREAK 0xc #define STATEMENT_RETURN 0xd #define STATEMENT_CASE 0xe +#define STATEMENT_NOOP 0xf :keyword_table @@ -1,6 +1,10 @@ static int g; int f(void) { + while (g+10 == 17){ + while (g+100==1234){ + } + } lbl1:break;;goto blah; case -1-3: continue;a:break;return;return 6+3<<sizeof(int); @@ -348,6 +348,7 @@ function parse_statement if c == KEYWORD_CASE goto stmt_case if c == KEYWORD_STATIC goto stmt_static_declaration if c == KEYWORD_EXTERN goto stmt_extern_declaration + if c == KEYWORD_WHILE goto stmt_while b = token_is_type(token) if b != 0 goto stmt_local_declaration @@ -366,6 +367,35 @@ function parse_statement ; @NONSTANDARD string Local extern declarations are not supported. byte 0 + :stmt_while + write_statement_header(out, STATEMENT_WHILE, token) + token += 16 + if *1token != SYMBOL_LPAREN goto while_no_lparen + p = token_matching_rparen(token) + token += 16 + out += 8 + *8out = expressions_end + expressions_end = parse_expression(token, p, expressions_end) + token = p + 16 + out += 8 + + ; put the while statement 1 block_depth deeper + p = statement_datas + p += block_depth < 3 + block_depth += 1 + if block_depth >= BLOCK_DEPTH_LIMIT goto too_much_nesting + *8out = *8p + out += 24 + c = *8p + parse_statement(&token, p) ; the body + block_depth -= 1 + + goto parse_statement_ret + :while_no_lparen + token_error(token, .str_while_no_lparen) + :str_while_no_lparen + string No ( after while. + byte 0 :stmt_local_declaration local l_base_type local l_prefix @@ -558,6 +588,8 @@ function parse_statement string No semicolon after goto. byte 0 :stmt_block + local Z + Z = out write_statement_header(out, STATEMENT_BLOCK, token) out += 8 @@ -607,6 +639,9 @@ function parse_statement byte 0 :stmt_empty ; empty statement, e.g. while(something)-> ; <- + ; we do have to output a statement here because otherwise that kind of thing would be screwed up + write_statement_header(out, STATEMENT_NOOP, token) + out += 40 token += 16 ; skip semicolon goto parse_statement_ret @@ -645,6 +680,7 @@ function print_statement_with_depth dat4 = statement + 32 dat4 = *8dat4 + if c == STATEMENT_NOOP goto print_stmt_noop if c == STATEMENT_BLOCK goto print_stmt_block if c == STATEMENT_CONTINUE goto print_stmt_continue if c == STATEMENT_BREAK goto print_stmt_break @@ -652,6 +688,7 @@ function print_statement_with_depth if c == STATEMENT_GOTO goto print_stmt_goto if c == STATEMENT_LABEL goto print_stmt_label if c == STATEMENT_CASE goto print_stmt_case + if c == STATEMENT_WHILE goto print_stmt_while if c == STATEMENT_LOCAL_DECLARATION goto print_stmt_local_decl die(.pristmtNI) @@ -666,6 +703,19 @@ function print_statement_with_depth puts(dat1) putcln(':) return + :print_stmt_noop + putcln(59) + return + :print_stmt_while + puts(.str_stmt_while) + putc(40) + print_expression(dat1) + putcln(41) + print_statement_with_depth(dat2, depth) + return + :str_stmt_while + string while ( + byte 0 :print_stmt_break puts(.str_stmt_break) return @@ -1105,6 +1155,35 @@ function token_skip_to_matching_rsquare string Unmatched [ byte 0 +; token should be pointing to (, this returns the corresponding ) +function token_matching_rparen + argument token + local token0 + local depth + token0 = token + depth = 0 + :matching_rparen_loop + if *1token == SYMBOL_LPAREN goto matching_rparen_incdepth + if *1token == SYMBOL_RPAREN goto matching_rparen_decdepth + if *1token == TOKEN_EOF goto matching_rparen_eof + :matching_rparen_next + token += 16 + goto matching_rparen_loop + :matching_rparen_incdepth + depth += 1 + goto matching_rparen_next + :matching_rparen_decdepth + depth -= 1 + if depth == 0 goto matching_rparen_ret + goto matching_rparen_next + :matching_rparen_ret + return token + + :matching_rparen_eof + token_error(token0, .str_matching_rparen_eof) + :str_matching_rparen_eof + string Unmatched ( + 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 |