X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=oberon.c;h=ec4cab05b3804d3c204407e28dcbb2eff1ccea22;hb=390a7e053165954865bc013a7c7057982c206453;hp=4dfc604a5f38159b0d1668b8376b0cc4fa8195e7;hpb=c3449e207b5e1e85ecea55975163a4dc6b986962;p=dsw-obn.git diff --git a/oberon.c b/oberon.c index 4dfc604..ec4cab0 100644 --- a/oberon.c +++ b/oberon.c @@ -22,7 +22,22 @@ enum { TRUE, FALSE, LPAREN, - RPAREN + RPAREN, + EQUAL, + NEQ, + LESS, + LEQ, + GREAT, + GEQ, + PLUS, + MINUS, + OR, + STAR, + SLASH, + DIV, + MOD, + AND, + NOT }; // ======================================================================= @@ -44,6 +59,7 @@ oberon_error(oberon_context_t * ctx, const char * fmt, ...) exit(1); } +/* static int oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item) { @@ -67,7 +83,9 @@ oberon_item_to_type_class(oberon_context_t * ctx, oberon_item_t * item) return class; } +*/ +/* static void oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * to) { @@ -79,6 +97,7 @@ oberon_autocast_to(oberon_context_t * ctx, oberon_item_t * from, oberon_item_t * oberon_error(ctx, "oberon_autocast_to: types not matched %i -> %i", from_class, to_class); } } +*/ // ======================================================================= // TABLE @@ -197,6 +216,18 @@ oberon_read_ident(oberon_context_t * ctx) { ctx -> token = FALSE; } + else if(strcmp(ident, "OR") == 0) + { + ctx -> token = OR; + } + else if(strcmp(ident, "DIV") == 0) + { + ctx -> token = DIV; + } + else if(strcmp(ident, "MOD") == 0) + { + ctx -> token = MOD; + } } static void @@ -267,6 +298,56 @@ oberon_read_symbol(oberon_context_t * ctx) ctx -> token = RPAREN; oberon_get_char(ctx); break; + case '=': + ctx -> token = EQUAL; + oberon_get_char(ctx); + break; + case '#': + ctx -> token = NEQ; + oberon_get_char(ctx); + break; + case '<': + ctx -> token = LESS; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = LEQ; + oberon_get_char(ctx); + } + break; + case '>': + ctx -> token = GREAT; + oberon_get_char(ctx); + if(ctx -> c == '=') + { + ctx -> token = GEQ; + oberon_get_char(ctx); + } + break; + case '+': + ctx -> token = PLUS; + oberon_get_char(ctx); + break; + case '-': + ctx -> token = MINUS; + oberon_get_char(ctx); + break; + case '*': + ctx -> token = STAR; + oberon_get_char(ctx); + break; + case '/': + ctx -> token = SLASH; + oberon_get_char(ctx); + break; + case '&': + ctx -> token = AND; + oberon_get_char(ctx); + break; + case '~': + ctx -> token = NOT; + oberon_get_char(ctx); + break; default: oberon_error(ctx, "invalid char"); break; @@ -294,22 +375,56 @@ oberon_read_token(oberon_context_t * ctx) } // ======================================================================= -// EXPR +// EXPRESSION // ======================================================================= static void oberon_expect_token(oberon_context_t * ctx, int token); -static oberon_item_t * oberon_expr(oberon_context_t * ctx); +static oberon_expr_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 * +static oberon_expr_t * +oberon_new_operator(int op, oberon_type_t * result, oberon_expr_t * left, oberon_expr_t * right) +{ + oberon_oper_t * operator; + operator = malloc(sizeof *operator); + memset(operator, 0, sizeof *operator); + + operator -> is_item = 0; + operator -> result = result; + operator -> op = op; + operator -> left = left; + operator -> right = right; + + return (oberon_expr_t *) operator; +} + +static oberon_expr_t * +oberon_new_item(int mode, oberon_type_t * result) +{ + oberon_item_t * item; + item = malloc(sizeof *item); + memset(item, 0, sizeof *item); + + item -> is_item = 1; + item -> result = result; + item -> mode = mode; + + return (oberon_expr_t *)item; +} + +static oberon_expr_t * +oberon_make_not(oberon_context_t * ctx, oberon_expr_t * expr) +{ + return oberon_new_operator(OP_LOGIC_NOT, expr -> result, expr, NULL); +} + +static oberon_expr_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); + oberon_expr_t * expr; switch(ctx -> token) { @@ -320,40 +435,229 @@ oberon_factor(oberon_context_t * ctx) { oberon_error(ctx, "undefined variable %s", name); } - item -> mode = MODE_VAR; - item -> var = var; + expr = oberon_new_item(MODE_VAR, var -> type); + expr -> item.var = var; break; case INTEGER: - item -> mode = MODE_INTEGER; - item -> integer = ctx -> integer; + expr = oberon_new_item(MODE_INTEGER, ctx -> int_type); + expr -> item.integer = ctx -> integer; oberon_assert_token(ctx, INTEGER); break; case TRUE: - item -> mode = MODE_BOOLEAN; - item -> boolean = 1; + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr -> item.boolean = 1; oberon_assert_token(ctx, TRUE); break; case FALSE: - item -> mode = MODE_BOOLEAN; - item -> boolean = 0; + expr = oberon_new_item(MODE_BOOLEAN, ctx -> bool_type); + expr -> item.boolean = 0; oberon_assert_token(ctx, FALSE); break; case LPAREN: oberon_assert_token(ctx, LPAREN); - item = oberon_expr(ctx); + expr = oberon_expr(ctx); oberon_assert_token(ctx, RPAREN); break; + case NOT: + oberon_assert_token(ctx, NOT); + expr = oberon_factor(ctx); + expr = oberon_make_not(ctx, expr); + break; default: oberon_error(ctx, "invalid expression"); } - return item; + return expr; +} + +static oberon_expr_t * +oberon_make_mul_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b) +{ + oberon_expr_t * expr; + oberon_type_t * result; + + result = a -> result; + + if(token == STAR) + { + expr = oberon_new_operator(OP_MUL, result, a, b); + } + else if(token == SLASH) + { + expr = oberon_new_operator(OP_DIV, result, a, b); + } + else if(token == DIV) + { + expr = oberon_new_operator(OP_DIV, result, a, b); + } + else if(token == MOD) + { + expr = oberon_new_operator(OP_MOD, result, a, b); + } + else if(token == AND) + { + expr = oberon_new_operator(OP_LOGIC_AND, result, a, b); + } + else + { + oberon_error(ctx, "oberon_make_mul_op: wat"); + } + + return expr; +} + +#define ISMULOP(x) \ + ((x) >= STAR && (x) <= AND) + +static oberon_expr_t * +oberon_term_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + + expr = oberon_factor(ctx); + while(ISMULOP(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_factor(ctx); + expr = oberon_make_mul_op(ctx, token, expr, inter); + } + + return expr; } -static oberon_item_t * +static oberon_expr_t * +oberon_make_add_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b) +{ + oberon_expr_t * expr; + oberon_type_t * result; + + result = a -> result; + + if(token == PLUS) + { + expr = oberon_new_operator(OP_ADD, result, a, b); + } + else if(token == MINUS) + { + expr = oberon_new_operator(OP_SUB, result, a, b); + } + else if(token == OR) + { + expr = oberon_new_operator(OP_LOGIC_OR, result, a, b); + } + else + { + oberon_error(ctx, "oberon_make_add_op: wat"); + } + + return expr; +} + +static oberon_expr_t * +oberon_make_unary_minus(oberon_context_t * ctx, oberon_expr_t * expr) +{ + return oberon_new_operator(OP_UNARY_MINUS, expr -> result, expr, NULL); +} + +#define ISADDOP(x) \ + ((x) >= PLUS && (x) <= OR) + +static oberon_expr_t * +oberon_simple_expr(oberon_context_t * ctx) +{ + oberon_expr_t * expr; + + int minus = 0; + if(ctx -> token == PLUS) + { + minus = 0; + oberon_assert_token(ctx, PLUS); + } + else if(ctx -> token == MINUS) + { + minus = 1; + oberon_assert_token(ctx, MINUS); + } + + expr = oberon_term_expr(ctx); + while(ISADDOP(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_term_expr(ctx); + expr = oberon_make_add_op(ctx, token, expr, inter); + } + + if(minus) + { + expr = oberon_make_unary_minus(ctx, expr); + } + + return expr; +} + +static oberon_expr_t * +oberon_make_relation(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_expr_t * b) +{ + oberon_expr_t * expr; + oberon_type_t * result; + + result = a -> result; + + if(token == EQUAL) + { + expr = oberon_new_operator(OP_EQ, result, a, b); + } + else if(token == NEQ) + { + expr = oberon_new_operator(OP_NEQ, result, a, b); + } + else if(token == LESS) + { + expr = oberon_new_operator(OP_LSS, result, a, b); + } + else if(token == LEQ) + { + expr = oberon_new_operator(OP_LEQ, result, a, b); + } + else if(token == GREAT) + { + expr = oberon_new_operator(OP_GRT, result, a, b); + } + else if(token == GEQ) + { + expr = oberon_new_operator(OP_GEQ, result, a, b); + } + else + { + oberon_error(ctx, "oberon_make_relation: wat"); + } + + return expr; +} + +#define ISRELATION(x) \ + ((x) >= EQUAL && (x) <= GEQ) + +static oberon_expr_t * oberon_expr(oberon_context_t * ctx) { - return oberon_factor(ctx); + oberon_expr_t * expr; + + expr = oberon_simple_expr(ctx); + while(ISRELATION(ctx -> token)) + { + int token = ctx -> token; + oberon_read_token(ctx); + + oberon_expr_t * inter = oberon_simple_expr(ctx); + expr = oberon_make_relation(ctx, token, expr, inter); + } + + return expr; } // ======================================================================= @@ -423,14 +727,14 @@ oberon_decl_seq(oberon_context_t * ctx) } static void -oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) +oberon_assign(oberon_context_t * ctx, oberon_expr_t * src, oberon_expr_t * dst) { - if(dst -> mode == MODE_INTEGER) - { - oberon_error(ctx, "invalid assignment"); - } - - oberon_autocast_to(ctx, src, dst); +// if(dst -> mode == MODE_INTEGER) +// { +// oberon_error(ctx, "invalid assignment"); +// } +// +// oberon_autocast_to(ctx, src, dst); oberon_generate_assign(ctx, src, dst); } @@ -438,8 +742,8 @@ oberon_assign(oberon_context_t * ctx, oberon_item_t * src, oberon_item_t * dst) static void oberon_statement(oberon_context_t * ctx) { - oberon_item_t * item1; - oberon_item_t * item2; + oberon_expr_t * item1; + oberon_expr_t * item2; if(ctx -> token == IDENT) { @@ -496,6 +800,46 @@ oberon_parse_module(oberon_context_t * ctx) // LIBRARY // ======================================================================= +static oberon_type_t * +oberon_register_global_type_ret(oberon_context_t * ctx, oberon_type_t * type) +{ + oberon_type_t * x = ctx -> types; + while(x -> next && strcmp(x -> next -> name, type -> name) != 0) + { + x = x -> next; + } + + if(x -> next) + { + oberon_error(ctx, "already defined"); + } + + // TODO: copy type name (not a pointer) + oberon_type_t * newtype = malloc(sizeof *newtype); + memcpy(newtype, type, sizeof *newtype); + newtype -> next = NULL; + oberon_generator_init_type(ctx, newtype); + + x -> next = newtype; + return newtype; +} + +static void +register_default_types(oberon_context_t * ctx) +{ + static oberon_type_t integer = { "INTEGER", OBERON_TYPE_INTEGER, sizeof(int) }; + static oberon_type_t boolean = { "BOOLEAN", OBERON_TYPE_BOOLEAN, sizeof(int) }; + + ctx -> int_type = oberon_register_global_type_ret(ctx, &integer); + ctx -> bool_type = oberon_register_global_type_ret(ctx, &boolean); +} + +void +oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type) +{ + oberon_register_global_type_ret(ctx, type); +} + oberon_context_t * oberon_create_context() { @@ -504,9 +848,12 @@ oberon_create_context() oberon_type_t * types = malloc(sizeof *types); memset(types, 0, sizeof *types); + ctx -> types = types; oberon_generator_init_context(ctx); - ctx -> types = types; + + register_default_types(ctx); + return ctx; } @@ -534,25 +881,3 @@ oberon_compile_module(oberon_context_t * ctx, const char * code) return mod; } -void -oberon_register_global_type(oberon_context_t * ctx, oberon_type_t * type) -{ - oberon_type_t * x = ctx -> types; - while(x -> next && strcmp(x -> next -> name, type -> name) != 0) - { - x = x -> next; - } - - if(x -> next) - { - oberon_error(ctx, "already defined"); - } - - // TODO: copy type name (not a pointer) - oberon_type_t * newtype = malloc(sizeof *newtype); - memcpy(newtype, type, sizeof *newtype); - newtype -> next = NULL; - oberon_generator_init_type(ctx, newtype); - - x -> next = newtype; -}