summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--05/constants.b2
-rw-r--r--05/main.c4
-rw-r--r--05/parse.b79
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
diff --git a/05/main.c b/05/main.c
index 8fa4dbd..c3f5138 100644
--- a/05/main.c
+++ b/05/main.c
@@ -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);
diff --git a/05/parse.b b/05/parse.b
index 40f2a30..767f749 100644
--- a/05/parse.b
+++ b/05/parse.b
@@ -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