From: DeaDDooMER Date: Thu, 3 Aug 2017 14:11:28 +0000 (+0300) Subject: Добавлена конструкция LOOP/EXIT X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=commitdiff_plain;h=5b29102a5440d6511087356b9d9579b7501ca1ec Добавлена конструкция LOOP/EXIT --- 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."