Парсер Bison не будет упреждать токен

У меня есть следующая грамматика парсера (это небольшой пример):

expr:
        ident assignop expr
        {
            $$ = new NAssignment(new NAssignmentIdentifier(*$1), $2, *$3);
        } |
        STAR expr %prec IDEREF
        {
            $$ = new NDereferenceOperator(*$2);
        } |
        STAR expr assignop expr %prec IDEREF
        {
            $$ = new NAssignment(new NAssignmentDereference(*$2), $3, *$4);
        } |
        ... ;

...

assignop:
        ASSIGN_EQUAL |
        ASSIGN_ADD |
        ASSIGN_SUBTRACT |
        ASSIGN_MULTIPLY |
        ASSIGN_DIVIDE ;

Теперь я пытаюсь разобрать любую из следующих строк:

*0x8000 = 0x7000;
*mem = 0x7000;

Однако Bison продолжает видеть «*mem» и сокращает правило «STAR expr» и не выполняет предварительный просмотр, чтобы увидеть, соответствует ли «STAR expr assignop...». Насколько я понимаю, Bison должен делать это с опережением. Мое ближайшее предположение состоит в том, что %prec отключает просмотр вперед или что-то в этом роде странное, но я не понимаю, почему это происходит (поскольку значения prec эквивалентны).

Как мне заставить его выполнять просмотр вперед в этом случае?

ИЗМЕНИТЬ:

Состояние, в которое он входит при встрече с «STAR expr», следующее:

state 45

   28 expr: STAR expr .
   29     | STAR expr . assignop expr
   35     | expr . binaryop expr

    $default  reduce using rule 28 (expr)

    assignop  go to state 81
    binaryop  go to state 79

Поэтому я не понимаю, почему он выбирает $default, когда он может выбрать assignop (обратите внимание, что порядок правил в файле parser.y не влияет на то, какой из них он выбирает в этом случае; я пытался изменить порядок assignop выше стандартного «STAR expr»).


person June Rhodes    schedule 09.04.2012    source источник


Ответы (2)


Это произойдет, если IDREF имеет более высокий приоритет, чем ASSIGN_EQUAL, ASSIGN_ADD и т. д. В частности, в этом случае с необработанным синтаксическим анализатором (до применения приоритета) у вас есть конфликты сдвига/уменьшения между правилом expr: STAR expr и различными токенами ASSIGN_XXX. Правила приоритета, которые у вас есть, разрешают все конфликты в пользу сокращения.

assignop в состоянии - это переход, а не сдвиг или сокращение, поэтому он вообще не участвует в просмотре вперед или обработке токена - gotos возникают только после того, как какой-то токен был сдвинут, а затем позже уменьшен до рассматриваемого нетерминала. .

person Chris Dodd    schedule 09.04.2012
comment
Ой! Я думал, что удалил этот вопрос, так как уже решил его. Я лучше добавлю свой ответ сейчас ... - person June Rhodes; 09.04.2012

В итоге я решил эту проблему, создав еще одно правило 'deref', например:

deref:
        STAR ident
        {
            $$ = new NDereferenceOperator(*$<ident>2);
        } |
        STAR numeric
        {
            $$ = new NDereferenceOperator(*$2);
        } |
        STAR CURVED_OPEN expr CURVED_CLOSE
        {
            $$ = new NDereferenceOperator(*$3);
        } |
        deref assignop expr
        {
            if ($1->cType == "expression-dereference") // We can't accept NAssignments as the deref in this case.
                $$ = new NAssignment(new NAssignmentDereference(((NDereferenceOperator*)$1)->expr), $2, *$3);
            else
                throw new CompilerException("Unable to apply dereferencing assignment operation to non-dereference operator based LHS.");
        } ;

замена обоих правил в 'expr' одним 'deref'.

person June Rhodes    schedule 09.04.2012