Установка уровней приоритета в грамматике BNFC
Фон:
Я беру урок по семантике программного обеспечения, и мы должны создать небольшой компилятор и среду исполнения для игрушечного языка под названием while. Нам дали скелет кода для Java, но нам разрешено использовать любой язык, который мы хотим. Я увидел в этом возможность отрепетировать грамматику и подумал, что было бы неплохо вместо этого сделать лабораторию на C++.
Теперь у меня возникли проблемы с настройкой правил приоритета для моих утверждений. Вот мой файл грамматики BNFC прямо сейчас:
SSkip. Stmt ::= "skip";
SAss. Stmt ::= VarName ":=" AExp;
SIf. Stmt1 ::= "if" BExp "then" Stmt "else" Stmt;
SWhile. Stmt1 ::= "while" BExp "do" Stmt;
SComp. Stmt ::= Stmt ";" Stmt;
coercions Stmt 1;
token VarName (letter (letter | digit) *);
EAdd. AExp ::= AExp "+" AExp1;
ESub. AExp ::= AExp "-" AExp1;
EMul. AExp1 ::= AExp1 "*" AExp2;
EDiv. AExp1 ::= AExp1 "/" AExp2;
EInt. AExp2 ::= Integer;
EVar. AExp2 ::= VarName;
coercions AExp 2;
BTrue. BExp1 ::= "true";
BFalse. BExp1 ::= "false";
BNeg. BExp ::= "not" BExp;
BConj. BExp ::= BExp "and" BExp;
BLeq. BExp ::= AExp "<=" AExp;
coercions BExp 1;
Что я хочу, так это ввод
while true do skip; x:=y
быть разобран в соответствии с моим составным правилом в нечто вроде
(SComp [SWhile [BTrue] [SSkip]] [(SAss "x" [EVar "y"])])
То есть я хочу, чтобы назначение не было частью тела цикла. Тем не менее, я получаю
(SWhile [BTrue] [(SComp SSkip (SAss "x" [(EVar "y")]))])
Как вы можете видеть, тело цикла while состоит из составного оператора, чего я не хотел. Как мне установить правила приоритета для достижения этого эффекта?
2 ответа
Оказывается, я неправильно понял свое назначение. Правила приоритетов, которые я описал, представлены в моей учебной книге, но так как моя основная задача - совместимость с синтаксическим анализатором, который нам дал учитель, я попробовал его в приведенном выше коде, и он также анализирует назначение в теле.,
Программа, которую я хотел написать, должна была "просто" быть:
(while true do skip) ; x := y
Но, по крайней мере, это совместимо!
Я думаю, что проблема в том, что Scomp - это тип Stmt, который не может лексически отличить его от простого Stmt.
Если правило было
Scomp. Stmt ::= "{" Stmt ";" Stmt "}";
Не было бы никакой двусмысленности. Есть причина, по которой составные операторы на любом известном вам языке имеют маркеры начала и конца; это оно.