diff options
author | Matthew Sotoudeh <matthew@masot.net> | 2024-03-11 16:33:24 -0700 |
---|---|---|
committer | Matthew Sotoudeh <matthew@masot.net> | 2024-03-11 16:33:24 -0700 |
commit | a9292a98cc6c65e2a4ad6da20937ef7568a4143d (patch) | |
tree | f921866c475208359285ff3f606c0fafa1812a32 /grammars/c/disambiguate.c | |
parent | 35fa21e59ad44de3ac5d075a3c1ae60d462a1a13 (diff) |
earlpy
Diffstat (limited to 'grammars/c/disambiguate.c')
-rw-r--r-- | grammars/c/disambiguate.c | 84 |
1 files changed, 46 insertions, 38 deletions
diff --git a/grammars/c/disambiguate.c b/grammars/c/disambiguate.c index 403d65f..b6a99e8 100644 --- a/grammars/c/disambiguate.c +++ b/grammars/c/disambiguate.c @@ -1,47 +1,41 @@ -struct token *TYPE_NAMES[1024]; -size_t N_TYPE_NAMES; - -void alert_parse(struct state *state) { - if (PRODUCTION_ID_TO_SYMBOL[state->production_id] == SYMBOL_TYPEDEF) { - for (struct token *t = find_token(state, 2); t->symbol != DONE_SYMBOL; t++) { - if (t->symbol == SYMBOL_IDENT) { - TYPE_NAMES[N_TYPE_NAMES++] = t; - break; - } - } - } -} - -int is_typename(struct token *token) { - if (!strcmp("int", token->string)) return 1; - for (size_t i = 0; i < N_TYPE_NAMES; i++) - if (!strcmp(TYPE_NAMES[i]->string, token->string)) - return 1; - return 0; -} +void alert_parse(struct state *state) { } int disambiguator(struct state *old, struct state *new) { - // printf("Old tree:\n"); - // print_parse_tree(old, 4); - // printf("New tree:\n"); - // print_parse_tree(new, 4); + // fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + // print_parse_tree(old, 0, stderr); + // print_parse_tree(new, 0, stderr); + // fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); - if (old->production_id == PRODUCTION_DECL_STMT) - if (!is_typename(find_token(old->reasons[0], 0))) - return 1; - if (new->production_id == PRODUCTION_DECL_STMT) - if (!is_typename(find_token(new->reasons[0], 0))) - return 0; + if (old->n_poisoned < new->n_poisoned) return 0; + if (new->n_poisoned < old->n_poisoned) return 1; // 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; + 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_SYMBOL[prod] == START_SYMBOL + && PRODUCTION_ID_TO_PRODUCTION[prod][1] != DONE_SYMBOL) { + struct token *old_tok = find_token(old, 1), + *new_tok = find_token(new, 1); + if (old_tok < new_tok) return 0; + else if (old_tok > new_tok) return 1; + } + + if (PRODUCTION_ID_TO_PRODUCTION[prod][0] == SYMBOL_ERROR && PRODUCTION_ID_TO_PRODUCTION[prod][1] != DONE_SYMBOL) { + struct token *old_tok = find_token(old, 1), + *new_tok = find_token(new, 1); + if (old_tok < new_tok) return 0; + else if (old_tok > new_tok) return 1; + } else if (PRODUCTION_ID_TO_PRODUCTION[prod][1] == SYMBOL_ERROR) { + struct token *old_tok = find_token(old, 1), + *new_tok = find_token(new, 1); + if (old_tok < new_tok) return 1; + else if (old_tok > new_tok) return 0; + } else 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); @@ -49,7 +43,7 @@ int disambiguator(struct state *old, struct state *new) { const char *precedence[] = {".", "->", "*", "/", "%", "+", "-", "<<", ">>", "<", "<=", ">", ">=", "==", "!=", "&", "|", "&&", "||", "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", - "^=", "|=", ",", 0}; + "^=", "|=", ",", ":", 0}; if (strcmp(old_s, new_s)) { for (const char **p = precedence; *p; p++) { if (!strcmp(old_s, *p)) { @@ -58,16 +52,30 @@ int disambiguator(struct state *old, struct state *new) { return 0; } } - // BAD! - return 2; + fprintf(stderr, "ERROR: didn't find operator '%s'\n", old_s); + exit(1); } else { - // Associate RIGHT if (old_tok < new_tok) return 1; else if (old_tok > new_tok) return 0; } } } + // Generally speaking, we want left associativity to avoid long chains of + // completions. + struct token *old_tok = find_token(old, 1), + *new_tok = find_token(new, 1); + if (old_tok < new_tok) return 1; + else if (old_tok > new_tok) return 0; + fprintf(stderr, "TOTALLY UNKNOWN!\n"); + fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~\n"); + pprint_state(old); + // print_parse_tree(old, 0, stderr); + fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~\n"); + pprint_state(new); + // print_parse_tree(new, 0, stderr); + fprintf(stderr, "~~~~~~~~~~~~~~~~~~~~~\n"); + exit(1); return 2; } |