Установка уровней приоритета в грамматике 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 "}";

Не было бы никакой двусмысленности. Есть причина, по которой составные операторы на любом известном вам языке имеют маркеры начала и конца; это оно.

Другие вопросы по тегам