diff options
Diffstat (limited to 'grammars/c/disambiguate.c')
-rw-r--r-- | grammars/c/disambiguate.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/grammars/c/disambiguate.c b/grammars/c/disambiguate.c new file mode 100644 index 0000000..9a8bf08 --- /dev/null +++ b/grammars/c/disambiguate.c @@ -0,0 +1,49 @@ +int disambiguator(struct state *old, struct state *new) { + // printf("Old tree: "); + // print_parse_tree2(old); + // printf("New tree: "); + // print_parse_tree2(new); + + if (old->start_idx != new->start_idx) { + // printf("\t\tIGNORING "); print_parse_tree2(old); + // printf("\t\tVS: "); print_parse_tree2(new); + return 2; + } + + // Prefer the earlier parsings in the grammar when two entirely different + // productions are taken. + if (old->production_id != new->production_id) + return old->production_id < new->production_id + ? 0 : 1; + + // If they're the same production ... + prod_id_t prod = old->production_id; + if (PRODUCTION_ID_TO_SYMBOL[prod] == SYMBOL_EXPR) { + if (PRODUCTION_ID_TO_PRODUCTION[prod][1] == SYMBOL_OP) { + struct token *old_tok = find_token(old, 1), + *new_tok = find_token(new, 1); + char *old_s = old_tok->string, *new_s = new_tok->string; + const char *precedence[] = {".", "->", "*", "/", "%", "+", "-", + "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "|", "&&", + "||", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", + "^=", "|=", ",", 0}; + if (strcmp(old_s, new_s)) { + for (const char **p = precedence; *p; p++) { + if (!strcmp(old_s, *p)) { + return 1; + } else if (!strcmp(new_s, *p)) { + return 0; + } + } + // BAD! + return 2; + } else { + // Associate RIGHT + if (old_tok < new_tok) return 1; + else if (old_tok > new_tok) return 0; + } + } + } + printf("TOTALLY UNKNOWN!\n"); + return 2; +} |