Скiльки змiнних буде у виразi ?
3
Введiть один символ для позначення змiнної номер 1
W
Введiть значення W
1.5
Введiть один символ для позначення змiнної номер 2
P
Введiть значення P
10
Введiть один символ для позначення змiнної номер 3
R
Введiть значення R
1.05
Введiть арифметичний вираз у iнфiкснiй формi
W*R^P
Вираз у iнфiкснiй формi: WRP^*
Результат 2.443342
Натиснiть довiльну клавiшу
Додаток 2.
Програмна реалізація простого компілятора виразів.
Нижче подано текст програми, написаної для компілятивної обробки [2] арифметичних виразів, записаних в інфіксній формі. Ця програма може бути використана як частина компілятора, котра відповідає за генерацію асемблерного коду для операторів присвоєння.
Особливості даної програми:
· однопрохідна генерація коду;
· відсутній лексичний сканер, тому всі ідентифікатори включаються в асемблерний код без перевірки;
· всі обчислення є цілочисловими;
· арифметичні функції не приймають параметрів, а результат повертають в регістрі AX;
· розпізнається більшість синтаксичних помилок;
· коректно розпізнаються пробіли та символи табуляції у виразі.
Текст програми:
const TAB = ^I;
CR = ^M;
Var Look: Char;
Procedure GetChar;
Begin
Read(Look);
End;
Procedure Error(s: String);
Begin
WriteLn;
WriteLn(^G, 'Помилка : ', s, '.');
End;
Procedure Abort(s: String);
Begin
Error(s);
Halt;
End;
Procedure Expected(s: String);
Begin
Abort(s + ' Очікується');
End;
Function IsAlpha(c: Char): Boolean;
Begin
IsAlpha := UpCase(c) In ['A'..'Z'];
End;
Function IsDigit(c: Char): Boolean;
Begin
IsDigit := c In ['0'..'9'];
End;
Function IsAlNum(c: Char): Boolean;
Begin
IsAlNum := IsAlpha(c) Or IsDigit(c);
End;
Function IsAdDop(c: Char): Boolean;
Begin
IsAdDop := c In ['+', '-'];
End;
Function IsWhite(c: Char): Boolean;
Begin
IsWhite := c In [' ', TAB];
End;
Procedure SkipWhite;
Begin
While IsWhite(Look) Do
GetChar;
End;
Procedure Match(x: Char);
Begin
If Look <> x Then Expected('''' + x + '''')
Else Begin
GetChar;
SkipWhite;
End;
End;
Function GetName: String;
Var Token: String;
Begin
Token := '';
If NOT IsAlpha(Look) Then Expected('Ім’я');
While IsAlNum(Look) Do Begin
Token := Token + UpCase(Look);
GetChar;
End;
GetName := Token;
SkipWhite;
End;
Function GetNum: String;
Var Value: String;
Begin
Value := '';
If NOT IsDigit(Look) Then Expected('Ціле число');
While IsDigit(Look) Do Begin
Value := Value + Look;
GetChar;
End;
GetNum := Value;
SkipWhite;
End;
Procedure Emit(s: String);
Begin
Write(TAB, s);
End;
Procedure EmitLn(s: String);
Begin
Emit(s);
WriteLn;
End;
Procedure Ident;
Var Name: String[8];
Begin
Name:= GetName;
If Look = '(' Then Begin
Match('(');
Match(')');
EmitLn('CALL ' + Name);
End
Else
EmitLn('MOV ' + Name + ',AX');
End;
Procedure Expression; Forward;
Procedure Factor;
Begin
If Look = '(' Then Begin
Match('(');
Expression;
Match(')');
End
Else If IsAlpha(Look) Then
Ident
Else
EmitLn('MOV ' + GetNum + ',AX');
End;
Procedure Multiply;
Begin
Match('*');
Factor;
EmitLn('POP DX');
EmitLn('MUL AX,DX');
End;
Procedure Divide;
Begin
Match('/');
Factor;
EmitLn('POP DX');
EmitLn('DIV DX,AX');
EmitLn('MOV DX,AX');
End;
Procedure Term;
Begin
Factor;
While Look In ['*', '/'] Do Begin
EmitLn('PUSH AX');
Case Look Of
'*': Multiply;
'/': Divide;
End;
End;
End;
Procedure Add;
Begin
Match('+');
Term;
EmitLn('POP DX');
EmitLn('ADD AX,DX');
End;
Procedure Subtract;
Begin
Match('-');
Term;
EmitLn('POP DX');
EmitLn('SUB DX,AX');
EmitLn('MOV DX,AX');
End;
Procedure Expression;
Begin
If IsAdDop(Look) Then
EmitLn('XOR AX,AX')
Else
Term;
While IsAdDop(Look) Do Begin
EmitLn('PUSH AX');
Case Look Of
'+': Add;
'-': Subtract;
End;
End;
End;
Procedure Assignment;
Var Name: String[8];
Begin
Name := GetName;
Match('=');
Expression;
EmitLn('MOV AX,' + Name);
End;
Procedure Init;
Begin
GetChar;
SkipWhite;
End;
Begin
WriteLn('Введіть оператор присвоєння');
Init;
WriteLn('Результуючий код на асемблерi');
Assignment;
If Look <> CR Then Expected('Новий рядок');
End.
Приклади роботи програми.
Приклад 1.
Введiть оператор присвоєння
a=123*(b+e)-func33()/3
Результуючий код на асемблерi
MOV 123,AX
PUSH AX
MOV B,AX
PUSH AX
MOV E,AX
POP DX
ADD AX,DX
POP DX
MUL AX,DX
PUSH AX
CALL FUNC33
PUSH AX
MOV 3,AX
POP DX
DIV DX,AX
MOV DX,AX
POP DX
SUB DX,AX
MOV DX,AX
MOV AX,A
Приклад 2.
Введiть оператор присвоєння
Variable=Val1*Val2+Stat() - 11 / epsilon
Результуючий код на асемблерi
MOV VAL1,AX
PUSH AX
MOV VAL2,AX
POP DX
MUL AX,DX
PUSH AX
CALL STAT
POP DX
ADD AX,DX
PUSH AX
MOV 11,AX
PUSH AX
MOV EPSILON,AX
POP DX
DIV DX,AX
MOV DX,AX
POP DX
SUB DX,AX
MOV DX,AX
MOV AX,VARIABLE
Приклад 3.
Введiть оператор присвоєння
RESULT=(MAX-MIN)*(-3/LENGTH)
Результуючий код на асемблерi
MOV MAX,AX
PUSH AX
MOV MIN,AX
POP DX
SUB DX,AX
MOV DX,AX
PUSH AX
XOR AX,AX
PUSH AX
MOV 3,AX
PUSH AX
MOV LENGTH,AX
POP DX
DIV DX,AX
MOV DX,AX
POP DX
SUB DX,AX
MOV DX,AX
POP DX
MUL AX,DX
MOV AX,RESULT
Приклад 4.
Введiть оператор присвоєння
OUT=IN+10*(value()
Результуючий код на асемблерi
MOV IN,AX
PUSH AX
MOV 10,AX
PUSH AX
CALL VALUE
Помилка: ')' Очiкується.
Приклад 5.
Введiть оператор присвоєння
Size=Long*Wide+X-
Результуючий код на асемблерi
MOV LONG,AX
PUSH AX
MOV WIDE,AX
POP DX
MUL AX,DX
PUSH AX
MOV X,AX
POP DX
ADD AX,DX
PUSH AX
Помилка: Цiле число Очiкується.