Вопрос по – Использование приоритета в бизоне для унарного минуса не решает конфликт сдвиг / уменьшение

2

Я разрабатываю очень простую грамматику, в которой я использую унарный минус-операнд. Однако я получаю сдвиг / уменьшение конфликта. В руководстве по Bison, и везде, где я смотрю, говорится, что я должен определить новый токен и дать ему более высокий приоритет, чем двоичный операнд минус, а затем использовать & quot;% prec TOKEN & quot; в правиле.

Я сделал это, но я все еще получаю предупреждение. Зачем?

Я использую бизона (GNU Bison) 2.4.1. Грамматика показана ниже:

%{
#include <string>
extern "C" int yylex(void);
%}

%union {
    std::string token;
}

%token <token> T_IDENTIFIER T_NUMBER
%token T_EQUAL T_LPAREN T_RPAREN

%right T_EQUAL
%left T_PLUS T_MINUS
%left T_MUL T_DIV
%left UNARY

%start program

%%

program : statements expr
;

statements : '\n'
           | statements line
;

line : assignment
     | expr
;

assignment : T_IDENTIFIER T_EQUAL expr
;

expr : T_NUMBER
     | T_IDENTIFIER
     | expr T_PLUS expr
     | expr T_MINUS expr
     | expr T_MUL expr
     | expr T_DIV expr
     | T_MINUS expr   %prec UNARY
     | T_LPAREN expr T_RPAREN
;

Ваш Ответ

2   ответа
3

ения исходит из правила:

statements : '\n'
           | statements line
;

Правило не то, что вы думаете. Например, вы можете написать:

a + b c + d

Я думаю, что это не должно быть действительным вкладом.

Но и правило программы не очень вменяемое:

program : statements expr
;

Правила должны быть примерно такими:

program: lines;

lines: line | lines line;

line: statement "\n" | "\n";

statement: assignment | expr;
7

%prec не делает столько, сколько вы можете надеяться здесь. Это говорит Bison, что в ситуации, когда у вас есть- a * b Вы хотите разобрать это как(- a) * b вместо- (a * b), Другими словами, здесь он предпочтетUNARY правитьT_MUL править. В любом случае вы можете быть уверены, чтоUNARY Правило будет применено в конце концов, и это только вопрос порядка, в котором входные данные сводятся к унарному аргументу.

В вашей грамматике все очень по-другому. Любая последовательностьline нетерминалы составятsequenceи нечего сказать, чтоline нетерминал должен заканчиваться на конце строки. На самом деле любое выражение может бытьline, Итак, вот в основном два способа разбораa - b: либо в виде одной строки с двоичным минусом, либо в виде двух & # x201C; линий & # x201D; вторая, начинающаяся с унарного минуса. Нет ничего, чтобы решить, какое из этих правил будет применяться, поэтому приоритет, основанный на правилах, здесь пока не работает.

Ваше решение исправляет расщепление линии, требуя каждыйline фактически заканчиваться или сопровождаться символом конца строки.

Если вы действительно хотите поведение, которое ваша грамматика показывает в отношении окончаний строк, вам понадобятся два отдельных нетерминала для выражений, которые могут и не могут начинаться сT_MINUS, Вы должны распространить это вверх по дереву: первоеline может начинаться с одинарного минуса, но последующие не должны. В скобках, начиная с минуса, все будет в порядке снова.

Error: User Rate Limit ExceededshouldError: User Rate Limit Exceeded gablin

Похожие вопросы