Компилятор для арифметических выражений

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
doors33
Сообщения: 2
Зарегистрирован: 28 июн 2013, 22:35

28 июн 2013, 22:42

Помогите доработать программу. Вот рабочая:

Программа microPascal.pas иллюстрирует организацию компилятора для грамматического разбора и генерации кода для языка арифметических выражений. В файле microPascal.exe компилятор представлен в готовом виде (Delphi).
Грамматика
F -> I | ( E ) Фактор
T -> F { * F } Терм
E -> T { + T } Выражение
P -> E = Программа
I -> L { L | D } Идентификатор
L - прописная или строчная буква лат. алфавита.
D - десятичная цифра.
Идентификаторы различаются по первым восьми литерам. Распознавание идентификаторов выполняется средствами лексического анализатора.

Грамматический разбор

Грамматический разбор выполняется по методу рекурсивного спуска. В результате строится семантическое дерево арифметического выражения.
Генерация кода

Код строится по семантическому дереву.

Код: Выделить всё

program microPascal; 
 uses SysUtils; 

 const m = 100; 

 var 
 fin,fout: TextFile; 

 h: array[1..m] of record Info: string[8]; LLink,RLink: Integer end; 
 Avail: Integer; 
 Lex: string[8]; 
 cLex: Integer; 
 pt: Integer; 
 ch: Char; 

 procedure Error(errCode: Integer); 
 begin 
 WriteLn(fout); 
 Write(fout,'ERROR: '); 
 case errCode of 
 1: WriteLn(fout,'End of input before logical end of program.'); 
 2: WriteLn(fout,'Unknown symbol.'); 
 3: WriteLn(fout,'Must be "id" or "(".'); 
 4: WriteLn(fout,'Must be ")".'); 
 5: WriteLn(fout,'Must be "=".'); 
 end; // case 
 CloseFile(fin); 
 CloseFile(fout); 
 Halt; 
 end; // Error 

 procedure getCh; 
 begin 
 if Eof(fin) then Error(1); 
 Read(fin,ch); 
 Write(fout,ch); 
 end; // getCh 

 procedure getLex; 
 var z: Integer; 
 begin 

 while ch = ' ' do getCh; 

 Lex:=ch; 
 case ch of 
 'a'..'z','A'..'Z': cLex:=1; 
 '+': cLex:=3; 
 '*': cLex:=4; 
 '(': cLex:=5; 
 ')': cLex:=6; 
 '=': cLex:=7; 
 else Error(2); 
 end; // case 

 getCh; 
 if cLex in [3..7] then Exit; 

 z:=1; 
 while ch in ['a'..'z','A'..'Z','0'..'9'] do 
 begin 
 if z < 8 then Lex := Lex + ch; 
 Inc(z); 
 getCh; 
 end; 

 end; // getLex 

 procedure E(var pt: Integer); forward; 

 procedure F(var pt: Integer); 
 var q: Integer; 
 begin 
 case cLex of 
 1: begin 
 q:=Avail; Avail:=h[q].RLink; 
 h[q].Info:=Lex; 
 h[q].LLink:=0; 
 getLex; 
 pt:=q; 
 end; 
 5: begin 
 getLex; 
 E(pt); 
 if cLex = 6 then 
 getLex 
 else 
 Error(4); 
 end; 
 else 
 Error(3); 
 end; // case 
 end; // F 

 procedure T(var pt: Integer); 
 var q: Integer; 
 begin 
 F(pt); 
 while cLex = 4 do 
 begin 
 q:=Avail; Avail:=h[q].RLink; 
 h[q].Info:=Lex; 
 h[q].LLink:=pt; 
 getLex; 
 F(h[q].RLink); 
 pt:=q; 
 end; 
 end; // T 

 procedure E(var pt: Integer); 
 var q: Integer; 
 begin 
 T(pt); 
 while cLex = 3 do 
 begin 
 q:=Avail; Avail:=h[q].RLink; 
 h[q].Info:=Lex; 
 h[q].LLink:=pt; 
 getLex; 
 T(h[q].RLink); 
 pt:=q; 
 end; 
 end; // E 

 procedure Prgm(var pt: Integer); 
 begin 
 E(pt); 
 if cLex = 7 then 
 begin 
 WriteLn(fout); 
 WriteLn(fout,'Success compilation.') 
 end 
 else 
 Error(5); 
 end; // Prgm 

 procedure printTree(pt: Integer); 
 begin 
 if h[pt].LLink = 0 then 
 WriteLn(fout,pt:3,h[pt].Info:9) 
 else 
 begin 
 WriteLn(fout,pt:3,h[pt].Info:9,h[pt].LLink:4,h[pt].RLink:4); 
 printTree(h[pt].LLink); 
 printTree(h[pt].RLink); 
 end; 
 end; // printTree 

 procedure genCode(pt,lev: Integer); 
 var mCode: string[3]; 
 begin 
 if h[pt].LLink = 0 then 
 begin 
 WriteLn(fout,' LDA ',h[pt].Info); 
 Exit; 
 end; 
 if h[pt].Info = '+' then mCode:='ADD' else mCode:='MUL'; 
 genCode(h[pt].LLink,lev+1); 
 WriteLn(fout,' STA @',lev); 
 genCode(h[pt].RLink,lev+1); 
 WriteLn(fout,' ',mCode,' @',lev); 
 end; // genCode 

 begin 
 AssignFile(fout,'output.txt'); Rewrite(fout); 
 AssignFile(fin,'input.txt'); Reset(fin); 

 for pt:=1 to m-1 do h[pt].RLink:=pt+1; 
 h[m].RLink:=0; 
 Avail:=1; 
 getCh; 
 { 
 repeat 
 getLex; 
 WriteLn(fout,cLex, ' |', Lex, '|'); 
 until cLex = 7; 
 } 
 getLex; 
 Prgm(pt); 
 WriteLn(fout); 
 WriteLn(fout,'Semantic tree:'); 
 WriteLn(fout,'pt = ',pt); 
 printTree(pt); 

 WriteLn(fout); 
 WriteLn(fout,'Program:'); 
 genCode(pt,1); 

 CloseFile(fin); 
 CloseFile(fout); 
 end.
