Reklama

Общая форма выражения

В реальном мире выражение может состоять из одного или более термов, разделенных «addops» (‘+’ или ‘-’). В БНФ это может быть записано как: <expression> ::= <term> [<addop> <term>]*
Мы можем применить это определение выражения, добавив простой цикл к процедуре Expression:
Parse and Translate an Expression
procedure Expression;
begin
Term;
while Look in ['+', '-'] do begin
EmitLn(‘MOVE D0,D1′);
case Look of
‘+’: Add;
‘-’: Subtract;
else Expected(‘Addop’);
end;
end;
end;
мы знали, что нужно сначала умножить, а затем сложить. (Видите, зачем нам нужен стек? ).
В ранние дни технологии компиляторов, люди использовали различные довольно сложные методы для того чтобы правила приоритета операторов соблюдались. Но, оказывается, все же, что ни один из них нам не нужен… эти правила могут быть очень хорошо применены в нашей технике нисходящего синтаксического анализа. До сих пор единственной формой, которую мы применяли для терма была форма одиночной десятичной цифры. В более общей форме мы можем определить терм как произведение показателей (product of factors), то есть
<term> ::= <factor> [ <mulop> <factor ]*
Что такое показатель? На данный момент это тоже, чем был раннее терм – одиночной цифрой.
Обратите внимание: терм имеет ту же форму, что и выражение. Фактически, мы можем добавить это в наш компилятор осторожно скопировав и переименовав. Но во избежание неразберихи ниже приведен полный листинг всех подпрограмм анализатора. (Заметьте способ, которым мы изменяем порядок операндов в Divide.)
Parse and Translate a Math Factor
procedure Factor;
begin
EmitLn(‘MOVE #’ + GetNum + ‘,D0′)
end;
Recognize and Translate a Multiply
procedure Multiply;
begin
Match(‘*’);
Factor;
EmitLn(‘MULS (SP)+,D0′);
end;
Recognize and Translate a Divide
procedure Divide;
begin
Match(‘/’);
Factor;
EmitLn(‘MOVE (SP)+,D1′);
EmitLn(‘DIVS D1,D0′);
end;
Parse and Translate a Math Term
procedure Term;
begin
Factor;
while Look in ['*', '/'] do begin
EmitLn(‘MOVE D0,-(SP)’);
case Look of
‘*’: Multiply;
‘/’: Divide;
else Expected(‘Mulop’);
end;
end;
end;
Recognize and Translate an Add

Parse and Translate a Math Factor
procedure Expression; Forward;
procedure Factor;
begin
if Look = ‘(‘ then begin
Match(‘(‘);
Expression;
Match(‘)’);
end
else
EmitLn(‘MOVE #’ + GetNum + ‘,D0′);
end;
Заметьте снова, как легко мы можем дополнять синтаксический анализатор, и как хорошо код Паскаля соответствует синтаксису БНФ.
Как обычно, откомпилируйте новую версию и убедитесь, что анализатор корректно распознает допустимые предложения и отмечает недопустимые сообщениями об ошибках.

Reklama