From 5b29102a5440d6511087356b9d9579b7501ca1ec Mon Sep 17 00:00:00 2001 From: DeaDDooMER Date: Thu, 3 Aug 2017 17:11:28 +0300 Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?utf8?q?=D0=B0=20=D0=BA=D0=BE=D0=BD=D1=81=D1=82=D1=80=D1=83=D0=BA=D1=86?= =?utf8?q?=D0=B8=D1=8F=20LOOP/EXIT?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- notes | 1 - src/oberon-internals.h | 2 ++ src/oberon.c | 40 +++++++++++++++++++++++++++++++++++++++- src/test.c | 6 +++--- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/notes b/notes index 693f32a..15aa1da 100644 --- 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 diff --git a/src/oberon-internals.h b/src/oberon-internals.h index f0a6bed..7a776d6 100644 --- a/src/oberon-internals.h +++ b/src/oberon-internals.h @@ -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 diff --git a/src/oberon.c b/src/oberon.c index f50f4d3..e95a9be 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -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); diff --git a/src/test.c b/src/test.c index 42fc4ff..ebb807b 100644 --- a/src/test.c +++ b/src/test.c @@ -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." -- 2.29.2