input.txt
c1 * (data + X) =

output.txt
c1 * (data + X) =
Success compilation.

Semantic tree:
pt = 2
2 * 1 4
1 c1
4 + 3 5
3 data
5 X

Program:
LDA c1
STA @1
LDA data
STA @2
LDA X
ADD @2
MUL @1
Хыиуду
Сообщения: 2388
Зарегистрирован: 06 мар 2005, 21:03
Откуда: Москва
Контактная информация:

02 июл 2013, 11:25

В чем вопрос-то?
Искусство программирования - заставить компьютер делать все то, что вам делать лень.
Для "спасибо" есть кнопка "Спасибо" в виде звездочки внизу под ником автора поста.
doors33
Сообщения: 2
Зарегистрирован: 28 июн 2013, 22:35

02 июл 2013, 16:03

Я когда создавал тему, появилось сообщение, что я ее дублирую. Поискал эту тему, не нашел, поэтому и недооформил.

А вопрс вот:

Надо расширить функционал компилятора добавив:

1. Возможность использовать целые числа
b*(a+1) - (без знака)

2. Включить понятие "оператор присвоения"

A -> I = E ;

3. Заменить понятие "программа" на:

P -> { A } #

Короче говоря в результате должно быть:

в файле input.txt записываем

a = 4; b = ( a + 1 ) * 3; #

после компиляции, а потом запуска microPascal.exe, в файле output.txt должны увидеть:

a = 4; b = ( a + 1 ) * 3; #
Success compilation.

Semantic tree:

(тут должно построиться семантическое дерево)

Program:
LDA #1
STA a
LDA a
ADD #1
MUL #3
STA b
HLT


Но это уже не актуално, потому как зачет поставили )
P.S. Кстати так ни у кого не получилось, чтобы в "Program" компилировалось как надо.
Ответить