2014-12-06 6 views
0
iteration_stmt : WHILE    {$$ = LabelSeed; LabelSeed++; 
            fprintf(fp, "While%i:\n", $$); 
            } 
       '(' expression ')' {fprintf(fp, "cmp %s, 1\n", regToString($<n>3)); 
            fprintf(fp, "jne EndWhile%i\n", $$); 
            NextReg--; 
            } 
       statement   {fprintf(fp, "jmp While%i\n", $$); 
            fprintf(fp, "EndWhile%i:\n", $$); 
            } 
       ; 

Я пытаюсь использовать iteration_stmt «s семантического значения для отслеживания значения LabelSeed, однако это значение не останется таким же путем отказа другие 2 действия. Например, в одном случае, мой вывод:Yacc/Bison семантического значения изменяется в середине пути через правило

While0: 
... 
jne EndWhile1 
... 
jmp While0 
EndWhile0: 

в другой его:

While2: 
... 
jne EndWhile2 
... 
jmp While0 
EndWhile0: 

Целое должно оставаться постоянным. Я не могу придумать какую-либо причину, по которой семантическое значение изменится. Может кто-то указать мне верное направление?

ответ

0

Смысловое значение iteration_stmt не будет установлен, пока правило всего не снижаются, и в этот момент $$ может быть использована для обозначения к нему в коде действия. Ваше использование $$ в сегментах кода действия фактически относится к неявным частично завершенным частям правила; только в действии для окончания заявление не-терминал будет $$ ссылаться на iteration_stmt.

Это потому, что внутри yacc/bison реализует rules with mid-rule actions как каскад правил правильной формы, с действиями только в конце.

Итак, попробуйте следующее:

iteration_stmt : WHILE    {$$ = LabelSeed; LabelSeed++; 
            fprintf(fp, "While%i:\n", $$); 
            } 
       '(' expression ')' {fprintf(fp, "cmp %s, 1\n", regToString($<n>3)); 
            fprintf(fp, "jne EndWhile%i\n", $1); 
            NextReg--; 
            } 
       statement   {fprintf(fp, "jmp While%i\n", $1); 
            fprintf(fp, "EndWhile%i:\n", $1); 
            } 
       ; 

Если первый $$ загружает семантическое значение WHILE токен, который другие действия могут ссылаться.

+1

Спасибо! Это зафиксировало еще одну небольшую ошибку в моей программе, так как я испортил стек значений. Просто чтобы сообщить другим, что я сделал, это создать подправило, которое выполнило первое действие, и использовало это правило для хранения LabelSeed. В основном то же, что и ваша идея, кроме того, что мне не нужно устанавливать значение в lex. 'whilesubroutine: WHILE {$$ = LabelSeed ++; fprintf (fp, "While% i: \ n", $$); }; ' – user3289912

+0

Нарушение правила с действиями среднего действия в каскад простых правил с конечными действиями не является полной эквивалентностью. Согласно [Levine et al] (http://www.amazon.com/Lex-Yacc-John-R-Levine/dp/B00007FYCY/) есть некоторые неясные случаи, когда грамматика становится двусмысленной. – arayq2

+0

Для терминалов значение, установленное в Lex, становится семантическим значением из-за правила по умолчанию {$$ = $ 1; } – arayq2

Смежные вопросы