Смекни!
smekni.com

Оптимальні програми обчислення виразів (стр. 6 из 6)

Ск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кується.