DEADSOFTWARE

Добавлена конструкция LOOP/EXIT
[dsw-obn.git] / src / oberon.c
index f50f4d300246b4beed4fd6e58afaf21cb307cf3a..e95a9bef396271f68b2dff5a6af06147cc530c09 100644 (file)
@@ -71,7 +71,9 @@ enum {
        REPEAT,
        UNTIL,
        FOR,
-       BY
+       BY,
+       LOOP,
+       EXIT
 };
 
 // =======================================================================
@@ -165,6 +167,7 @@ oberon_open_scope(oberon_context_t * ctx)
                scope -> local = scope -> up -> local;
                scope -> parent = scope -> up -> parent;
                scope -> parent_type = scope -> up -> parent_type;
+               scope -> exit_label = scope -> up -> exit_label;
        }
 
        ctx -> decl = scope;
@@ -437,6 +440,14 @@ oberon_read_ident(oberon_context_t * ctx)
        {
                ctx -> token = BY;
        }
+       else if(strcmp(ident, "LOOP") == 0)
+       {
+               ctx -> token = LOOP;
+       }
+       else if(strcmp(ident, "EXIT") == 0)
+       {
+               ctx -> token = EXIT;
+       }
 }
 
 static void
@@ -3160,6 +3171,33 @@ oberon_statement(oberon_context_t * ctx)
                oberon_generate_label(ctx, end);
                oberon_assert_token(ctx, END);
        }
+       else if(ctx -> token == LOOP)
+       {
+               gen_label_t * begin;
+               gen_label_t * end;
+
+               begin = oberon_generator_reserve_label(ctx);
+               end = oberon_generator_reserve_label(ctx);
+
+               oberon_open_scope(ctx);
+               oberon_assert_token(ctx, LOOP);
+               oberon_generate_label(ctx, begin);
+               ctx -> decl -> exit_label = end;
+               oberon_statement_seq(ctx);
+               oberon_generate_goto(ctx, begin);
+               oberon_generate_label(ctx, end);
+               oberon_assert_token(ctx, END);
+               oberon_close_scope(ctx -> decl);
+       }
+       else if(ctx -> token == EXIT)
+       {
+               oberon_assert_token(ctx, EXIT);
+               if(ctx -> decl -> exit_label == NULL)
+               {
+                       oberon_error(ctx, "not in LOOP-END");
+               }
+               oberon_generate_goto(ctx, ctx -> decl -> exit_label);
+       }
        else if(ctx -> token == RETURN)
        {
                oberon_assert_token(ctx, RETURN);