Лекции по построению компилятора на Pascal

       

ГРАММАТИКА


Некоторое время назад мы реализовали синтаксические уравнения БНФ для арифметических выражений фактически даже не записав их все в одном месте. Пришло время сделать это. Вот они:

<expression> ::= <unary op> <term> [<addop> <term>]*

     <term>       ::= <factor> [<mulop> factor]*

     <factor>     ::= <integer> | <variable> | ( <expression> )

(Запомните, преимущества этой грамматики в том, что она осуществляет такую иерархию приоритетов операторов, которую мы обычно ожидаем для алгебры.)

На самом деле, пока мы говорим об этом, я хотел бы прямо сейчас немного исправить эту грамматику. Способ, которым мы обрабатываем унарный минус, немного неудобный. Я нашел, что лучше записать грамматику таким образом:

     <expression>    ::= <term> [<addop> <term>]*

     <term>          ::= <signed factor> [<mulop> factor]*

     <signed factor> ::= [<addop>] <factor>

     <factor>        ::= <integer> | <variable> | (<expression>)

Это возлагает обработку унарного минуса на Factor, которому он в действительности и принадлежит.

Это не означает, что вы должны возвратиться назад и переписать программы, которые вы уже написали, хотя вы свободны сделать так, если хотите. Но с этого момента я буду использовать новый синтаксис.

Теперь, возможно, для вас не будет ударом узнать, что мы можем определить аналогичную грамматику для булевой алгебры. Типичный набор правил такой:

     <b-expression>::= <b-term> [<orop> <b-term>]*

     <b-term>      ::= <not-factor> [AND <not-factor>]*


     <not-factor>  ::= [NOT] <b-factor>

     <b-factor>    ::= <b-literal> | <b-variable> | (<b-expression>)

Заметьте, что в этой грамматике оператор AND аналогичен "*", а OR (и исключающее OR) - "+". Оператор NOT аналогичен унарному минусу. Эта иерархия не является абсолютным стандартом... некоторые языки, особенно Ada, обрабатывают все логические операторы как имеющие одинаковый уровень приоритета... но это кажется естественным.

Обратите также внимание на небольшое различие способов, которыми обрабатываются NOT и унарный минус. В алгебре унарный минус считается идущим со всем термом и поэтому никогда не появляется более одного раза в данном терме. Поэтому выражение вида:

     a * -b



или еще хуже:

     a - -b

не разрешены. В булевой алгебре наоборот, выражение

     a AND NOT b

имеет точный смысл и показанный синтаксис учитывает это.


Содержание раздела