#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "avl.h" #define TODO assert(!"TODO"); #define CHECK assert(!"CHECK"); #define argv0 program_invocation_name #ifdef ZDEBUG #define zprintf(fmt, ...) \ printf(fmt, ## __VA_ARGS__); #else #define zprintf(...); #endif const char* command = NULL; static void parse_args(int argc, char* const* argv) { for (int opt; (opt = getopt(argc, argv, "c:")) != -1; ) switch (opt) { case 'c': command = optarg; break; default: { printf("Unknown option '%c'!" "\n", opt); exit(1); break; } } } struct string { char* data; unsigned refcount; }; struct string* new_string(const char* data_ro) { struct string* this = malloc(sizeof(*this)); this->data = strdup(data_ro); this->refcount = 1; return this; } struct string* new_string_from_fmt_va(const char* fmt, va_list va) { struct string* this = malloc(sizeof(*this)); int x = vasprintf(&this->data, fmt, va); if (x < 0) { abort(); } this->refcount = 1; return this; } struct string* new_string_from_fmt(const char* fmt, ...) { va_list ap; va_start(ap, fmt); struct string* this = new_string_from_fmt_va(fmt, ap); va_end(ap); return this; } struct string* inc_string(struct string* this) { if (this) this->refcount++; return this; } int compare_strings(const struct string* a, const struct string* b) { return strcmp(a->data, b->data); } int compare_strings_vv(const void* a, const void* b) { return compare_strings( (const struct string*) a, (const struct string*) b); } void free_string(struct string* this) { if (this && !--this->refcount) { free(this->data); free(this); } } void free_string_v(void* ptr) { free_string((struct string*) ptr); } struct stringset { struct avl_tree_t* tree; unsigned refcount; }; struct stringset* new_stringset(void) { struct stringset* this = malloc(sizeof(*this)); this->tree = avl_alloc_tree(compare_strings_vv, free_string_v); this->refcount = 1; return this; } bool stringset_add(struct stringset* this, struct string* new) { bool is_new; struct avl_node_t* node = avl_insert(this->tree, new); if (node) { inc_string(new); is_new = true; } else { TODO; } return is_new; } bool stringset_update(struct stringset* this, const struct stringset* updateme) { bool is_new = false; for (struct avl_node_t* i = updateme->tree->head; i; i = i->next) { struct avl_node_t* node = avl_insert(this->tree, i->item); if (node) { inc_string(i->item); is_new = true; } else if (errno == EEXIST) { ; } else { TODO; } } return is_new; } struct stringset* inc_stringset(struct stringset* this) { if (this) this->refcount++; return this; } void stringset_println(const struct stringset* this) { for (struct avl_node_t* i = this->tree->head; i; i = i->next) { const struct string* str = i->item; printf("%s\n", str->data); } } void free_stringset(struct stringset* this) { if (this && !--this->refcount) { avl_free_tree(this->tree); free(this); } } struct value; struct value* inc_value(struct value* this); void free_value(struct value* this); struct expression { enum expression_kind { ek_syntax_error, // primary: ek_literal, ek_variable, // arithmetic operators: ek_positive, ek_negative, ek_add, ek_subtract, ek_multiply, ek_divide, ek_integer_divide, ek_remainder, ek_exponent, // bitwise operator: ek_leftbitshift, ek_rightbitshift, // comparision operators: ek_greater_than, ek_less_than, ek_greater_than_equal_to, ek_less_than_equal_to, // equality operators: ek_equal_to, ek_not_equal_to, // logical operators: ek_logical_not, ek_logical_and, ek_logical_or, ek_ternary, ek_assign, ek_comma, } kind; unsigned column; struct string* string; struct expression* center; struct expression* left; struct expression* right; struct value* value; unsigned refcount; }; struct expression* inc_expression(struct expression* this); struct expression* new_syntax_error_expression( unsigned column, struct string* error_message) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_syntax_error; this->column = column; this->string = inc_string(error_message); this->center = NULL; this->left = NULL; this->right = NULL; this->value = NULL; this->refcount = 1; return this; } struct expression* new_literal_expression( struct value* value) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_literal; this->string = NULL;; this->center = NULL; this->left = this->right = NULL; this->value = inc_value(value); this->refcount = 1; return this; } struct expression* new_variable_expression( struct string* variable) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_variable; this->string = inc_string(variable); this->center = NULL; this->left = this->right = NULL; this->value = NULL; this->refcount = 1; return this; } struct expression* new_logical_not_expression( struct expression* sub) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_logical_not; this->string = NULL; this->center = inc_expression(sub); this->left = NULL; this->right = NULL; this->value = NULL; this->refcount = 1; return this; } struct expression* new_positive_expression( struct expression* sub) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_positive; this->string = NULL; this->center = inc_expression(sub); this->left = NULL; this->right = NULL; this->value = NULL; this->refcount = 1; return this; } struct expression* new_negative_expression( struct expression* sub) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_negative; this->string = NULL; this->center = inc_expression(sub); this->left = NULL; this->right = NULL; this->value = NULL; this->refcount = 1; return this; } struct expression* new_binary_expression( enum expression_kind kind, struct expression* left, struct expression* right) { struct expression* this = malloc(sizeof(*this)); this->kind = kind; this->string = NULL; this->center = NULL; this->left = inc_expression(left); this->right = inc_expression(right); this->value = NULL; this->refcount = 1; return this; } struct expression* new_ternary_expression( struct expression* center, struct expression* left, struct expression* right) { struct expression* this = malloc(sizeof(*this)); this->kind = ek_ternary; this->string = NULL; this->center = inc_expression(center); this->left = inc_expression(left); this->right = inc_expression(right); this->value = NULL; this->refcount = 1; return this; } struct expression* inc_expression(struct expression* this) { if (this) this->refcount++; return this; } void free_expression(struct expression* this) { if (this && !--this->refcount) { free_string(this->string); free_expression(this->center); free_expression(this->left); free_expression(this->right); free_value(this->value); free(this); } } enum value_kind { vk_number, vk_error, }; struct value { enum value_kind kind; struct stringset* errors; mpq_t mpq; unsigned refcount; }; struct value* new_error_value(struct stringset* errors) { struct value* this = malloc(sizeof(*this)); this->kind = vk_error; this->errors = inc_stringset(errors); mpq_init(this->mpq); this->refcount = 1; return this; } struct value* new_error_value_from_fmt(const char* fmt, ...) { va_list va; va_start(va, fmt); struct string* message = new_string_from_fmt_va(fmt, va); struct stringset* set = new_stringset(); stringset_add(set, message); struct value* this = new_error_value(set); free_stringset(set); free_string(message); va_end(va); return this; } struct value* new_error_value_from_union( const struct value* left, const struct value* right) { assert(left->kind == vk_error); assert(right->kind == vk_error); struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); struct value* retval = new_error_value(set); free_stringset(set); return retval; } struct value* new_value_from_int(int x) { struct value* this = malloc(sizeof(*this)); this->kind = vk_number; this->errors = NULL; mpq_init(this->mpq); mpq_set_si(this->mpq, x, 1); this->refcount = 1; return this; } struct value* new_value(mpq_t mpq) { struct value* this = malloc(sizeof(*this)); this->kind = vk_number; this->errors = NULL; mpq_init(this->mpq); mpq_set(this->mpq, mpq); this->refcount = 1; return this; } struct value* inc_value(struct value* this) { if (this) this->refcount++; return this; } void free_value(struct value* this) { if (this && !--this->refcount) { mpq_clear(this->mpq); free_stringset(this->errors); free(this); } } struct value* scan(const char* text) { const char* moving = text; const char* digits = "0123456789"; unsigned ibase = 10; if (text[0] == '0' && text[1] == 'b') { digits = "01"; ibase = 2; moving += 2; } else if (text[0] == '0' && text[1] == 'x') { digits = "0123456789ABCDEF"; ibase = 16; moving += 2; } mpq_t base; mpq_init(base); mpq_t tmp; mpq_init(tmp); mpq_t value; mpq_init(value); mpq_set_si(value, 0, 1); mpq_set_si(base, ibase, 1); while ('_' == *moving || (*moving && index(digits, toupper(*moving)))) { if ('_' == *moving) { moving++; } else { mpq_set_si(tmp, index(digits, toupper(*moving++)) - digits, 1); mpq_mul(value, value, base); mpq_add(value, value, tmp); } } while ('_' == *moving) { moving++; } if (*moving == '.') { mpq_t factor; mpq_init(factor); moving++; mpq_set_si(factor, 1, ibase); while ('_' == *moving || (*moving && index(digits, toupper(*moving)))) { if ('_' == *moving) { moving++; } else { mpq_set_si(tmp, index(digits, toupper(*moving++)) - digits, 1); mpq_mul(tmp, factor, tmp); mpq_add(value, value, tmp); mpq_div(factor, factor, base); } } mpq_clear(factor); } while ('_' == *moving) { moving++; } assert(*moving == '\0'); struct value* retval = new_value(value); mpq_clear(base); mpq_clear(tmp); mpq_clear(value); return retval; } struct scope { avl_tree_t* tree; }; struct variable { struct string* name; struct value* value; }; struct variable* new_variable(struct string* name) { struct variable* this = malloc(sizeof(*this)); this->name = inc_string(name); this->value = NULL; return this; } int compare_variable(const void* a, const void* b) { const struct variable* A = a, *B = b; return strcmp(A->name->data, B->name->data); } void free_variable(void* ptr) { struct variable* this = ptr; free_string(this->name); free_value(this->value); free(this); } struct scope* new_scope(void) { struct scope* this = malloc(sizeof(*this)); this->tree = avl_alloc_tree(compare_variable, free_variable); return this; } struct value** scope_lookup( struct scope* this, struct string* name) { struct avl_node_t* node = avl_search(this->tree, &name); if (!node) { struct variable* var = new_variable(name); node = avl_insert(this->tree, var); } return &((struct variable*) node->item)->value; } void free_scope(struct scope* this) { avl_free_tree(this->tree); free(this); } enum token { t_uninitialized, t_error, // primary: t_identifier, t_literal, t_binary, t_hexadecimal, // brakets: t_oparen, t_cparen, // arithmetic operators: t_plus, t_minus, t_asterisk, t_slash, t_percent, t_slash_slash, t_asterisk_asterisk, // comparision operators: t_lessthan, t_lessthan_equals, t_lessthan_lessthan, t_greaterthan, t_greaterthan_equals, t_greaterthan_greaterthan, t_emark_equals, t_equals_equals, // logical operators: t_vbar_vbar, t_ampersand_ampersand, // misc: t_emark, t_qmark, t_colon, t_equals, t_comma, t_EOF, number_of_tokens, }; static const char* const tokennames[number_of_tokens] = { [t_EOF] = "EOF", [t_identifier] = "identifier", [t_literal] = "literal", [t_binary] = "binary-literal", [t_hexadecimal] = "hexadecimal-literal", [t_oparen] = "open parentheses", [t_cparen] = "close parentheses", [t_plus] = "plus", [t_minus] = "minus", [t_asterisk] = "asterisk", [t_asterisk_asterisk] = "double-asterisk", [t_percent] = "percent", [t_slash] = "slash", [t_slash_slash] = "double-slash", [t_lessthan] = "less-than", [t_lessthan_equals] = "less-than-or-equal-to", [t_greaterthan] = "greater-than", [t_greaterthan_equals] = "greater-than-or-equal-to", [t_emark_equals] = "not-equal-to", [t_equals_equals] = "equal-to", [t_vbar_vbar] = "logical-or", [t_ampersand_ampersand] = "logical-and", [t_emark] = "exclamation mark", [t_qmark] = "question mark", [t_colon] = "colon", [t_equals] = "assignment", [t_comma] = "comma", }; struct tokenizer { const char* text; unsigned start_index; unsigned index; enum token token; struct buffer { char* data; size_t n, cap; } buffer; }; struct tokenizer* new_tokenizer(const char* text) { struct tokenizer* this = malloc(sizeof(*this)); this->text = text; this->start_index = 0; this->index = 0; this->token = t_uninitialized; this->buffer.data = NULL; this->buffer.n = 0; this->buffer.cap = 0; return this; } void tokenizer_append_char( struct tokenizer* this, char code) { if (this->buffer.n == this->buffer.cap) { this->buffer.cap = this->buffer.cap << 1 ?: 1; this->buffer.data = realloc( this->buffer.data, sizeof(*this->buffer.data) * this->buffer.cap); } this->buffer.data[this->buffer.n++] = code; } enum tokenizer_state { ts_error, ts_EOF, ts_literal, ts_identifier, ts_equals, ts_comma, ts_slash, ts_plus, ts_minus, ts_qmark, ts_emark, ts_colon, ts_percent, ts_asterisk, ts_asterisk_asterisk, ts_lessthan, ts_lessthan_equals, ts_lessthan_lessthan, ts_greaterthan, ts_greaterthan_equals, ts_greaterthan_greaterthan, ts_equals_equals, ts_slash_slash, ts_oparen, ts_cparen, ts_vbar_vbar, ts_start, ts_reading_literal_prefix, ts_reading_literal, ts_reading_literal2, ts_reading_literal_binary, ts_reading_literal_binary2, ts_reading_literal_hexadecimal, ts_reading_literal_hexadecimal2, ts_reading_identifier, ts_reading_equals, ts_reading_equals_equals, ts_reading_slash, ts_reading_slash_slash, ts_reading_comma, ts_reading_plus, ts_reading_minus, ts_reading_qmark, ts_reading_emark, ts_reading_colon, ts_reading_asterisk, ts_reading_asterisk_asterisk, ts_reading_percent, ts_reading_lessthan, ts_reading_lessthan_equals, ts_reading_lessthan_lessthan, ts_reading_greaterthan, ts_reading_greaterthan_equals, ts_reading_greaterthan_greaterthan, ts_reading_oparen, ts_reading_cparen, ts_reading_vbar, ts_reading_vbar_vbar, number_of_tokenizer_states, } tokenizer_lookup[number_of_tokenizer_states][128] = { #define ANY 0 ... 127 // skip whitespace: [ts_start][' '] = ts_start, // EOF token: [ts_start][0] = ts_EOF, // binary: "0b" ['_', '0', '1']+ ('.' ['_', '0', '1']*)? // hexadecimal: "0x" [_0-9a-fA-F]+ (.[_0-9a-fA-F]*)? // literal: [0-9]+ [_0-9]* (. [_0-9]*)? [ts_start]['0'] = ts_reading_literal_prefix, [ts_reading_literal_prefix][ANY] = ts_literal, [ts_reading_literal_prefix]['b'] = ts_reading_literal_binary, [ts_reading_literal_binary][ ANY ] = ts_literal, [ts_reading_literal_binary]['0' ... '1'] = ts_reading_literal_binary, [ts_reading_literal_binary][ '_' ] = ts_reading_literal_binary, [ts_reading_literal_binary][ '.' ] = ts_reading_literal_binary2, [ts_reading_literal_binary2][ ANY ] = ts_literal, [ts_reading_literal_binary2][ '_' ] = ts_reading_literal_binary2, [ts_reading_literal_binary2]['0' ... '1'] = ts_reading_literal_binary2, [ts_reading_literal_prefix]['x'] = ts_reading_literal_hexadecimal, [ts_reading_literal_hexadecimal][ ANY ] = ts_literal, [ts_reading_literal_hexadecimal]['0' ... '9'] = ts_reading_literal_hexadecimal, [ts_reading_literal_hexadecimal]['a' ... 'f'] = ts_reading_literal_hexadecimal, [ts_reading_literal_hexadecimal]['A' ... 'F'] = ts_reading_literal_hexadecimal, [ts_reading_literal_hexadecimal][ '_' ] = ts_reading_literal_hexadecimal, [ts_reading_literal_hexadecimal][ '.' ] = ts_reading_literal_hexadecimal2, [ts_reading_literal_hexadecimal2][ ANY ] = ts_literal, [ts_reading_literal_hexadecimal2][ '_' ] = ts_reading_literal_hexadecimal2, [ts_reading_literal_hexadecimal2]['0' ... '9'] = ts_reading_literal_hexadecimal2, [ts_reading_literal_hexadecimal2]['a' ... 'f'] = ts_reading_literal_hexadecimal2, [ts_reading_literal_hexadecimal2]['A' ... 'F'] = ts_reading_literal_hexadecimal2, [ts_reading_literal_prefix]['_'] = ts_reading_literal, [ts_reading_literal_prefix]['.'] = ts_reading_literal2, [ts_reading_literal_prefix]['0' ... '9'] = ts_reading_literal, [ts_start]['1' ... '9'] = ts_reading_literal, [ts_reading_literal][ ANY ] = ts_literal, [ts_reading_literal][ '_' ] = ts_reading_literal, [ts_reading_literal]['0' ... '9'] = ts_reading_literal, [ts_reading_literal]['a' ... 'z'] = ts_error, [ts_reading_literal][ '.' ] = ts_reading_literal2, [ts_reading_literal2][ ANY ] = ts_literal, [ts_reading_literal2][ '_' ] = ts_reading_literal2, [ts_reading_literal2]['0' ... '9'] = ts_reading_literal2, // identifiers: [ts_start][ '_' ] = ts_reading_identifier, [ts_start]['a' ... 'z'] = ts_reading_identifier, [ts_reading_identifier][ ANY ] = ts_identifier, [ts_reading_identifier][ '_' ] = ts_reading_identifier, [ts_reading_identifier]['0' ... '9'] = ts_reading_identifier, [ts_reading_identifier]['a' ... 'z'] = ts_reading_identifier, // symbols: [ts_start]['+'] = ts_reading_plus, [ts_reading_plus][ANY] = ts_plus, [ts_start]['-'] = ts_reading_minus, [ts_reading_minus][ANY] = ts_minus, [ts_start]['%'] = ts_reading_percent, [ts_reading_percent][ANY] = ts_percent, [ts_start]['?'] = ts_reading_qmark, [ts_reading_qmark][ANY] = ts_qmark, [ts_start]['!'] = ts_reading_emark, [ts_reading_emark][ANY] = ts_emark, [ts_start][':'] = ts_reading_colon, [ts_reading_colon][ANY] = ts_colon, [ts_start][','] = ts_reading_comma, [ts_reading_comma][ANY] = ts_comma, [ts_start]['('] = ts_reading_oparen, [ts_reading_oparen][ANY] = ts_oparen, [ts_start][')'] = ts_reading_cparen, [ts_reading_cparen][ANY] = ts_cparen, // '*' or '**' [ts_start]['*'] = ts_reading_asterisk, [ts_reading_asterisk][ANY] = ts_asterisk, [ts_reading_asterisk]['*'] = ts_reading_asterisk_asterisk, [ts_reading_asterisk_asterisk][ANY] = ts_asterisk_asterisk, // '/' or '//': [ts_start]['/'] = ts_reading_slash, [ts_reading_slash][ANY] = ts_slash, [ts_reading_slash]['/'] = ts_reading_slash_slash, [ts_reading_slash_slash][ANY] = ts_slash_slash, // '=' or '==': [ts_start]['='] = ts_reading_equals, [ts_reading_equals][ANY] = ts_equals, [ts_reading_equals]['='] = ts_reading_equals_equals, [ts_reading_equals_equals][ANY] = ts_equals_equals, // '<' or '<=' or '<<': [ts_start]['<'] = ts_reading_lessthan, [ts_reading_lessthan][ANY] = ts_lessthan, [ts_reading_lessthan]['='] = ts_reading_lessthan_equals, [ts_reading_lessthan_equals][ANY] = ts_lessthan_equals, [ts_reading_lessthan]['<'] = ts_reading_lessthan_lessthan, [ts_reading_lessthan_lessthan][ANY] = ts_lessthan_lessthan, // '>' or '>=' or '>>': [ts_start]['>'] = ts_reading_greaterthan, [ts_reading_greaterthan][ANY] = ts_greaterthan, [ts_reading_greaterthan]['='] = ts_reading_greaterthan_equals, [ts_reading_greaterthan_equals][ANY] = ts_greaterthan_equals, [ts_reading_greaterthan]['>'] = ts_reading_greaterthan_greaterthan, [ts_reading_greaterthan_greaterthan][ANY] = ts_greaterthan_greaterthan, // '||': [ts_start]['|'] = ts_reading_vbar, [ts_reading_vbar]['|'] = ts_reading_vbar_vbar, [ts_reading_vbar_vbar][ANY] = ts_vbar_vbar, }; void tokenizer_next( struct tokenizer* this) { this->buffer.n = 0; this->start_index = this->index; enum tokenizer_state state = ts_start; while (state >= ts_start) { assert(this->text[this->index] >= 0); state = tokenizer_lookup[state][(uint8_t) this->text[this->index]]; if (state > ts_start) { tokenizer_append_char(this, this->text[this->index]); this->index++; } if (state == ts_start) { this->buffer.n = 0; this->index++; this->start_index = this->index; } } // for sake of the error message: if (state == ts_error) { tokenizer_append_char(this, this->text[this->index]); } tokenizer_append_char(this, '\0'); switch (state) { case ts_error: { this->token = t_error; break; } case ts_EOF: { this->token = t_EOF; break; } case ts_literal: { this->token = t_literal; break; } case ts_identifier: { this->token = t_identifier; break; } case ts_equals: { this->token = t_equals; break; } case ts_comma: { this->token = t_comma; break; } case ts_plus: { this->token = t_plus; break; } case ts_qmark: { this->token = t_qmark; break; } case ts_minus: { this->token = t_minus; break; } case ts_slash: { this->token = t_slash; break; } case ts_equals_equals: { this->token = t_equals_equals; break; } case ts_emark: { this->token = t_emark; break; } case ts_oparen: { this->token = t_oparen; break; } case ts_cparen: { this->token = t_cparen; break; } case ts_percent: { this->token = t_percent; break; } case ts_lessthan: { this->token = t_lessthan; break; } case ts_lessthan_equals: { this->token = t_lessthan_equals; break; } case ts_colon: { this->token = t_colon; break; } case ts_asterisk: { this->token = t_asterisk; break; } case ts_vbar_vbar: { this->token = t_vbar_vbar; break; } case ts_slash_slash: { this->token = t_slash_slash; break; } case ts_lessthan_lessthan: { this->token = t_lessthan_lessthan; break; } case ts_greaterthan_greaterthan: { this->token = t_greaterthan_greaterthan; break; } case ts_asterisk_asterisk: { this->token = t_asterisk_asterisk; break; } default: TODO; break; } } void free_tokenizer( struct tokenizer* this) { free(this->buffer.data); free(this); } struct string* make_unexpected_token_message( struct tokenizer* tokenizer) { if (tokenizer->token == t_error) { return new_string_from_fmt( "unexpected unknown token '%s'", tokenizer->buffer.data); } else { assert(tokennames[tokenizer->token]); return new_string_from_fmt( "unexpected %s token", tokennames[tokenizer->token]); } } struct expression* parse_root(struct tokenizer* tokenizer); struct expression* parse_primary(struct tokenizer* tokenizer) { struct expression* retval = NULL; switch (tokenizer->token) { case t_error: { struct string* message = new_string_from_fmt( "unknown token '%s'", tokenizer->buffer.data); retval = new_syntax_error_expression( /* column: */ tokenizer->start_index + 1, /* message: */ message); tokenizer_next(tokenizer); free_string(message); break; } case t_literal: { struct value* value = scan(tokenizer->buffer.data); retval = new_literal_expression(value); tokenizer_next(tokenizer); free_value(value); break; } case t_hexadecimal: { TODO; break; } case t_identifier: { struct string* name = new_string(tokenizer->buffer.data); retval = new_variable_expression(name); tokenizer_next(tokenizer); free_string(name); break; } case t_oparen: { tokenizer_next(tokenizer); struct expression* sub = parse_root(tokenizer); if (sub->kind == ek_syntax_error) { retval = inc_expression(sub); } else if (tokenizer->token == t_cparen) { tokenizer_next(tokenizer); retval = inc_expression(sub); } else { TODO; } free_expression(sub); break; } default: { struct string* message = make_unexpected_token_message(tokenizer); retval = new_syntax_error_expression( /* column: */ tokenizer->start_index + 1, /* message: */ message); tokenizer_next(tokenizer); free_string(message); break; } } assert(retval); return retval; } struct expression* parse_prefix(struct tokenizer* tokenizer) { struct expression* retval = NULL; switch (tokenizer->token) { case t_emark: { tokenizer_next(tokenizer); struct expression* sub = parse_prefix(tokenizer); if (sub->kind == ek_syntax_error) { retval = sub; } else { TODO; #if 0 struct expression* retval = new_logical_not_expression(sub); free_expression(sub); return retval; #endif } break; } case t_plus: { tokenizer_next(tokenizer); struct expression* sub = parse_prefix(tokenizer); if (sub->kind == ek_syntax_error) { retval = sub; } else { TODO; #if 0 retval = new_positive_expression(sub); free_expression(sub); #endif } break; } case t_minus: { tokenizer_next(tokenizer); struct expression* sub = parse_prefix(tokenizer); if (sub->kind == ek_syntax_error) { retval = inc_expression(sub); } else { retval = new_negative_expression(sub); } free_expression(sub); break; } default: { retval = parse_primary(tokenizer); break; } } assert(retval); return retval; } struct expression* parse_exponent(struct tokenizer* tokenizer) { struct expression* left = parse_prefix(tokenizer); while (true && left->kind != ek_syntax_error && (tokenizer->token == t_asterisk_asterisk)) { tokenizer_next(tokenizer); struct expression* right = parse_prefix(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_exponent, left, right); left = retval; } free_expression(right); } return left; } struct expression* parse_multiplicative(struct tokenizer* tokenizer) { struct expression* left = parse_exponent(tokenizer); while (true && left->kind != ek_syntax_error && (false || tokenizer->token == t_asterisk || tokenizer->token == t_slash || tokenizer->token == t_slash_slash || tokenizer->token == t_percent)) { switch (tokenizer->token) { case t_asterisk: { tokenizer_next(tokenizer); struct expression* right = parse_exponent(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_multiply, left, right); left = retval; } free_expression(right); break; } case t_slash: { tokenizer_next(tokenizer); struct expression* right = parse_exponent(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_divide, left, right); free_expression(left); left = retval; } free_expression(right); break; } case t_slash_slash: { tokenizer_next(tokenizer); struct expression* right = parse_exponent(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_integer_divide, left, right); free_expression(left); left = retval; } free_expression(right); break; } case t_percent: { tokenizer_next(tokenizer); struct expression* right = parse_exponent(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_remainder, left, right); free_expression(left); left = retval; } free_expression(right); break; } default: break; } } return left; } struct expression* parse_additive(struct tokenizer* tokenizer) { struct expression* left = parse_multiplicative(tokenizer); while (true && left->kind != ek_syntax_error && (false || tokenizer->token == t_plus || tokenizer->token == t_minus)) { switch (tokenizer->token) { case t_plus: { tokenizer_next(tokenizer); struct expression* right = parse_multiplicative(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = right; } else { struct expression* retval = new_binary_expression(ek_add, left, right); free_expression(left); free_expression(right); left = retval; } break; } case t_minus: { tokenizer_next(tokenizer); struct expression* right = parse_multiplicative(tokenizer); if (right->kind == ek_syntax_error) { TODO; } else { struct expression* retval = new_binary_expression(ek_subtract, left, right); free_expression(left); left = retval; } free_expression(right); break; } default: TODO; break; } } return left; } struct expression* parse_shift(struct tokenizer* tokenizer) { struct expression* left = parse_additive(tokenizer); while (true && left->kind != ek_syntax_error && (false || tokenizer->token == t_lessthan_lessthan || tokenizer->token == t_greaterthan_greaterthan)) { switch (tokenizer->token) { case t_lessthan_lessthan: { tokenizer_next(tokenizer); struct expression* right = parse_additive(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = right; } else { struct expression* retval = new_binary_expression(ek_leftbitshift, left, right); free_expression(left); free_expression(right); left = retval; } break; } case t_greaterthan_greaterthan: { tokenizer_next(tokenizer); struct expression* right = parse_additive(tokenizer); if (right->kind == ek_syntax_error) { TODO; } else { struct expression* retval = new_binary_expression(ek_rightbitshift, left, right); free_expression(left); left = retval; } free_expression(right); break; } default: TODO; break; } } return left; } struct expression* parse_comparision(struct tokenizer* tokenizer) { struct expression* left = parse_shift(tokenizer); while (true && left->kind != ek_syntax_error && (false || tokenizer->token == t_lessthan || tokenizer->token == t_lessthan_equals || tokenizer->token == t_greaterthan || tokenizer->token == t_greaterthan_equals)) { switch (tokenizer->token) { case t_lessthan: { tokenizer_next(tokenizer); struct expression* right = parse_shift(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_less_than, left, right); free_expression(left); left = retval; } free_expression(right); break; } case t_lessthan_equals: { tokenizer_next(tokenizer); struct expression* right = parse_additive(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_less_than_equal_to, left, right); free_expression(left); left = retval; } free_expression(right); break; } case t_greaterthan: { TODO; #if 0 next_token(); struct expression* right = parse_additive(); struct expression* retval = new_binary_expression(ek_greater_than, left, right); free_expression(left); free_expression(right); left = retval; goto again; #endif } case t_greaterthan_equals: { TODO; #if 0 next_token(); struct expression* right = parse_additive(); struct expression* retval = new_binary_expression(ek_greater_than_equal_to, left, right); free_expression(left); free_expression(right); left = retval; goto again; #endif } default: break; } } return left; } struct expression* parse_equality(struct tokenizer* tokenizer) { struct expression* left = parse_comparision(tokenizer); while (true && left->kind != ek_syntax_error && (false || tokenizer->token == t_equals_equals || tokenizer->token == t_emark_equals)) { switch (tokenizer->token) { case t_equals_equals: { tokenizer_next(tokenizer); struct expression* right = parse_comparision(tokenizer); if (right->kind == ek_syntax_error) { free_expression(left); left = inc_expression(right); } else { struct expression* retval = new_binary_expression(ek_equal_to, left, right); free_expression(left); left = retval; } free_expression(right); break; } case t_emark_equals: { TODO; #if 0 next_token(); struct expression* right = parse_comparision(); struct expression* retval = new_binary_expression(ek_not_equal_to, left, right); free_expression(left); free_expression(right); left = retval; goto again; #endif } default: break; } } return left; } struct expression* parse_logical_and(struct tokenizer* tokenizer) { struct expression* left = parse_equality(tokenizer); while (tokenizer->token == t_ampersand_ampersand) { TODO; } return left; } struct expression* parse_logical_or(struct tokenizer* tokenizer) { struct expression* left = parse_logical_and(tokenizer); while (tokenizer->token == t_vbar_vbar) { tokenizer_next(tokenizer); struct expression* right = parse_comparision(tokenizer); struct expression* retval = new_binary_expression(ek_logical_or, left, right); free_expression(left); free_expression(right); left = retval; } return left; } struct expression* parse_ternary(struct tokenizer* tokenizer) { struct expression* center = parse_logical_or(tokenizer); while (true && center->kind != ek_syntax_error && tokenizer->token == t_qmark) { tokenizer_next(tokenizer); struct expression* left = parse_root(tokenizer); if (left->kind == ek_syntax_error) { free_expression(center); center = inc_expression(left); } else if (tokenizer->token == t_colon) { tokenizer_next(tokenizer); struct expression* right = parse_logical_or(tokenizer); if (right->kind == ek_syntax_error) { free_expression(center); center = inc_expression(right); } else { struct expression* new = new_ternary_expression(center, left, right); free_expression(center); center = new; } free_expression(right); } else { struct string* message = make_unexpected_token_message(tokenizer); struct expression* error = new_syntax_error_expression( tokenizer->start_index + 1, message); free_expression(center); center = error; tokenizer_next(tokenizer); free_string(message); } free_expression(left); } return center; } struct expression* parse_assign(struct tokenizer* tokenizer) { struct expression* left = parse_ternary(tokenizer); if (tokenizer->token == t_equals) { tokenizer_next(tokenizer); struct expression* right = parse_assign(tokenizer); struct expression* retval = new_binary_expression(ek_assign, left, right); free_expression(left); free_expression(right); return retval; } return left; } struct expression* parse_comma(struct tokenizer* tokenizer) { struct expression* left = parse_assign(tokenizer); while (tokenizer->token == t_comma) { tokenizer_next(tokenizer); struct expression* right = parse_assign(tokenizer); struct expression* retval = new_binary_expression(ek_comma, left, right); free_expression(left); free_expression(right); left = retval; } return left; } struct expression* parse_root(struct tokenizer* tokenizer) { return parse_comma(tokenizer); } struct expression* parse(const char* text) { struct tokenizer* tokenizer = new_tokenizer(text); tokenizer_next(tokenizer); struct expression* root = parse_root(tokenizer); if (root->kind != ek_syntax_error && tokenizer->token != t_EOF) { struct string* message = make_unexpected_token_message(tokenizer); struct expression* error = new_syntax_error_expression( tokenizer->index + 1, message); free_expression(root); root = error; free_string(message); } free_tokenizer(tokenizer); return root; } #if 0 struct value** evaluate_lvalue( struct expression* expression, struct scope* scope) { switch (expression->kind) { case ek_syntax_error: assert(0); break; case ek_variable: { return scope_lookup(scope, expression->string); } case ek_literal: TODO; break; case ek_add: TODO; break; case ek_subtract: TODO; break; case ek_multiply: TODO; break; case ek_divide: TODO; break; case ek_positive: TODO; break; case ek_negative: TODO; break; case ek_greater_than: TODO; break; case ek_greater_than_equal_to: TODO; break; case ek_less_than: TODO; break; case ek_less_than_equal_to: TODO; break; case ek_equal_to: TODO; break; case ek_not_equal_to: TODO; break; case ek_logical_not: TODO; break; case ek_logical_and: TODO; break; case ek_logical_or: TODO; break; case ek_ternary: TODO; break; case ek_remainder: TODO; break; case ek_assign: { TODO; break; }; case ek_comma: { TODO; break; }; } return NULL; } #endif struct value* evaluate( struct expression* expression, struct scope* scope) { struct value* retval = NULL; switch (expression->kind) { case ek_syntax_error: assert(0); break; case ek_variable: { struct value* val = *scope_lookup(scope, expression->string); if (val) { retval = inc_value(val); } else { retval = new_error_value_from_fmt( "error: use of undefined variable '%s'!", expression->string->data); } break; }; case ek_literal: { retval = inc_value(expression->value); break; } case ek_add: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_unionnew_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { TODO; } else if (right->kind == vk_error) { TODO; } else { mpq_t q; mpq_init(q); mpq_add(q, left->mpq, right->mpq); retval = new_value(q); mpq_clear(q); } free_value(left), free_value(right); break; } case ek_subtract: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { TODO; } else if (right->kind == vk_error) { TODO; } else { TODO; #if 0 mpq_t q; mpq_init(q); mpq_sub(q, left->mpq, right->mpq); retval = new_value(q); mpq_clear(q); #endif } free_value(left); free_value(right); break; } case ek_multiply: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else { TODO; #if 0 mpq_t q; mpq_init(q); mpq_mul(q, left->mpq, right->mpq); retval = new_value(q); mpq_clear(q); #endif } free_value(left), free_value(right); break; } case ek_integer_divide: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else { mpq_t q; mpq_init(q); mpq_div(q, left->mpq, right->mpq); mpz_tdiv_q(mpq_numref(q), mpq_numref(q), mpq_denref(q)); mpz_set_si(mpq_denref(q), 1); retval = new_value(q); mpq_clear(q); } free_value(left), free_value(right); break; } case ek_rightbitshift: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { retval = new_error_value_from_union(left, right); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0) { if (mpq_sgn(right->mpq) > 0) { if (mpz_fits_ulong_p(mpq_numref(right->mpq))) { unsigned long r = mpz_get_ui(mpq_numref(right->mpq)); mpq_t q; mpq_init(q); mpq_div_2exp(q, left->mpq, r); retval = new_value(q); mpq_clear(q); } else { retval = new_error_value_from_fmt( "error: cannot right bitshift beyond ULONG_MAX"); } } else { retval = new_error_value_from_fmt( "error: cannot right bitshift by a negative value"); } } else { retval = new_error_value_from_fmt( "error: cannot right bitshift by a fractional value"); } free_value(left), free_value(right); break; } case ek_leftbitshift: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { retval = new_error_value_from_union(left, right); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0) { if (mpq_sgn(right->mpq) > 0) { if (mpz_fits_ulong_p(mpq_numref(right->mpq))) { unsigned long rshift = mpz_get_ui(mpq_numref(right->mpq)); mpq_t q; mpq_init(q); mpq_mul_2exp(q, left->mpq, rshift); retval = new_value(q); mpq_clear(q); } else { retval = new_error_value_from_fmt( "error: cannot left bitshift beyond ULONG_MAX"); } } else { retval = new_error_value_from_fmt( "error: cannot left bitshift by a negative value"); } } else { retval = new_error_value_from_fmt( "error: cannot left bitshift by fractional value"); } free_value(left), free_value(right); break; } case ek_exponent: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { retval = new_error_value_from_union(left, right); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else if (mpz_cmp_si(mpq_denref(right->mpq), 1) == 0) { if (mpq_sgn(right->mpq) > 0) { if (mpz_fits_ulong_p(mpq_numref(right->mpq))) { unsigned long rpow = mpz_get_ui(mpq_numref(right->mpq)); mpz_t n, d; mpz_init(n), mpz_init(d); mpz_pow_ui(n, mpq_numref(left->mpq), rpow); mpz_pow_ui(d, mpq_denref(left->mpq), rpow); mpq_t q, t; mpq_init(q), mpq_init(t); mpq_set_z(q, n); mpq_set_z(t, d); mpq_div(q, q, t); retval = new_value(q); mpq_clear(q), mpq_clear(t); } else { retval = new_error_value_from_fmt( "error: cannot exponentiate beyond ULONG_MAX"); } } else { retval = new_error_value_from_fmt( "error: negative exponents not supported"); } } else { retval = new_error_value_from_fmt( "error: cannot exponentiate by a fraction"); } free_value(left), free_value(right); break; } case ek_divide: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else { TODO; #if 0 mpq_t q; mpq_init(q); mpq_div(q, left->mpq, right->mpq); retval = new_value(q); mpq_clear(q); #endif } free_value(left), free_value(right); break; } case ek_remainder: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { retval = inc_value(left); } else if (right->kind == vk_error) { retval = inc_value(right); } else { mpq_t q; mpq_init(q); // (x % y) => x - (x // y) * y mpq_div(q, left->mpq, right->mpq); mpz_tdiv_q(mpq_numref(q), mpq_numref(q), mpq_denref(q)); mpz_set_si(mpq_denref(q), 1); mpq_mul(q, q, right->mpq); mpq_sub(q, left->mpq, q); retval = new_value(q); mpq_clear(q); } free_value(left), free_value(right); break; } case ek_positive: { retval = evaluate(expression->center, scope); break; } case ek_negative: { struct value* sub = evaluate(expression->center, scope); if (sub->kind == vk_error) { TODO; } else { mpq_t q; mpq_init(q); mpq_neg(q, sub->mpq); retval = new_value(q); free_value(sub); mpq_clear(q); } break; } case ek_greater_than: { TODO; #if 0 struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) > 0); free_value(left), free_value(right); #endif break; } case ek_greater_than_equal_to: { TODO; #if 0 struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) >= 0); free_value(left), free_value(right); break; #endif } case ek_less_than: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { TODO; } else if (right->kind == vk_error) { TODO; } else { retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) < 0); } free_value(left), free_value(right); break; } case ek_less_than_equal_to: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { TODO; } else if (right->kind == vk_error) { TODO; } else { retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) <= 0); } free_value(left), free_value(right); break; } case ek_equal_to: { struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); if (left->kind == vk_error && right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else if (left->kind == vk_error) { TODO; } else if (right->kind == vk_error) { TODO; } else { retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) == 0); } free_value(left), free_value(right); break; } case ek_not_equal_to: { TODO; #if 0 struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); retval = new_value_from_int(mpq_cmp(left->mpq, right->mpq) != 0); free_value(left), free_value(right); break; #endif } case ek_logical_not: { TODO; #if 0 struct value* sub = evaluate(expression->center, scope); retval = new_value_from_int(mpq_sgn(sub->mpq) == 0); free_value(sub); break; #endif } case ek_logical_and: { TODO; #if 0 struct value* left = evaluate(expression->left, scope); struct value* right = evaluate(expression->right, scope); retval = new_value_from_int( mpq_sgn(left->mpq) != 0 && mpq_sgn(right->mpq) != 0); free_value(left), free_value(right); break; #endif } case ek_logical_or: { struct value* left = evaluate(expression->left, scope); if (left->kind == vk_error) { struct value* right = evaluate(expression->right, scope); if (right->kind == vk_error) { TODO; // new_error_value_from_union struct stringset* set = new_stringset(); stringset_update(set, left->errors); stringset_update(set, right->errors); retval = new_error_value(set); free_stringset(set); } else { retval = inc_value(left); } free_value(right); } else { TODO; #if 0 struct value* right = evaluate(expression->right, scope); retval = new_value_from_int( mpq_sgn(left->mpq) != 0 || mpq_sgn(right->mpq) != 0); free_value(left), free_value(right); break; #endif } free_value(left); break; } case ek_ternary: { struct value* conditional = evaluate(expression->center, scope); if (conditional->kind == vk_error) { retval = inc_value(conditional); } else if (mpq_sgn(conditional->mpq) != 0) { retval = evaluate(expression->left, scope); } else { retval = evaluate(expression->right, scope); } free_value(conditional); break; } case ek_assign: { if (expression->left->kind == ek_variable) { struct value** lvalue = scope_lookup( scope, expression->left->string); retval = evaluate(expression->right, scope); free_value(*lvalue), *lvalue = inc_value(retval); } else { TODO; struct string* message = new_string_from_fmt( "error: cannot assign to rvalue-expressions"); struct stringset* set = new_stringset(); stringset_add(set, message); retval = new_error_value(set); free_stringset(set); free_string(message); } break; }; case ek_comma: { TODO; #if 0 free_value(evaluate(expression->left, scope)); retval = evaluate(expression->right, scope); break; #endif }; } return retval; } void print_mpz(const mpz_t x_ro, const char* digits[10]) { assert(mpz_sgn(x_ro) > 0); mpz_t x, d, b; mpz_init(x), mpz_init(d), mpz_init(b); mpz_set(x, x_ro); mpz_set_ui(b, 10); size_t n = mpz_sizeinbase(x, 10); unsigned *buffer = malloc(sizeof(*buffer) * n); unsigned *moving = buffer; while (mpz_sgn(x)) { mpz_fdiv_qr(x, d, x, b); assert(mpz_fits_uint_p(d)); unsigned int diu = (unsigned int) mpz_get_ui(d); assert(diu < 10); *moving++ = diu; } while (moving > buffer) { printf("%s", digits[*--moving]); } free(buffer); mpz_clear(x), mpz_clear(d), mpz_clear(b); } void print(struct value* this) { switch (this->kind) { case vk_error: { stringset_println(this->errors); break; } case vk_number: { mpq_t v; mpq_init(v); mpq_set(v, this->mpq); if (mpq_sgn(v) == 0) { putchar('0'); } else { if (mpq_sgn(v) < 0) { putchar('-'); mpq_abs(v, v); } mpz_t q; mpz_init(q); mpz_fdiv_q(q, mpq_numref(v), mpq_denref(v)); if (mpz_sgn(q) > 0) { print_mpz(q, (const char*[10]){"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}); putchar(' '); } mpq_t qq; mpq_init(qq); mpq_set_z(qq, q); mpq_sub(v, v, qq); if (mpq_sgn(v) > 0) { print_mpz(mpq_numref(v), (const char*[10]){"⁰", "¹", "²", "³", "⁴", "⁵", "⁶", "⁷", "⁸", "⁹"}); putchar('/'); print_mpz(mpq_denref(v), (const char*[10]){"₀", "₁", "₂", "₃", "₄", "₅", "₆", "₇", "₈", "₉"}); } mpq_clear(qq); mpz_clear(q); } mpq_clear(v); puts(""); break; } } } void syntax_error_print( const struct expression* this) { assert(this->kind == ek_syntax_error); printf("%*s↑\n", this->column - 1, ""); printf("%*s└ %s\n", this->column - 1, "", this->string->data); } int main(int argc, char* const* argv) { int retval = 0; parse_args(argc, argv); if (command) { struct scope* scope = new_scope(); struct expression* expression = parse(command); if (expression->kind == ek_syntax_error) { printf("syntax error!\n"); printf("%s\n", command); syntax_error_print(expression); retval = 1; } else { struct value* value = evaluate(expression, scope); print(value); free_value(value); } free_expression(expression); free_scope(scope); } else { struct scope* scope = new_scope(); for (char* line; (line = readline(">>> ")); free(line)) { if (!*line) continue; add_history(line); struct expression* expression = parse(line); struct value* value = evaluate(expression, scope); TODO; // switch on value kind // print(value); free_value(value); free_expression(expression); } free_scope(scope); } return retval; }