diff --git a/src/compiler/build_tables/parse_table_builder.cc b/src/compiler/build_tables/parse_table_builder.cc index c705c2c1..e06f4098 100644 --- a/src/compiler/build_tables/parse_table_builder.cc +++ b/src/compiler/build_tables/parse_table_builder.cc @@ -602,9 +602,9 @@ class ParseTableBuilderImpl : public ParseTableBuilder { for (auto &preceding_symbol : preceding_symbols) { ParseState &preceding_state = parse_table.states[preceding_state_id]; if (preceding_state.nonterminal_entries.count(symbol.index)) break; - preceding_state_id = preceding_symbol.is_terminal() ? - preceding_state.terminal_entries[preceding_symbol].actions.back().state_index : - preceding_state.nonterminal_entries[preceding_symbol.index]; + preceding_state_id = preceding_symbol.is_non_terminal() ? + preceding_state.nonterminal_entries[preceding_symbol.index] : + preceding_state.terminal_entries[preceding_symbol].actions.back().state_index; } const ParseItemSet &preceding_item_set = *item_sets_by_state_id[preceding_state_id]; for (auto &preceding_entry : preceding_item_set.entries) { diff --git a/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/expected_error.txt b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/expected_error.txt new file mode 100644 index 00000000..cbb3e02c --- /dev/null +++ b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/expected_error.txt @@ -0,0 +1,14 @@ +Unresolved conflict for symbol sequence: + + _program_start '[' identifier • ']' … + +Possible interpretations: + + 1: _program_start '[' (array_repeat1 identifier) • ']' … + 2: _program_start '[' (array_type_repeat1 identifier) • ']' … + +Possible resolutions: + + 1: Specify a higher precedence in `array_repeat1` than in the other rules. + 2: Specify a higher precedence in `array_type_repeat1` than in the other rules. + 3: Add a conflict for these rules: `array` `array_type` diff --git a/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/grammar.json b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/grammar.json new file mode 100644 index 00000000..0be2008c --- /dev/null +++ b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/grammar.json @@ -0,0 +1,82 @@ +{ + "name": "conflict_in_repeat_rule_after_external_token", + + "externals": [ + {"type": "SYMBOL", "name": "_program_start"}, + ], + + "rules": { + "statement": { + "type": "CHOICE", + "members": [ + { + "type": "SEQ", + "members": [ + {"type": "SYMBOL", "name": "_program_start"}, + {"type": "SYMBOL", "name": "array"}, + {"type": "STRING", "value": ";"} + ] + }, + { + "type": "SEQ", + "members": [ + {"type": "SYMBOL", "name": "_program_start"}, + {"type": "SYMBOL", "name": "array_type"}, + {"type": "SYMBOL", "name": "identifier"}, + {"type": "STRING", "value": ";"} + ] + } + ] + }, + + "array": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + {"type": "SYMBOL", "name": "identifier"}, + {"type": "STRING", "value": "0"} + ] + } + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + + "array_type": { + "type": "SEQ", + "members": [ + { + "type": "STRING", + "value": "[" + }, + { + "type": "REPEAT", + "content": { + "type": "CHOICE", + "members": [ + {"type": "SYMBOL", "name": "identifier"}, + {"type": "STRING", "value": "void"} + ] + } + }, + { + "type": "STRING", + "value": "]" + } + ] + }, + + "identifier": {"type": "PATTERN", "value": "[a-z]+"} + } +} diff --git a/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/readme.md b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/readme.md new file mode 100644 index 00000000..32841cd0 --- /dev/null +++ b/test/fixtures/test_grammars/conflict_in_repeat_rule_after_external_token/readme.md @@ -0,0 +1 @@ +This grammar is similar to the `conflict_in_repeat_rule` grammar, except that the conflict occurs after an external token is consumed. This tests that the logic for determining the repeat rule's "parent" rule works in the presence of external tokens.