编译原理求教(200分)

  • 主题发起人 jackyrong
  • 开始时间
J

jackyrong

Unregistered / Unconfirmed
GUEST, unregistred user!
最近,我们老师要求我们搞个在WINDOWS下的编译器(用什么语言
都可以),要求如下:
输入一个算术表达式,输出为表达式的值,而且重要的是输入
产生这个表达式的中间代码。
要求有一定的查错能力并能给出提示。例子如下:
中间代码是三地址的汇编码,形式为
op a,b,c
OP为操作码,A,B是进行指定的操作的操作数,C是存放操作结果的
单元。操作数可以是变量名或直接量,对于某些OP,A,B,C三个
中可以少用或不用。比如输入1+2*3+4
输出的中间代码为
:= 1 t0
:= 2 t1
:= 3 t2
* t1 t2 t1
+ t0 t1 t0
:= 4 t1
+ t0 t1 t0
每个临时变量保存当前式子的表达式的计算结果,有时要同时用
几个临时变量,这里T0保存加法的左操作数,直到算出运算结果。
附注:题目输入的可以为
a=3
b=1
c=2
d=a+b*c=5
就是说也应该能够分析赋值了的变量。
我们老师说这道题目有奥林匹克计算机比赛题目的难度,说一般的
学生起码要1个月才能搞好。而且我发觉,班上有个专门搞
APPLICATION开发的(他不搞数据库的),很快就搞出初步的DEMO
版,而我和其他学习数据库开发的,对这些编译原理却一愁莫展,
那么想问下各位大侠,到底学编译原理有无用呀?哪位大侠可以
解决上面的问题呀?大家不妨提出解决上面题目的方案拉,互相
学习下咯。

 
找来的,代码如下,但对与A=3,B=3,C=A+B的情况还不能
很好处理,但可以计数了,但看不懂程序,不知道各位大侠能否
给这个程序关键部分加点注释和完善它呢?
unit zmain;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ExtCtrls;
const
MaxStack=1000;
EpsReal=1e-5;
type
TOperator=(opAdd,opSub,opMul,opDiv,opLBracket,opRBracket);
//定义操作运
算符,oplbracker括号
TTokenType=(ttOperator,ttVariable,ttError);
TToken=record
kind: TTokenType;
case integer of
1:(areg:integer;value:Extended;);
2:(aop:TOperator);
end;
TMainForm = class(TForm)
Panel1: TPanel;
Splitter1: TSplitter;
Panel2: TPanel;
fromMemo: TMemo;
Splitter2: TSplitter;
toMemo: TMemo;
Button1: TButton;
Button2: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Panel1Click(Sender: TObject);
private
{ Private declarations }
stack: array [1..maxstack] of TToken;
sp: integer;
function push(const T:TToken):boolean;
function pop:TToken;
function parse: integer;
public
{ Public declarations }
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
function TMainForm.push(const T:TToken):boolean;
//进栈操作
begin
result:=false;
if sp>=maxstack then
exit;
inc(sp);
stack[sp]:=T;
result:=true;
end;
function TMainForm.pop:TToken;
//出栈操作
begin
pop:=stack[sp];
dec(sp);
end;
function TMainForm.parse:integer;
const
lev:array [TOperator] of integer=(1,1,2,2,-2,-1);//定义操作优先级
opStr:array [TOperator] of string=('ADD','SUB','MUL','DIV','NONAME','NONAM
E');
var
i,state,b:integer;
s:string;
token,t1,t2,t3,tnew:TToken;
regused:integer;
function nexttoken:TToken;
var
r,q:string;
e:integer;
begin
result.kind:=ttOperator;
result.aop:=opRBracket;
if length(s)=0 then
exit;
case s[1] of
'a'..'z','A'..'Z','0'..'9':begin
result.kind:=ttVariable;
inc(regused);
result.areg:=regused;
while (length(s)>0) and (s[1] in ['a'..'z','A'..'Z','0'..'9','.']) d
o
begin
r:=r+s[1];
delete(s,1,1);
end;
val(r,result.value,e);
if e<>0 then
begin
while e<>0do
begin
if not InputQuery('Value?','Please input the value of variable '
+r,q) then
begin
result.kind:=ttError;
exit;
end;
val(q,result.value,e);
end;
//END WHILE
end;
//END IF
toMemo.Lines.Add('MOV t'+inttostr(regused)+' <- '+r+'('+FloatToStrF(
result.value,ffFixed,18,3)+')');
end;
//END 字母情况
'+':begin
result.kind:=ttOperator;result.aop:=opAdd;delete(s,1,1);
end;

'-':begin
result.kind:=ttOperator;result.aop:=opSub;delete(s,1,1);
end;

'*':begin
result.kind:=ttOperator;result.aop:=opMul;delete(s,1,1);
end;

'/':begin
result.kind:=ttOperator;result.aop:=opDiv;delete(s,1,1);
end;

'(':begin
result.kind:=ttOperator;result.aop:=opLBracket;delete(s,1,1)
;
end;
')':begin
result.kind:=ttOperator;result.aop:=opRBracket;delete(s,1,1)
;
end;
else
result.kind:=ttError;
end;
end;
procedure InitStack;
//初始栈
begin
sp:=1;
stack[1].kind:=ttOperator;
stack[1].aop:=opLBracket;
end;
procedure Shift(const NextState:integer);
begin
State:=NextState;
end;
begin
//主体解释函数
result:=3;
s:=fromMemo.Lines.Text;
i:=1;
while i<=length(s)do
if (s<=#32) or (s>=#127) then
delete(s,i,1) el
se begin
s:=upcase(s);inc(i);
end;
fromMemo.Lines.Text:=s;
b:=0;
for i:=1 to length(s)do
//检验括号是否匹配
begin
if s='(' then
inc(b) else
if s=')' then
dec(b);
if b<0 then
exit;
end;
if b<>0 then
exit;
result:=1;
toMemo.Lines.Clear;
InitStack;
state:=1;
regused:=0;
while (length(s)>0) or (sp>1)do
begin
case state of
1:begin
token:=nexttoken;
if not ((token.kind = ttVariable) or
((token.kind = ttOperator) and (token.aop = opLBracket))) then
exit
;
if not push(token) then
begin
result:=5;exit;
end;
if token.kind = ttVariable then
shift(2);
end;
2:begin
token:=nexttoken;
if token.kind <> ttOperator then
begin
result:=2;exit;
end;
if token.aop = opLBracket then
begin
result:=4;exit;
end;
t3:=pop;t2:=pop;
while lev[token.aop]<=lev[t2.aop]do
begin
t1:=pop;
inc(regused);
case t2.aop of
opAdd:tnew.value:=t1.value+t3.value;
opSub:tnew.value:=t1.value-t3.value;
opMul:tnew.value:=t1.value*t3.value;
opDiv:begin
if abs(tnew.value)<EpsReal then
begin
result:=7;
exit;
end;
tnew.value:=t1.value/t3.value;
end;
end;
tnew.areg:=regused;
tnew.kind:=ttVariable;
toMemo.Lines.Add(opstr[t2.aop]+' t'+inttostr(t1.areg)+', t'+inttos
tr(t3.areg)+' -> t'+inttostr(regused)+'('+FloatToStrF(tnew.value,ffFixed,18,
3)+')');
t3:=tnew;
t2:=pop;
end;
if token.aop=opRBracket then
push(t3) else
begin
push(t2);
push(t3);
if not push(token) then
begin
result:=5;exit;
end;
shift(1);
end;
end;
end;
end;
toMemo.Lines.Add('Result: t'+inttostr(stack[1].areg)+'('+FloatToStrF(stack
[1].value,ffFixed,18,3)+')');
result:=0;
end;
procedure TMainForm.Button1Click(Sender: TObject);
var
r:integer;
begin
r:=parse;
if r<>0 then
begin
MessageDlg('Error!',mtWarning,[mbOK],0);
toMemo.Lines.Clear;
case r of //显示出错信息
1:toMemo.Lines.Add('Variable was expected but not found!');
2:toMemo.Lines.Add('Operator was expected but not found!');
3:toMemo.Lines.Add('Bracketsdo
n''t match!!!');
4:toMemo.Lines.Add('Operator was expected but ''('' found!');
5:toMemo.Lines.Add('Stack overflow!!!');
6:toMemo.Lines.Add('Warning: variable not assigned!!!');
7:toMemo.Lines.Add('FPE: Division by zero!!!');
else
toMemo.Lines.Add('Unknow error!');
end;
end;
end;
procedure TMainForm.Button2Click(Sender: TObject);
begin
Application.Terminate;
end;
 
呵呵,我们的编译课居然不让做 课程设计,气死我了!
 
我怎么觉得这是在搞解释器呀
 
楼顶上的,你不是北大的吧?
我给北大的mm做编译实习的作业,说句实话,精神都近于崩溃了。两个月的作业让我
几天之内做出来,我又不是神仙!
我曾经两天写过两个外排序,一天写了一个什么根据网页连接生成图的程序,后来
又改成了网络版,还写什么全文搜索引擎。那时候只是数据结构,现在的作业纯粹是
对我的摧残。
我写了三天,编译变量定义生成符号表都没完成。
 
呵呵,总算遇到研究编译器的了。数据库这种东西,鄙人认为几乎谈不上有难度——会就
会,不会就不会,因此一直在算法里打滚,现在总算遇到同风了。
to mikedeakins:
这么好的题目,明知一个人完不成,怎么不拿出来让大家一起来做呢?
关注中...
 
有意思阿!我们做的是dos下面的。我来看看
 
哎呀,creation-zy 老兄早说就好了。我昏天黑地地干了好几天,也没做完。
不过我写的部分应该足够让同学及格的了。
 
希望能在这里把编译原理好好补一下,我觉得还是应该学好编译原理的。
 
编译原理的程序,很多地方都有,随便找来看看就行了
 
多人接受答案了。
 
顶部