X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=src%2Foberon.c;h=8a84e1359dcd48f368f41cd945a76bb92a11b599;hb=cbfeec1f4192adbd7adb494ef79447366f051c20;hp=f2310db26de0ab2b1bffb82efee2a4b346bf7052;hpb=86c0ca1aafd465a3e0d4a9d6b1af661eba483ae1;p=dsw-obn.git diff --git a/src/oberon.c b/src/oberon.c index f2310db..8a84e13 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -61,7 +61,13 @@ enum { IMPORT, REAL, CHAR, - STRING + STRING, + IF, + THEN, + ELSE, + ELSIF, + WHILE, + DO }; // ======================================================================= @@ -380,6 +386,30 @@ oberon_read_ident(oberon_context_t * ctx) { ctx -> token = IS; } + else if(strcmp(ident, "IF") == 0) + { + ctx -> token = IF; + } + else if(strcmp(ident, "THEN") == 0) + { + ctx -> token = THEN; + } + else if(strcmp(ident, "ELSE") == 0) + { + ctx -> token = ELSE; + } + else if(strcmp(ident, "ELSIF") == 0) + { + ctx -> token = ELSIF; + } + else if(strcmp(ident, "WHILE") == 0) + { + ctx -> token = WHILE; + } + else if(strcmp(ident, "DO") == 0) + { + ctx -> token = DO; + } } static void @@ -1641,6 +1671,10 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ || b -> result -> class == OBERON_TYPE_INTEGER || a -> result -> class == OBERON_TYPE_REAL || b -> result -> class == OBERON_TYPE_REAL) + { + // accept + } + else { oberon_error(ctx, "used only with numeric types"); } @@ -2845,6 +2879,9 @@ oberon_decl_seq(oberon_context_t * ctx) oberon_prevent_undeclarated_procedures(ctx); } +static void +oberon_statement_seq(oberon_context_t * ctx); + static void oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { @@ -2877,6 +2914,78 @@ oberon_statement(oberon_context_t * ctx) oberon_opt_proc_parens(ctx, item1); } } + else if(ctx -> token == IF) + { + gen_label_t * end; + gen_label_t * els; + oberon_expr_t * cond; + + els = oberon_generator_reserve_label(ctx); + end = oberon_generator_reserve_label(ctx); + + oberon_assert_token(ctx, IF); + cond = oberon_expr(ctx); + if(cond -> result -> class != OBERON_TYPE_BOOLEAN) + { + oberon_error(ctx, "condition must be boolean"); + } + oberon_assert_token(ctx, THEN); + oberon_generate_branch(ctx, cond, false, els); + oberon_statement_seq(ctx); + oberon_generate_goto(ctx, end); + oberon_generate_label(ctx, els); + + while(ctx -> token == ELSIF) + { + els = oberon_generator_reserve_label(ctx); + + oberon_assert_token(ctx, ELSIF); + cond = oberon_expr(ctx); + if(cond -> result -> class != OBERON_TYPE_BOOLEAN) + { + oberon_error(ctx, "condition must be boolean"); + } + oberon_assert_token(ctx, THEN); + oberon_generate_branch(ctx, cond, false, els); + oberon_statement_seq(ctx); + oberon_generate_goto(ctx, end); + oberon_generate_label(ctx, els); + } + + if(ctx -> token == ELSE) + { + oberon_assert_token(ctx, ELSE); + oberon_statement_seq(ctx); + } + + oberon_generate_label(ctx, end); + oberon_assert_token(ctx, END); + } + else if(ctx -> token == WHILE) + { + gen_label_t * begin; + gen_label_t * end; + oberon_expr_t * cond; + + begin = oberon_generator_reserve_label(ctx); + end = oberon_generator_reserve_label(ctx); + + oberon_assert_token(ctx, WHILE); + oberon_generate_label(ctx, begin); + cond = oberon_expr(ctx); + if(cond -> result -> class != OBERON_TYPE_BOOLEAN) + { + oberon_error(ctx, "condition must be boolean"); + } + oberon_generate_branch(ctx, cond, false, end); + + oberon_assert_token(ctx, DO); + oberon_statement_seq(ctx); + oberon_generate_goto(ctx, begin); + + oberon_assert_token(ctx, END); + oberon_generate_label(ctx, end); + } else if(ctx -> token == RETURN) { oberon_assert_token(ctx, RETURN);