Я пытаюсь создать файл .y для разработки базового языка программирования, где терминальные значения просто истинны и ложны. Однако у меня возникла проблема с определением правила для оператора if. Синтаксис оператора if похож на;
a=TRUE
if TRUE: print(a)
и мой BNF похож;
statement : assignment | ifstatement | print
ifstatement : IF expression COLON statement {if ($2==true){$$ = $4;}}
где IF — токен ключевого слова if и COLON для ':'. Но когда я компилирую свои файлы, я получаю следующую ошибку:
$4 of ‘ifstatement’ has no declared type ifstatement : IF expression COLON statement {if ($2==true){$$ = $4;}}
Итак, мой вопрос: какое может быть правило, которое я должен использовать для операторов if else, отличных от {если($2==истина){$$ = $4;}}?
Проблема, на которую жалуется бизон, заключается в том, что вы присваиваете $$
, что является семантическим значением ifstatement
, но вы не сказали бизону, каков тип ifstatement
. Как и в C, если у вас есть переменная, вам нужно объявить ее тип.
Это предполагает, что вы сказали bison, что не все грамматические символы имеют один и тот же тип. Другими словами, у вас есть объявление %union
, в котором указаны имена тегов для всех типов, которые вы используете. Затем вам нужно объявить типы всех токенов и нетерминалов, которые имеют значения, используя объявления %token
и %type
.
Ваше действие if ($2==true){$$ = $4;}
требует, чтобы $$
(ifexpression
), $2
(expression
) и $4
(statement
) были объявлены типы. Если bison жалуется только на один из них, то вы знаете, как объявлять типы, потому что два других уже объявлены. В противном случае, если у вас много таких ошибок, то вам следует просмотреть файл соответствующий раздел в руководстве по зубру. Вы также можете прочитать всю главу о семантические значения.
Однако ничто из вышеперечисленного не решает реальной проблемы с этим действием, связанной с вашим подходом к интерпретации программного кода. Ожидается, что оператор if
будет оценивать свою ветвь true
только в том случае, если условие действительно истинно. Но обратите внимание, что значение $4
уже было вычислено до того, как ваше действие было выполнено, независимо от того, выполняется ли условие. Все, что делает действие, — это перенаправляет уже вычисленное значение statement
в значение ifstatement
. Также обратите внимание, что $$
ничего не присваивается, если условие равно false
. Таким образом, его значение равно значению $4
или оно не инициализировано, и в последнем случае попытка использовать его значение приведет к неопределенному поведению.
Вот почему любой нетривиальный язык не может быть оценен во время синтаксического анализа. Условные блоки могут быть оценены только после того, как условный оператор был проанализирован, поэтому их оценку необходимо отложить. И повторяющиеся блоки — например, операторы for
и while
— должны оцениваться много раз, хотя они анализируются только один раз.