Итак, я нахожусь в процессе создания компилятора для C, и в настоящее время я создаю таблицы литералов, переменных и функций.
И это правило дает мне конфликт уменьшения/уменьшения:
lval: ID { check_var(); }
| ID { check_var(); } LBRACK NUM RBRACK
| ID { check_var(); } LBRACK ID { check_var(); } RBRACK;
Ошибка следующая:
parser.y: warning: 1 reduce/reduce conflict [-Wconflicts-rr]
parser.y:104.6-21: warning: rule useless in parser due to conflicts [-Wother]
| ID { check_var(); } LBRACK ID { check_var(); } RBRACK;
^^^^^^^^^^^^^^^^
У меня есть правила приоритета, чтобы избежать ошибок в токенах, но теперь он указывает на не токен, поэтому не знаю, что мне делать?
Если это случайно поможет, вот мои правила приоритета:
%token INPUT OUTPUT WRITE
%token RETURN VOID IF ELSE WHILE ASSIGN SEMI COMMA
%token LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK
%token NUM ID STRING INT
%left EQ NEQ GE LE GT LT
%left PLUS MINUS
%left TIMES OVER





Bison не проверяет, идентичны ли два пользовательских блока кода в вашем синтаксисе. Таким образом, он рассматривает вашу грамматику как:
lval: ID action_1
| ID action_2 LBRACK NUM RBRACK
| ID action_3 LBRACK ID action_4 RBRACK
;
А Bison (по умолчанию) действует как LALR(1) парсер, то есть он просматривает только один токен перед принятием решения. Поэтому, когда он видит, что вершина стека является токеном ID, а упреждающий токен — токеном LBRACK, он не может решить, следует ли ему выполнять action_2 или action_3, не понимая, что на самом деле это не имеет значения.
Решите эту проблему, используя подправило, чтобы объединить общую вещь, которая должна происходить, когда за ID следует LBRACK (а также в других ситуациях):
id_with_check: ID { check_var(); } ;
lval: id_with_check
| id_with_check LBRACK NUM RBRACK
| id_with_check LBRACK id_with_check RBRACK
;
Это было удивительно точно и быстро. Я действительно остался без вопросов. Спасибо, ашеплер! 10/10
Можете ли вы превратить
ID { check_var(); }в свой собственный символ? Тогда у вас естьlval: checked_id | checked_id LBRACK NUM RBRACK | checked_id LBRACK checked_id RBRACK;