X-Git-Url: http://deadsoftware.ru/gitweb?p=dsw-obn.git;a=blobdiff_plain;f=src%2Foberon.c;h=50429645b22a713480253b1fb262128dc1b97af6;hp=e88ff79159e28e93c010a73ebde045ee8a6c9132;hb=9bcd389a97869b2ab6b1c6fdc35c0f09beab66c5;hpb=72048038b5be32cc940c8452541b8bb3e75958a9 diff --git a/src/oberon.c b/src/oberon.c index e88ff79..5042964 100644 --- a/src/oberon.c +++ b/src/oberon.c @@ -52,8 +52,8 @@ enum { TYPE, ARRAY, OF, - LBRACE, - RBRACE, + LBRACK, + RBRACK, RECORD, POINTER, TO, @@ -74,7 +74,10 @@ enum { FOR, BY, LOOP, - EXIT + EXIT, + LBRACE, + RBRACE, + DOTDOT }; // ======================================================================= @@ -149,6 +152,15 @@ oberon_new_type_string(int size) return x; } +static oberon_type_t * +oberon_new_type_set(int size) +{ + oberon_type_t * x; + x = oberon_new_type_ptr(OBERON_TYPE_SET); + x -> size = size; + return x; +} + // ======================================================================= // TABLE // ======================================================================= @@ -505,37 +517,43 @@ oberon_read_number(oberon_context_t * ctx) } else if(ctx -> c == '.') { - mode = 2; oberon_get_char(ctx); - - while(isdigit(ctx -> c)) + if(ctx -> c == '.') { - oberon_get_char(ctx); + /* Чит: избегаем конфликта с DOTDOT */ + ctx -> code_index -= 1; } - - if(ctx -> c == 'E' || ctx -> c == 'D') + else { - exp_i = ctx -> code_index; - - if(ctx -> c == 'D') - { - mode = 3; - } - - oberon_get_char(ctx); + mode = 2; - if(ctx -> c == '+' || ctx -> c == '-') + while(isdigit(ctx -> c)) { oberon_get_char(ctx); } - while(isdigit(ctx -> c)) + if(ctx -> c == 'E' || ctx -> c == 'D') { + exp_i = ctx -> code_index; + + if(ctx -> c == 'D') + { + mode = 3; + } + oberon_get_char(ctx); - } - } + if(ctx -> c == '+' || ctx -> c == '-') + { + oberon_get_char(ctx); + } + while(isdigit(ctx -> c)) + { + oberon_get_char(ctx); + } + } + } end_i = ctx -> code_index; } @@ -699,6 +717,11 @@ oberon_read_symbol(oberon_context_t * ctx) case '.': ctx -> token = DOT; oberon_get_char(ctx); + if(ctx -> c == '.') + { + ctx -> token = DOTDOT; + oberon_get_char(ctx); + } break; case '(': ctx -> token = LPAREN; @@ -774,11 +797,11 @@ oberon_read_symbol(oberon_context_t * ctx) oberon_get_char(ctx); break; case '[': - ctx -> token = LBRACE; + ctx -> token = LBRACK; oberon_get_char(ctx); break; case ']': - ctx -> token = RBRACE; + ctx -> token = RBRACK; oberon_get_char(ctx); break; case '^': @@ -791,6 +814,14 @@ oberon_read_symbol(oberon_context_t * ctx) case '\'': oberon_read_string(ctx); break; + case '{': + ctx -> token = LBRACE; + oberon_get_char(ctx); + break; + case '}': + ctx -> token = RBRACE; + oberon_get_char(ctx); + break; default: oberon_error(ctx, "invalid char %c", ctx -> c); break; @@ -871,12 +902,18 @@ oberon_make_unary_op(oberon_context_t * ctx, int token, oberon_expr_t * a) if(token == MINUS) { - if(result -> class != OBERON_TYPE_INTEGER) + if(result -> class == OBERON_TYPE_SET) + { + expr = oberon_new_operator(OP_COMPLEMENTATION, result, a, NULL); + } + else if(result -> class == OBERON_TYPE_INTEGER) + { + expr = oberon_new_operator(OP_UNARY_MINUS, result, a, NULL); + } + else { oberon_error(ctx, "incompatible operator type"); } - - expr = oberon_new_operator(OP_UNARY_MINUS, result, a, NULL); } else if(token == NOT) { @@ -1394,7 +1431,7 @@ oberon_make_record_selector(oberon_context_t * ctx, oberon_expr_t * expr, char * } #define ISSELECTOR(x) \ - (((x) == LBRACE) \ + (((x) == LBRACK) \ || ((x) == DOT) \ || ((x) == UPARROW) \ || ((x) == LPAREN)) @@ -1502,12 +1539,12 @@ oberon_designator(oberon_context_t * ctx) name = oberon_assert_ident(ctx); expr = oberon_make_record_selector(ctx, expr, name); break; - case LBRACE: - oberon_assert_token(ctx, LBRACE); + case LBRACK: + oberon_assert_token(ctx, LBRACK); int num_indexes = 0; oberon_expr_t * indexes = NULL; oberon_expr_list(ctx, &num_indexes, &indexes, 0); - oberon_assert_token(ctx, RBRACE); + oberon_assert_token(ctx, RBRACK); for(int i = 0; i < num_indexes; i++) { @@ -1619,6 +1656,59 @@ oberon_integer_item(oberon_context_t * ctx, int64_t i) return expr; } +static oberon_expr_t * +oberon_element(oberon_context_t * ctx) +{ + oberon_expr_t * e1; + oberon_expr_t * e2; + + e1 = oberon_expr(ctx); + if(e1 -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "expected integer"); + } + + e2 = NULL; + if(ctx -> token == DOTDOT) + { + oberon_assert_token(ctx, DOTDOT); + e2 = oberon_expr(ctx); + if(e2 -> result -> class != OBERON_TYPE_INTEGER) + { + oberon_error(ctx, "expected integer"); + } + } + + oberon_expr_t * set; + set = oberon_new_operator(OP_RANGE, ctx -> set_type, e1, e2); + return set; +} + +static oberon_expr_t * +oberon_set(oberon_context_t * ctx) +{ + oberon_expr_t * set; + oberon_expr_t * elements; + set = oberon_new_item(MODE_SET, ctx -> set_type, true); + set -> item.integer = 0; + + oberon_assert_token(ctx, LBRACE); + if(ISEXPR(ctx -> token)) + { + elements = oberon_element(ctx); + set = oberon_new_operator(OP_UNION, ctx -> set_type, set, elements); + while(ctx -> token == COMMA) + { + oberon_assert_token(ctx, COMMA); + elements = oberon_element(ctx); + set = oberon_new_operator(OP_UNION, ctx -> set_type, set, elements); + } + } + oberon_assert_token(ctx, RBRACE); + + return set; +} + static oberon_expr_t * oberon_factor(oberon_context_t * ctx) { @@ -1663,6 +1753,9 @@ oberon_factor(oberon_context_t * ctx) expr -> item.boolean = false; oberon_assert_token(ctx, FALSE); break; + case LBRACE: + expr = oberon_set(ctx); + break; case LPAREN: oberon_assert_token(ctx, LPAREN); expr = oberon_expr(ctx); @@ -1720,6 +1813,7 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ oberon_expr_t * expr; oberon_type_t * result; + bool error = false; if(token == IS) { oberon_type_t * v = a -> result; @@ -1825,10 +1919,21 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ } else if(token == SLASH) { - oberon_autocast_to_real(ctx, &a); - oberon_autocast_to_real(ctx, &b); - oberon_autocast_binary_op(ctx, &a, &b); - expr = oberon_new_operator(OP_DIV, a -> result, a, b); + if(a -> result -> class == OBERON_TYPE_SET + || b -> result -> class == OBERON_TYPE_SET) + { + oberon_autocast_binary_op(ctx, &a, &b); + result = a -> result; + expr = oberon_new_operator(OP_SYM_DIFFERENCE, result, a, b); + } + else + { + oberon_autocast_to_real(ctx, &a); + oberon_autocast_to_real(ctx, &b); + oberon_autocast_binary_op(ctx, &a, &b); + result = a -> result; + expr = oberon_new_operator(OP_DIV, result, a, b); + } } else if(token == DIV) { @@ -1844,29 +1949,58 @@ oberon_make_bin_op(oberon_context_t * ctx, int token, oberon_expr_t * a, oberon_ else { oberon_autocast_binary_op(ctx, &a, &b); - - if(token == PLUS) + result = a -> result; + if(result -> class == OBERON_TYPE_SET) { - expr = oberon_new_operator(OP_ADD, a -> result, a, b); - } - else if(token == MINUS) - { - expr = oberon_new_operator(OP_SUB, a -> result, a, b); - } - else if(token == STAR) - { - expr = oberon_new_operator(OP_MUL, a -> result, a, b); + switch(token) + { + case PLUS: + expr = oberon_new_operator(OP_UNION, result, a, b); + break; + case MINUS: + expr = oberon_new_operator(OP_DIFFERENCE, result, a, b); + break; + case STAR: + expr = oberon_new_operator(OP_INTERSECTION, result, a, b); + break; + default: + error = true; + break; + } } - else if(token == MOD) + else if(result -> class == OBERON_TYPE_INTEGER + || result -> class == OBERON_TYPE_REAL) { - expr = oberon_new_operator(OP_MOD, a -> result, a, b); + switch(token) + { + case PLUS: + expr = oberon_new_operator(OP_ADD, result, a, b); + break; + case MINUS: + expr = oberon_new_operator(OP_SUB, result, a, b); + break; + case STAR: + expr = oberon_new_operator(OP_MUL, result, a, b); + break; + case MOD: + expr = oberon_new_operator(OP_MOD, result, a, b); + break; + default: + error = true; + break; + } } else { - oberon_error(ctx, "oberon_make_bin_op: bin wat"); + error = true; } } + if(error) + { + oberon_error(ctx, "invalid operation"); + } + return expr; } @@ -3399,6 +3533,9 @@ register_default_types(oberon_context_t * ctx) ctx -> char_type = oberon_new_type_char(1); oberon_define_type(ctx -> world_scope, "CHAR", ctx -> char_type, 1); + + ctx -> set_type = oberon_new_type_set(4); + oberon_define_type(ctx -> world_scope, "SET", ctx -> set_type, 1); } static void @@ -3440,6 +3577,9 @@ oberon_make_min_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ case OBERON_TYPE_INTEGER: expr = oberon_integer_item(ctx, -powl(2, bits - 1)); break; + case OBERON_TYPE_SET: + expr = oberon_integer_item(ctx, 0); + break; default: oberon_error(ctx, "allowed only basic types"); break; @@ -3476,6 +3616,9 @@ oberon_make_max_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list_ case OBERON_TYPE_INTEGER: expr = oberon_integer_item(ctx, powl(2, bits - 1) - 1); break; + case OBERON_TYPE_SET: + expr = oberon_integer_item(ctx, bits); + break; default: oberon_error(ctx, "allowed only basic types"); break; @@ -3513,6 +3656,8 @@ oberon_make_size_call(oberon_context_t * ctx, int num_args, oberon_expr_t * list case OBERON_TYPE_INTEGER: case OBERON_TYPE_BOOLEAN: case OBERON_TYPE_REAL: + case OBERON_TYPE_CHAR: + case OBERON_TYPE_SET: size = type -> size; break; default: