diff --git a/main.c b/main.c index 18626ca..5c2e452 100644 --- a/main.c +++ b/main.c @@ -16,6 +16,13 @@ #define argv0 program_invocation_name +// Function to print a 16-bit value in binary format +static void print_binary(uint16_t value) { + for (int bit = 15; bit >= 0; bit--) { + printf("%d", (value >> bit) & 1); + } +} + #ifdef ZDEBUG #define zprintf(fmt, ...) \ printf(fmt, ## __VA_ARGS__); @@ -380,241 +387,247 @@ static void print(uint16_t truthtable, int depth) } } +// Data structures for the simplification algorithm +struct todo_heap { + uint16_t data[N]; + int n; + + // truthtable -> index in 'todo' + int reverse[N]; +}; + +struct done_list { + int headtails[N], next[N], head; + + // for debugging: + #if ZDEBUG + bool in[N]; + #endif +}; + +// Forward declarations of helper functions +static uint16_t simplifier_pop(struct todo_heap* todo); +static void simplifier_append(struct todo_heap* todo, uint16_t truthtable, int cost); +static void simplifier_update(struct todo_heap* todo, uint16_t truthtable, int cost); +static void simplifier_insert(struct done_list* done, int index); + +// Pop the smallest cost item from the heap +static uint16_t simplifier_pop(struct todo_heap* todo) +{ + assert(todo->n > 0); + + uint16_t retval = todo->data[0]; + + todo->reverse[retval] = -1; + + uint16_t moving = todo->data[todo->n-- - 1]; + + int cost = lookup[moving].cost; + + int index = 0; + + again: + { + int left = index * 2 + 1; + int right = index * 2 + 2; + + uint16_t smallest = moving; + + if (left < todo->n && lookup[todo->data[left]].cost < cost) + smallest = todo->data[left]; + + if (right < todo->n && lookup[todo->data[right]].cost < lookup[smallest].cost) + smallest = todo->data[right]; + + if (smallest == moving) + { + todo->data[index] = moving; + + todo->reverse[moving] = index; + } + else + { + int new_index = todo->reverse[smallest]; + + todo->data[index] = smallest; + + todo->reverse[smallest] = index; + + index = new_index; + + goto again; + } + } + + return retval; +} + +// Append a new item to the heap +static void simplifier_append(struct todo_heap* todo, uint16_t truthtable, int cost) +{ + assert(todo->reverse[truthtable] == -1); + + int index = todo->n++, new_index; + + while (index > 0 && lookup[todo->data[new_index = (index - 1) / 2]].cost > cost) + { + todo->data[index] = todo->data[new_index]; + + todo->reverse[todo->data[new_index]] = index; + + index = new_index; + } + + todo->data[index] = truthtable; + + todo->reverse[truthtable] = index; + + lookup[truthtable].cost = cost; +} + +// Update an existing item in the heap +static void simplifier_update(struct todo_heap* todo, uint16_t truthtable, int cost) +{ + assert(todo->reverse[truthtable] != -1); + + assert(cost < lookup[truthtable].cost); + + int index = todo->reverse[truthtable], new_index; + + while (index > 0 && lookup[todo->data[new_index = (index - 1) / 2]].cost > cost) + { + todo->data[index] = todo->data[new_index]; + + todo->reverse[todo->data[new_index]] = index; + + index = new_index; + } + + todo->data[index] = truthtable; + todo->reverse[truthtable] = index; + + lookup[truthtable].cost = cost; +} + +// Insert an item into the done list +static void simplifier_insert(struct done_list* done, int index) +{ + #if ZDEBUG + assert(!done->in[index]); + #endif + + int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1; + + while (done->headtails[head] == -1 || index < done->headtails[head]) + { + done->headtails[head] = index; + + prevhead = head, head = head & ~(head & -head); + } + + if (done->headtails[head] < index) + { + if (prevhead == -1) + { + assert(done->headtails[head] == head); + + done->next[head] = index; + } + else + { + int tophalftail = done->headtails[prevhead - 1]; + + assert(tophalftail != -1); + + done->next[tophalftail] = index; + } + } + else + { + done->head = index; + } + + int n = ~index & M; + int tail = index & 1 ? index : index | (n & -n), prevtail = -1; + + while (done->headtails[tail] == -1 || done->headtails[tail] < index) + { + done->headtails[tail] = index; + + prevtail = tail, tail = tail | (n = ~tail & M, n & -n); + } + + if (index < done->headtails[tail]) + { + if (prevtail == -1) + { + assert(done->headtails[tail] == tail); + + #if ZDEBUG + assert(done->in[tail]); + #endif + + done->next[index] = tail; + } + else + { + int bottomhalfhead = done->headtails[prevtail + 1]; + + assert(bottomhalfhead != -1); + + done->next[index] = bottomhalfhead; + } + } + else + { + done->next[index] = -1; + } + + #if ZDEBUG + done->in[index] = true; + #endif +} + void calculate_simplifications(void) { // init 'lookup': + for (int i = 0; i < N; i++) { - for (int i = 0; i < N; i++) - { - lookup[i].kind = ek_unreachable; - - lookup[i].cost = INT_MAX; - } + lookup[i].kind = ek_unreachable; + lookup[i].cost = INT_MAX; } // heap of truthtables; key = cost - struct { - uint16_t data[N]; - int n; - - // truthtable -> index in 'todo' - int reverse[N]; - } todo; + struct todo_heap todo; // init 'todo': + todo.n = 0; + for (int i = 0; i < N; i++) { - todo.n = 0; - - for (int i = 0; i < N; i++) - { - todo.reverse[i] = -1; - } - } - - uint16_t pop(void) - { - assert(todo.n > 0); - - uint16_t retval = todo.data[0]; - - todo.reverse[retval] = -1; - - uint16_t moving = todo.data[todo.n-- - 1]; - - int cost = lookup[moving].cost; - - int index = 0; - - again: - { - int left = index * 2 + 1; - int right = index * 2 + 2; - - uint16_t smallest = moving; - - if (left < todo.n && lookup[todo.data[left]].cost < cost) - smallest = todo.data[left]; - - if (right < todo.n && lookup[todo.data[right]].cost < lookup[smallest].cost) - smallest = todo.data[right]; - - if (smallest == moving) - { - todo.data[index] = moving; - - todo.reverse[moving] = index; - } - else - { - int new = todo.reverse[smallest]; - - todo.data[index] = smallest; - - todo.reverse[smallest] = index; - - index = new; - - goto again; - } - } - - return retval; - } - - void append(uint16_t truthtable, int cost) - { - assert(todo.reverse[truthtable] == -1); - - int index = todo.n++, new_index; - - while (index > 0 && lookup[todo.data[new_index = (index - 1) / 2]].cost > cost) - { - todo.data[index] = todo.data[new_index]; - - todo.reverse[todo.data[new_index]] = index; - - index = new_index; - } - - todo.data[index] = truthtable; - - todo.reverse[truthtable] = index; - - lookup[truthtable].cost = cost; - } - - void update(uint16_t truthtable, int cost) - { - assert(todo.reverse[truthtable] != -1); - - assert(cost < lookup[truthtable].cost); - - int index =todo. reverse[truthtable], new_index; - - while (index > 0 && lookup[todo.data[new_index = (index - 1) / 2]].cost > cost) - { - todo.data[index] = todo.data[new_index]; - - todo.reverse[todo.data[new_index]] = index; - - index = new_index; - } - - todo.data[index] = truthtable; - todo.reverse[truthtable] = index; - - lookup[truthtable].cost = cost; + todo.reverse[i] = -1; } // create a list of the "done" truthtables - struct { - int headtails[N], next[N], head; - - // for debugging: - #if ZDEBUG - bool in[N]; - #endif - } done = {}; + struct done_list done = {}; // init 'done': + done.head = -1; + for (int i = 0; i < N; i++) { - done.head = -1; - - for (int i = 0; i < N; i++) - { - done.headtails[i] = -1; - - #if ZDEBUG - done.in[i] = false; - #endif - } - } - - void insert(int index) - { - #if ZDEBUG - assert(!done.in[index]); - #endif - - int head = index & 1 ? index & ~(index & -index) : index, prevhead = -1; - - while (done.headtails[head] == -1 || index < done.headtails[head]) - { - done.headtails[head] = index; - - prevhead = head, head = head & ~(head & -head); - } - - if (done.headtails[head] < index) - { - if (prevhead == -1) - { - assert(done.headtails[head] == head); - - done.next[head] = index; - } - else - { - int tophalftail = done.headtails[prevhead - 1]; - - assert(tophalftail != -1); - - done.next[tophalftail] = index; - } - } - else - { - done.head = index; - } - - int n = ~index & M; - int tail = index & 1 ? index : index | (n & -n), prevtail = -1; - - while (done.headtails[tail] == -1 || done.headtails[tail] < index) - { - done.headtails[tail] = index; - - prevtail = tail, tail = tail | (n = ~tail & M, n & -n); - } - - if (index < done.headtails[tail]) - { - if (prevtail == -1) - { - assert(done.headtails[tail] == tail); - - #if ZDEBUG - assert(done.in[tail]); - #endif - - done.next[index] = tail; - } - else - { - int bottomhalfhead = done.headtails[prevtail + 1]; - - assert(bottomhalfhead != -1); - - done.next[index] = bottomhalfhead; - } - } - else - { - done.next[index] = -1; - } + done.headtails[i] = -1; #if ZDEBUG - done.in[index] = true; + done.in[i] = false; #endif } - append(W, 0), lookup[W].kind = ek_W; - append(X, 0), lookup[X].kind = ek_X; - append(Y, 0), lookup[Y].kind = ek_Y; - append(Z, 0), lookup[Z].kind = ek_Z; + simplifier_append(&todo, W, 0), lookup[W].kind = ek_W; + simplifier_append(&todo, X, 0), lookup[X].kind = ek_X; + simplifier_append(&todo, Y, 0), lookup[Y].kind = ek_Y; + simplifier_append(&todo, Z, 0), lookup[Z].kind = ek_Z; - append(0, 1), lookup[0].kind = ek_0; - append(M, 1), lookup[M].kind = ek_1; + simplifier_append(&todo, 0, 1), lookup[0].kind = ek_0; + simplifier_append(&todo, M, 1), lookup[M].kind = ek_1; // disable terminal autowrap: if (verbose && print_with_color) @@ -624,9 +637,9 @@ void calculate_simplifications(void) for (int iterations = 1; todo.n && iterations <= N; iterations++) { - uint16_t truthtable = pop(); + uint16_t truthtable = simplifier_pop(&todo); - insert(truthtable); + simplifier_insert(&done, truthtable); int cost = lookup[truthtable].cost; @@ -659,11 +672,11 @@ void calculate_simplifications(void) { if (todo.reverse[not_truthtable] == -1) { - append(not_truthtable, not_cost); + simplifier_append(&todo, not_truthtable, not_cost); } else { - update(not_truthtable, not_cost); + simplifier_update(&todo, not_truthtable, not_cost); } lookup[not_truthtable].kind = ek_not; @@ -683,9 +696,9 @@ void calculate_simplifications(void) if (bin_cost < lookup[bin_truthtable].cost) \ { \ if (todo.reverse[bin_truthtable] == -1) \ - append(bin_truthtable, bin_cost); \ + simplifier_append(&todo, bin_truthtable, bin_cost); \ else \ - update(bin_truthtable, bin_cost); \ + simplifier_update(&todo, bin_truthtable, bin_cost); \ \ lookup[bin_truthtable].kind = ekind; \ lookup[bin_truthtable].left = truthtable; \ @@ -701,9 +714,9 @@ void calculate_simplifications(void) if (bin_cost < lookup[bin_truthtable].cost) \ { \ if (todo.reverse[bin_truthtable] == -1) \ - append(bin_truthtable, bin_cost); \ + simplifier_append(&todo, bin_truthtable, bin_cost); \ else \ - update(bin_truthtable, bin_cost); \ + simplifier_update(&todo, bin_truthtable, bin_cost); \ \ lookup[bin_truthtable].kind = ekind; \ lookup[bin_truthtable].left = i; \ @@ -760,7 +773,7 @@ void calculate_simplifications(void) if (use_operators.xor) { - BINARY_OPERATOR(ek_xor, XOR); + BINARY_OPERATOR(ek_xor, XOR); } if (use_operators.nxor) @@ -770,7 +783,7 @@ void calculate_simplifications(void) if (use_operators.lt) { - BINARY_OPERATOR(ek_lt, LT); + BINARY_OPERATOR(ek_lt, LT); } if (use_operators.lte) @@ -780,7 +793,7 @@ void calculate_simplifications(void) if (use_operators.gt) { - BINARY_OPERATOR(ek_gt, GT); + BINARY_OPERATOR(ek_gt, GT); } if (use_operators.gte) @@ -805,11 +818,11 @@ void calculate_simplifications(void) { \ if (todo.reverse[ternary_truthtable] == -1) \ { \ - append(ternary_truthtable, ternary_cost); \ + simplifier_append(&todo, ternary_truthtable, ternary_cost); \ } \ else \ { \ - update(ternary_truthtable, ternary_cost); \ + simplifier_update(&todo, ternary_truthtable, ternary_cost); \ } \ \ lookup[ternary_truthtable].kind = ek_ternary; \ @@ -946,489 +959,520 @@ void get_simplifications(void) } } +// Token types enum +enum token_kind { + tk_uninitialized, + + tk_0, + tk_1, + + tk_w, + tk_x, + tk_y, + tk_z, + + tk_oparen, + tk_cparen, + + tk_emark, + tk_emarkequals, + tk_emarkvbar, + tk_emarkampersand, + + tk_equalsequals, + + tk_vbarvbar, + tk_vbaremark, + + tk_qmark, + + tk_less_than, + tk_less_than_eq, + + tk_greater_than, + tk_greater_than_eq, + + tk_ampersandemark, + tk_ampersandampersand, + + tk_colon, + + tk_EOF, +}; + +// Parser state struct to avoid globals +struct parser_state { + enum token_kind tokenkind; + const char* moving; +}; + +// Forward declarations for all parsing functions +static void next_token(struct parser_state* state); +static uint16_t parse_primary(struct parser_state* state); +static uint16_t parse_prefix(struct parser_state* state); +static uint16_t parse_compares(struct parser_state* state); +static uint16_t parse_equals(struct parser_state* state); +static uint16_t parse_ands(struct parser_state* state); +static uint16_t parse_ors(struct parser_state* state); +static uint16_t parse_ternary(struct parser_state* state); +static uint16_t parse_root(struct parser_state* state); + +// Process next token +static void next_token(struct parser_state* state) +{ + while (*state->moving && *state->moving == ' ') + state->moving++; + + switch (*state->moving) + { + case 0: + state->tokenkind = tk_EOF; + break; + + case '0': + state->tokenkind = tk_0, state->moving++; + break; + + case '1': + state->tokenkind = tk_1, state->moving++; + break; + + case 'w': + state->tokenkind = tk_w, state->moving++; + break; + + case 'x': + state->tokenkind = tk_x, state->moving++; + break; + + case 'y': + state->tokenkind = tk_y, state->moving++; + break; + + case 'z': + state->tokenkind = tk_z, state->moving++; + break; + + case '(': + state->tokenkind = tk_oparen, state->moving++; + break; + + case ')': + state->tokenkind = tk_cparen, state->moving++; + break; + + case '?': + state->tokenkind = tk_qmark, state->moving++; + break; + + case ':': + state->tokenkind = tk_colon, state->moving++; + break; + + // either '||' or '|!': + case '|': + { + state->moving++; + + switch (*state->moving) + { + case '|': + state->tokenkind = tk_vbarvbar, state->moving++; + break; + + case '!': + state->tokenkind = tk_vbaremark, state->moving++; + break; + + default: + { + puts("syntax error"); + exit(1); + break; + } + } + + break; + } + + // either '&&' or '&!': + case '&': + { + state->moving++; + + switch (*state->moving) + { + case '&': + state->tokenkind = tk_ampersandampersand, state->moving++; + break; + + case '!': + state->tokenkind = tk_ampersandemark, state->moving++; + break; + + default: + { + puts("syntax error"); + exit(1); + break; + } + } + + break; + } + + // either '!' or '!=' or '!&' or '!|' + case '!': + { + state->moving++; + + switch (*state->moving) + { + case '=': + state->tokenkind = tk_emarkequals, state->moving++; + break; + + case '|': + state->tokenkind = tk_emarkvbar, state->moving++; + break; + + case '&': + state->tokenkind = tk_emarkampersand, state->moving++; + break; + + default: + state->tokenkind = tk_emark; + break; + } + + break; + } + + case '<': + { + state->moving++; + + switch (*state->moving) + { + case '=': + state->tokenkind = tk_less_than_eq, state->moving++; + break; + + default: + { + state->tokenkind = tk_less_than; + break; + } + } + + break; + } + + case '>': + { + state->moving++; + + switch (*state->moving) + { + case '=': + state->tokenkind = tk_greater_than_eq, state->moving++; + break; + + default: + { + state->tokenkind = tk_greater_than; + break; + } + } + + break; + } + + // could only be '==': + case '=': + { + state->moving++; + + switch (*state->moving) + { + case '=': + state->tokenkind = tk_equalsequals, state->moving++; + break; + + default: + { + puts("syntax error"); + exit(1); + break; + } + } + + break; + } + + default: + assert(!"TODO"); + break; + } +} + +// Parse a primary expression (literals, variables, parenthesized expressions) +static uint16_t parse_primary(struct parser_state* state) +{ + uint16_t retval; + + switch (state->tokenkind) + { + case tk_0: + retval = 0, next_token(state); + break; + + case tk_1: + retval = M, next_token(state); + break; + + case tk_w: + retval = W, next_token(state); + break; + + case tk_x: + retval = X, next_token(state); + break; + + case tk_y: + retval = Y, next_token(state); + break; + + case tk_z: + retval = Z, next_token(state); + break; + + case tk_oparen: + { + next_token(state); + + retval = parse_root(state); + + if (state->tokenkind != tk_cparen) + { + assert(!"NOPE"); + } + + next_token(state); + break; + } + + default: + assert(!"TODO"); + break; + } + + return retval; +} + +// Parse a prefix expression (unary operators) +static uint16_t parse_prefix(struct parser_state* state) +{ + if (state->tokenkind == tk_emark) + { + next_token(state); + + return ~parse_prefix(state); + } + else + { + return parse_primary(state); + } +} + +// Parse comparison expressions (<, <=, >, >=) +static uint16_t parse_compares(struct parser_state* state) +{ + uint16_t left = parse_prefix(state); + + again: switch (state->tokenkind) + { + case tk_less_than: + { + next_token(state); + left = (~left & parse_equals(state)) & M; + goto again; + } + + case tk_less_than_eq: + { + next_token(state); + left = (~left | parse_equals(state)) & M; + goto again; + } + + case tk_greater_than_eq: + { + next_token(state); + left = (left | ~parse_equals(state)) & M; + goto again; + } + + case tk_greater_than: + { + next_token(state); + left = (left & ~parse_equals(state)) & M; + goto again; + } + + default: + break; + } + + return left; +} + +// Parse equality expressions (==, !=) +static uint16_t parse_equals(struct parser_state* state) +{ + uint16_t left = parse_compares(state); + + again: switch (state->tokenkind) + { + case tk_equalsequals: + { + next_token(state); + left = ~(left ^ parse_equals(state)) & M; + goto again; + } + + case tk_emarkequals: + { + next_token(state); + left = left ^ parse_equals(state); + goto again; + } + + default: + break; + } + + return left; +} + +// Parse AND expressions (&&, &!, !&) +static uint16_t parse_ands(struct parser_state* state) +{ + uint16_t left = parse_equals(state); + + again: switch (state->tokenkind) + { + case tk_ampersandampersand: + { + next_token(state); + left = left & parse_equals(state); + goto again; + } + + case tk_ampersandemark: + { + next_token(state); + left = ~left & parse_equals(state); + goto again; + } + + case tk_emarkampersand: + { + next_token(state); + left = ~(left & parse_equals(state)); + goto again; + } + + default: + break; + } + + return left; +} + +// Parse OR expressions (||, |!, !|) +static uint16_t parse_ors(struct parser_state* state) +{ + uint16_t left = parse_ands(state); + + again: switch (state->tokenkind) + { + case tk_vbarvbar: + { + next_token(state); + left = left | parse_ands(state); + goto again; + } + + case tk_vbaremark: + { + next_token(state); + left = (~left | parse_ands(state)) & M; + goto again; + } + + case tk_emarkvbar: + { + next_token(state); + left = ~(left | parse_ands(state)) & M; + goto again; + } + + default: + break; + } + + return left; +} + +// Parse ternary expressions (cond ? expr : expr) +static uint16_t parse_ternary(struct parser_state* state) +{ + uint16_t cond = parse_ors(state); + + if (state->tokenkind == tk_qmark) + { + next_token(state); + + uint16_t left = parse_ors(state); + + if (state->tokenkind != tk_colon) + { + puts("syntax error!"); + exit(1); + } + + next_token(state); + + uint16_t right = parse_ternary(state); + + return (cond & left) | (~cond & right); + } + else + { + return cond; + } +} + +// Parse the root expression +static uint16_t parse_root(struct parser_state* state) +{ + return parse_ternary(state); +} + +// Main evaluation function uint16_t evaluate(const char* text) { - enum { - tk_uninitialized, + struct parser_state state = { + .tokenkind = tk_uninitialized, + .moving = text + }; - tk_0, - tk_1, + next_token(&state); - tk_w, - tk_x, - tk_y, - tk_z, + uint16_t truthtable = parse_root(&state); - tk_oparen, - tk_cparen, - - tk_emark, - tk_emarkequals, - tk_emarkvbar, - tk_emarkampersand, - - tk_equalsequals, - - tk_vbarvbar, - tk_vbaremark, - - tk_qmark, - - tk_less_than, - tk_less_than_eq, - - tk_greater_than, - tk_greater_than_eq, - - tk_ampersandemark, - tk_ampersandampersand, - - tk_colon, - - tk_EOF, - } tokenkind = tk_uninitialized; - - const char* moving = text; - - void next_token(void) - { - while (*moving && *moving == ' ') - moving++; - - switch (*moving) - { - case 0: - tokenkind = tk_EOF; - break; - - case '0': - tokenkind = tk_0, moving++; - break; - - case '1': - tokenkind = tk_1, moving++; - break; - - case 'w': - tokenkind = tk_w, moving++; - break; - - case 'x': - tokenkind = tk_x, moving++; - break; - - case 'y': - tokenkind = tk_y, moving++; - break; - - case 'z': - tokenkind = tk_z, moving++; - break; - - case '(': - tokenkind = tk_oparen, moving++; - break; - - case ')': - tokenkind = tk_cparen, moving++; - break; - - case '?': - tokenkind = tk_qmark, moving++; - break; - - case ':': - tokenkind = tk_colon, moving++; - break; - - // either '||' or '|!': - case '|': - { - moving++; - - switch (*moving) - { - case '|': - tokenkind = tk_vbarvbar, moving++; - break; - - case '!': - tokenkind = tk_vbaremark, moving++; - break; - - default: - { - puts("syntax error"); - exit(1); - break; - } - } - - break; - } - - // either '&&' or '&!': - case '&': - { - moving++; - - switch (*moving) - { - case '&': - tokenkind = tk_ampersandampersand, moving++; - break; - - case '!': - tokenkind = tk_ampersandemark, moving++; - break; - - default: - { - puts("syntax error"); - exit(1); - break; - } - } - - break; - } - - // either '!' or '!=' or '!&' or '!|' - case '!': - { - moving++; - - switch (*moving) - { - case '=': - tokenkind = tk_emarkequals, moving++; - break; - - case '|': - tokenkind = tk_emarkvbar, moving++; - break; - - case '&': - tokenkind = tk_emarkampersand, moving++; - break; - - default: - tokenkind = tk_emark; - break; - } - - break; - } - - case '<': - { - moving++; - - switch (*moving) - { - case '=': - tokenkind = tk_less_than_eq, moving++; - break; - - default: - { - tokenkind = tk_less_than; - break; - } - } - - break; - } - - case '>': - { - moving++; - - switch (*moving) - { - case '=': - tokenkind = tk_greater_than_eq, moving++; - break; - - default: - { - tokenkind = tk_greater_than; - break; - } - } - - break; - } - - // could only be '==': - case '=': - { - moving++; - - switch (*moving) - { - case '=': - tokenkind = tk_equalsequals, moving++; - break; - - default: - { - puts("syntax error"); - exit(1); - break; - } - } - - break; - } - - default: - assert(!"TODO"); - break; - } - } - - next_token(); - - uint16_t parse_root(void) - { - uint16_t parse_ternary(void) - { - uint16_t parse_ors(void) - { - uint16_t parse_ands(void) - { - uint16_t parse_equals(void) - { - uint16_t parse_compares(void) - { - uint16_t parse_prefix(void) - { - uint16_t parse_primary(void) - { - uint16_t retval; - - switch (tokenkind) - { - case tk_0: - retval = 0, next_token(); - break; - - case tk_1: - retval = M, next_token(); - break; - - case tk_w: - retval = W, next_token(); - break; - - case tk_x: - retval = X, next_token(); - break; - - case tk_y: - retval = Y, next_token(); - break; - - case tk_z: - retval = Z, next_token(); - break; - - case tk_oparen: - { - next_token(); - - retval = parse_root(); - - if (tokenkind != tk_cparen) - { - assert(!"NOPE"); - } - - next_token(); - break; - } - - default: - assert(!"TODO"); - break; - } - - return retval; - } - - if (tokenkind == tk_emark) - { - next_token(); - - return ~parse_prefix(); - } - else - { - return parse_primary(); - } - } - - uint16_t left = parse_prefix(); - - again: switch (tokenkind) - { - case tk_less_than: - { - next_token(); - left = (~left & parse_equals()) & M; - goto again; - } - - case tk_less_than_eq: - { - next_token(); - left = (~left | parse_equals()) & M; - goto again; - } - - case tk_greater_than_eq: - { - next_token(); - left = ( left | ~parse_equals()) & M; - goto again; - } - - case tk_greater_than: - { - next_token(); - left = ( left & ~parse_equals()) & M; - goto again; - } - - default: - break; - } - - return left; - } - - uint16_t left = parse_compares(); - - again: switch (tokenkind) - { - case tk_equalsequals: - { - next_token(); - left = ~(left ^ parse_equals()) & M; - goto again; - } - - case tk_emarkequals: - { - next_token(); - left = left ^ parse_equals(); - goto again; - } - - default: - break; - } - - return left; - } - - uint16_t left = parse_equals(); - - again: switch (tokenkind) - { - case tk_ampersandampersand: - { - next_token(); - left = left & parse_equals(); - goto again; - } - - case tk_ampersandemark: - { - next_token(); - left = ~left & parse_equals(); - goto again; - } - - case tk_emarkampersand: - { - next_token(); - left = ~(left & parse_equals()); - goto again; - } - - default: - break; - } - - return left; - } - - uint16_t left = parse_ands(); - - again: switch (tokenkind) - { - case tk_vbarvbar: - { - next_token(); - left = left | parse_ands(); - goto again; - } - - case tk_vbaremark: - { - next_token(); - left = (~left | parse_ands()) & M; - goto again; - } - - case tk_emarkvbar: - { - next_token(); - left = ~(left | parse_ands()) & M; - goto again; - } - - default: - break; - } - - return left; - } - - uint16_t cond = parse_ors(); - - if (tokenkind == tk_qmark) - { - next_token(); - - uint16_t left = parse_ors(); - - if (tokenkind != tk_colon) - { - puts("syntax error!"); - exit(1); - } - - next_token(); - - uint16_t right = parse_ternary(); - - return (cond & left) | (~cond & right); - } - else - { - return cond; - } - } - - return parse_ternary(); - } - - uint16_t truthtable = parse_root(); - - if (tokenkind != tk_EOF) + if (state.tokenkind != tk_EOF) { puts("syntax error!"); exit(1); @@ -1451,7 +1495,9 @@ int main(int argc, char* const* argv) if (cost != INT_MAX) { - printf("0b%016b: [%2i]: ", i, cost), print(i, 0), puts(""); + printf("0b"); + print_binary(i) + printf(": [%2i]: ", cost), print(i, 0), puts(""); } } } @@ -1514,7 +1560,10 @@ int main(int argc, char* const* argv) { uint16_t truthtable = evaluate(command); - // printf("truthtable = 0b%016b\n", truthtable); + // Print binary representation manually instead of using %b format + // printf("truthtable = 0b"); + // print_binary(truthtable); + // printf("\n"); if (lookup[truthtable].kind == ek_unreachable) { @@ -1522,7 +1571,9 @@ int main(int argc, char* const* argv) } else { - printf("%2i: ", lookup[truthtable].cost), print(truthtable, 0), puts(""); + printf("%2i: ", lookup[truthtable].cost); + print(truthtable, 0); + puts(""); } } else @@ -1544,7 +1595,10 @@ int main(int argc, char* const* argv) uint16_t truthtable = evaluate(line); - // printf("truthtable = 0b%016b\n", truthtable); + // Print binary representation manually instead of using %b format + // printf("truthtable = 0b"); + // print_binary(truthtable); + // printf("\n"); if (lookup[truthtable].kind == ek_unreachable) { @@ -1552,8 +1606,9 @@ int main(int argc, char* const* argv) } else { - printf("%2i: ", lookup[truthtable].cost), - print(truthtable, 0), puts(""); + printf("%2i: ", lookup[truthtable].cost); + print(truthtable, 0); + puts(""); } } }