сдвиг / уменьшение конфликта в грамматике с необязательной точкой с запятой - PullRequest
2 голосов
/ 11 апреля 2020

Пример репозитория

Я хотел бы сделать что-то вроде этого:

// match used as a statement, semicolon is optional
match (1) {}

// match used as an expression, semicolon is required
1 + match (2) {};
statement
    : expression_without_block T_SEMICOLON
    | expression_with_block
;

expression
    : expression_without_block
    | expression_with_block
;

expression_without_block
    : scalar
    | expression_without_block T_PLUS expression
    | T_PLUS expression
;

expression_with_block
    : T_MATCH T_LEFT expression T_RIGHT T_CURLY_LEFT T_CURLY_RIGHT
;

Идея состоит в том, что expression_with_block не может быть используется в начале выражения, делая следующее однозначным:

match (1) {}
+2;

// Can't mean
(match (1) {} + 2);
// because of the line "expression_without_block T_PLUS expression"

Грамматика вызывает конфликты сдвиг / уменьшение, но я понятия не имею, почему. Вывод говорит следующее (но я не уверен, что с ним делать):

State 11 conflicts: 1 shift/reduce

...

State 11

    5 expression: expression_without_block .
    8 expression_without_block: expression_without_block . T_PLUS expression

    T_PLUS  shift, and go to state 14

    T_PLUS    [reduce using rule 5 (expression)]
    $default  reduce using rule 5 (expression)

Полный файл вывода можно найти здесь .

I Я также даже не уверен, что это правильный подход, потому что тогда что-то подобное не сработает:

// `match` can't be at the lhs of an expression, even in sub-expressions
func_call(match (10) {} + 20);

Есть ли способ достичь того, что я описываю здесь, в зубре? Я не эксперт по бизонам, поэтому я очень признателен за помощь. Спасибо!

1 Ответ

2 голосов
/ 11 апреля 2020

Это очень классический c вид конфликта, который случается с леворекурсивными правилами, но в качестве разрешения по умолчанию конфликта сдвига / уменьшения является сдвиг, тогда все будет хорошо.

Вот как вы должны прочитать трассировку бизонов:

T_PLUS  shift, and go to state 14              -- when next token is T_PLUS shift action is selected

T_PLUS    [reduce using rule 5 (expression)]   -- the action between [] was disabled by Bison default conflict resolution

Чтобы переопределить разрешение конфликтов Bison по умолчанию (что здесь не обязательно), мы можем использовать приоритет оператора (см. https://www.gnu.org/software/bison/manual/bison.html#Precedence -Decl ) или приоритет для неоператора (см. https://www.gnu.org/software/bison/manual/bison.html#Non -операторы )

...