X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=oberon.c;h=4dfc604a5f38159b0d1668b8376b0cc4fa8195e7;hp=e411c6c2fdaa455bf15fddcd54c7b94a37f3c8c3;hb=c3449e207b5e1e85ecea55975163a4dc6b986962;hpb=b752043cfbb49243ca3727dbfc9be5b614a8c9c2 diff --git a/oberon.c b/oberon.c index e411c6c..4dfc604 100644 --- a/oberon.c +++ b/oberon.c @@ -3,7 +3,9 @@ #include #include #include + #include "oberon.h" +#include "generator.h" enum { EOF_ = 0, @@ -16,26 +18,18 @@ enum { COLON, BEGIN, ASSIGN, - INTEGER -}; - -enum { - MODE_VAR, - MODE_INTEGER, + INTEGER, + TRUE, + FALSE, + LPAREN, + RPAREN }; -typedef struct -{ - int mode; - int integer; - oberon_var_t * var; -} oberon_item_t; - // ======================================================================= // UTILS // ======================================================================= -static void +void oberon_error(oberon_context_t * ctx, const char * fmt, ...) { va_list ptr; @@ -55,22 +49,37 @@ oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item) { int class; - if(item -> mode == MODE_INTEGER) + switch(item -> mode) { - class = OBERON_TYPE_INTEGER; - } - else if(item -> mode == MODE_VAR) - { - class = item -> var -> type -> class; - } - else - { - oberon_error(ctx, "oberon_item_to_type_class: wat"); + case MODE_INTEGER: + class = OBERON_TYPE_INTEGER; + break; + case MODE_BOOLEAN: + class = OBERON_TYPE_BOOLEAN; + break; + case MODE_VAR: + class = item -> var -> type -> class; + break; + default: + oberon_error(ctx, "oberon_item_to_type_class: wat"); + break; } return class; } +static void +oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to) +{ + int from_class = oberon_item_to_type_class(ctx, from); + int to_class = oberon_item_to_type_class(ctx, to); + + if(from_class != to_class) + { + oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class); + } +} + // ======================================================================= // TABLE // ======================================================================= @@ -117,20 +126,11 @@ oberon_define_var(oberon_context_t * ctx, char * name, oberon_type_t * type) memset(newvar, 0, sizeof *newvar); newvar -> name = name; newvar -> type = type; + oberon_generator_init_var(ctx, newvar); x -> next = newvar; } -// ======================================================================= -// GENERATOR -// ======================================================================= - -static void -oberon_generate_assign(oberon_context_t * ctx, void * src, void * dst, int size) -{ - printf("G: %p := %p (%i);\n", dst, src, size); -} - // ======================================================================= // SCANER // ======================================================================= @@ -164,9 +164,9 @@ oberon_read_ident(oberon_context_t * ctx) c = ctx -> code[i]; } - char * ident = malloc(len + 2); + char * ident = malloc(len + 1); memcpy(ident, &ctx->code[ctx->code_index], len); - ident[len + 1] = 0; + ident[len] = 0; ctx -> code_index = i; ctx -> c = ctx -> code[i]; @@ -189,6 +189,14 @@ oberon_read_ident(oberon_context_t * ctx) { ctx -> token = BEGIN; } + else if(strcmp(ident, "TRUE") == 0) + { + ctx -> token = TRUE; + } + else if(strcmp(ident, "FALSE") == 0) + { + ctx -> token = FALSE; + } } static void @@ -225,6 +233,46 @@ oberon_skip_space(oberon_context_t * ctx) } } +static void +oberon_read_symbol(oberon_context_t * ctx) +{ + int c = ctx -> c; + switch(c) + { + case 0: + ctx -> token = EOF_; + break; + case ';': + ctx -> token = SEMICOLON; + oberon_get_char(ctx); + break; + case ':': + ctx -> token = COLON; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = ASSIGN; + oberon_get_char(ctx); + } + break; + case '.': + ctx -> token = DOT; + oberon_get_char(ctx); + break; + case '(': + ctx -> token = LPAREN; + oberon_get_char(ctx); + break; + case ')': + ctx -> token = RPAREN; + oberon_get_char(ctx); + break; + default: + oberon_error(ctx, "invalid char"); + break; + } +} + static void oberon_read_token(oberon_context_t * ctx) { @@ -241,26 +289,73 @@ oberon_read_token(oberon_context_t * ctx) } else { - switch(c) - { - case 0: ctx -> token = EOF_; break; - case ';': ctx -> token = SEMICOLON; oberon_get_char(ctx); break; - case ':': - /****************************************************/ - ctx -> token = COLON; oberon_get_char(ctx); - if(ctx -> c == '=') - { - ctx -> token = ASSIGN; - oberon_get_char(ctx); - } - break; - /****************************************************/ - case '.': ctx -> token = DOT; oberon_get_char(ctx); break; - default: oberon_error(ctx, "invalid char"); - } + oberon_read_symbol(ctx); } } +// ======================================================================= +// EXPR +// ======================================================================= + +static void oberon_expect_token(oberon_context_t * ctx, int token); +static oberon_item_t * oberon_expr(oberon_context_t * ctx); +static void oberon_assert_token(oberon_context_t * ctx, int token); +static char * oberon_assert_ident(oberon_context_t * ctx); + +static oberon_item_t * +oberon_factor(oberon_context_t * ctx) +{ + char * name; + oberon_var_t * var; + + oberon_item_t * item = malloc(sizeof *item); + memset(item, 0, sizeof *item); + + switch(ctx -> token) + { + case IDENT: + name = oberon_assert_ident(ctx); + var = oberon_find_var(ctx, name); + if(var == NULL) + { + oberon_error(ctx, "undefined variable %s", name); + } + item -> mode = MODE_VAR; + item -> var = var; + break; + case INTEGER: + item -> mode = MODE_INTEGER; + item -> integer = ctx -> integer; + oberon_assert_token(ctx, INTEGER); + break; + case TRUE: + item -> mode = MODE_BOOLEAN; + item -> boolean = 1; + oberon_assert_token(ctx, TRUE); + break; + case FALSE: + item -> mode = MODE_BOOLEAN; + item -> boolean = 0; + oberon_assert_token(ctx, FALSE); + break; + case LPAREN: + oberon_assert_token(ctx, LPAREN); + item = oberon_expr(ctx); + oberon_assert_token(ctx, RPAREN); + break; + default: + oberon_error(ctx, "invalid expression"); + } + + return item; +} + +static oberon_item_t * +oberon_expr(oberon_context_t * ctx) +{ + return oberon_factor(ctx); +} + // ======================================================================= // PARSER // ======================================================================= @@ -284,9 +379,8 @@ oberon_assert_token(oberon_context_t * ctx, int token) static char * oberon_assert_ident(oberon_context_t * ctx) { - char * ident; oberon_expect_token(ctx, IDENT); - ident = ctx -> string; + char * ident = ctx -> string; oberon_read_token(ctx); return ident; } @@ -328,37 +422,6 @@ oberon_decl_seq(oberon_context_t * ctx) } } -static oberon_item_t * -oberon_expr(oberon_context_t * ctx) -{ - oberon_item_t * item = malloc(sizeof *item); - memset(item, 0, sizeof *item); - - if(ctx -> token == IDENT) - { - char * name = oberon_assert_ident(ctx); - oberon_var_t * var = oberon_find_var(ctx, name); - if(var == NULL) - { - oberon_error(ctx, "undefined variable"); - } - item -> mode = MODE_VAR; - item -> var = var; - } - else if(ctx -> token == INTEGER) - { - item -> mode = MODE_INTEGER; - item -> integer = ctx -> integer; - oberon_assert_token(ctx, INTEGER); - } - else - { - oberon_error(ctx, "invalid expression"); - } - - return item; -} - static void oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) { @@ -367,16 +430,9 @@ oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) oberon_error(ctx, "invalid assignment"); } - int src_class = oberon_item_to_type_class(ctx, src); - int dst_class = oberon_item_to_type_class(ctx, dst); - - if(src_class != dst_class) - { - oberon_error(ctx, "types not matched"); - } + oberon_autocast_to(ctx, src, dst); - // TODO: code generation - oberon_generate_assign(ctx, 0, 0, 4); + oberon_generate_assign(ctx, src, dst); } static void @@ -406,7 +462,7 @@ oberon_statement_seq(oberon_context_t * ctx) } static void -oberon_parse_it(oberon_context_t * ctx) +oberon_parse_module(oberon_context_t * ctx) { char *name1, *name2; oberon_read_token(ctx); @@ -421,7 +477,9 @@ oberon_parse_it(oberon_context_t * ctx) if(ctx -> token == BEGIN) { oberon_assert_token(ctx, BEGIN); + oberon_generate_begin_module(ctx); oberon_statement_seq(ctx); + oberon_generate_end_module(ctx); } oberon_assert_token(ctx, END); @@ -447,10 +505,18 @@ oberon_create_context() oberon_type_t * types = malloc(sizeof *types); memset(types, 0, sizeof *types); + oberon_generator_init_context(ctx); ctx -> types = types; return ctx; } +void +oberon_destroy_context(oberon_context_t * ctx) +{ + oberon_generator_destroy_context(ctx); + free(ctx); +} + oberon_module_t * oberon_compile_module(oberon_context_t * ctx, const char * code) { @@ -462,7 +528,9 @@ oberon_compile_module(oberon_context_t * ctx, const char * code) ctx -> mod -> vars = vars; oberon_init_scaner(ctx, code); - oberon_parse_it(ctx); + oberon_parse_module(ctx); + + oberon_generate_code(ctx); return mod; } @@ -484,6 +552,7 @@ oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type) oberon_type_t * newtype = malloc(sizeof *newtype); memcpy(newtype, type, sizeof *newtype); newtype -> next = NULL; + oberon_generator_init_type(ctx, newtype); x -> next = newtype; }