DEADSOFTWARE

Добавлена конструкция LOOP/EXIT
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Thu, 3 Aug 2017 14:11:28 +0000 (17:11 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Thu, 3 Aug 2017 14:11:28 +0000 (17:11 +0300)
notes
src/oberon-internals.h
src/oberon.c
src/test.c

diff --git a/notes b/notes
index 693f32a80a90486705b57524ae58393bd068e60d..15aa1da6de3a10d2105fea29184e0af25f7174bf 100644 (file)
--- a/notes
+++ b/notes
@@ -4,7 +4,6 @@
 - Нет типа SET
 - Нет оператора IS
 - Нет конструкции CASE
-- Нет конструкции LOOP/EXIT
 - Нет конструкции WITH
 - Нет модуля SYSTEM
 - Нет функций ASH CAP CHR ENTIER LEN LONG MAX MIN ODD ORD SHORT SIZE
index f0a6bed23e96fa8ec6b70d9cafc3a133713485ba..7a776d695502bec8b53225c031e31f808d207841 100644 (file)
@@ -30,6 +30,8 @@ struct oberon_scope_t
        int local;
        oberon_object_t * parent;
        oberon_type_t * parent_type;
+
+       gen_label_t * exit_label;
 };
 
 enum oberon_type_kind
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);
index 42fc4ff3030a00a18b2b673141cc0f7137f2a1fc..ebb807bc518fa1211589cb47f32e2ae7f733bd38 100644 (file)
@@ -14,10 +14,10 @@ static char source_test[] =
        ""
        "BEGIN"
        "  Out.Open();"
-       "  len := 2 * 8;"
-       "  FOR i := 0 TO len BY 2 DO"
+       "  LOOP"
        "    Out.String('Count '); Out.Int(i, 0); Out.Ln;"
-       "    len := len + 2;"
+       "    i := i + 1;"
+       "    IF i > 4 THEN EXIT END;"
        "  END;"
        "  Out.String('end'); Out.Ln;"
        "END Test."