pl0函数注释Word格式.docx
《pl0函数注释Word格式.docx》由会员分享,可在线阅读,更多相关《pl0函数注释Word格式.docx(41页珍藏版)》请在冰豆网上搜索。
\nPROGRAMINCOMPLETE\n"
exit
(1);
}
ll=cc=0;
//linelength,charactercount
%5d"
cx);
while((!
feof(infile))//added&
modifiedbyalex01-02-09
&
&
((ch=getc(infile))!
='
\n'
))//从文件infile中读取字符并放ch中
fprintf(outfile,"
%c"
ch);
line[++ll]=ch;
//将从文件中读取的字符存储在数组line中
}//while
\n"
line[++ll]='
'
;
}
ch=line[++cc];
//将当前第一个读取到的字符赋值给ch;
字符数+1;
}//getch
//getsasymbolfrominputstream.
voidgetsym(void)
inti,k;
chara[MAXIDLEN+1];
while(ch=='
||ch=='
\t'
)//若是空格或是制表符直接跳过获取下一字符
//modifiedbyyzhang02-03-12,addsomewhitespace
getch();
//判断ch是保留字或者是标识符
if(isalpha(ch))//判断字符ch是否为英文字母若为英文字母返回非零值否则返回零
{//symbolisareservedwordoranidentifier.判断是为标识符和保留字
k=0;
//k记录当前数组a中存入的字符个数
do
if(k<
MAXIDLEN)
a[k++]=ch;
//将ch放进数组a中
getch();
//读取下一字符
}//若当前字符是字母或者数字循环执行
while(isalpha(ch)||isdigit(ch));
//isdigit函数判断字符c是否为数字若为数字返回非零
a[k]=0;
strcpy(id,a);
//id在文件p10.h中声明为char型数组将数组a中的内容给数组id
word[0]=id;
//word在文件p10.h中声明为存储保留字的字符串数组将该数组的第一个元素赋值为id
i=NRW;
//令i的值为保留字的数目
while(strcmp(id,word[i--]));
//将字符串id与Word中保留字对应的字符串进行比较
if(++i)//表示id是已存在于word数组中的保留字
sym=wsym[i];
//symbolisareservedword
else//id不是已定义的保留字是标识符
sym=SYM_IDENTIFIER;
//symbolisanidentifier
//判断ch是否是数字
elseif(isdigit(ch))//判断字符ch是否为数字若为数字返回非零值否则返回零
{//symbolisanumber.
k=num=0;
sym=SYM_NUMBER;
num=num*10+ch-'
0'
//将读进的数字转化为对应的十进制数存储在num中
k++;
while(isdigit(ch));
//当为数字是循环写入
if(k>
MAXNUMLEN)//该数字中所含数字的个数大于MAXNUMLEN
error(25);
//Thenumberistoogreat.该数字过大
//判断ch是否是关系运算符
elseif(ch=='
:
'
)//如果当前字符是'
//获取下一字符
if(ch=='
='
)//下一字符为'
,表示赋值
sym=SYM_BECOMES;
//:
=
//继续读取字符
else//非法字符
sym=SYM_NULL;
//illegal?
>
)//如果当前字符为'
表示>
sym=SYM_GEQ;
//>
else//表示>
sym=SYM_GTR;
<
)//如果当期字符为'
)//读取下一字符为'
表示<
sym=SYM_LEQ;
//<
elseif(ch=='
不相等
sym=SYM_NEQ;
else//表示'
sym=SYM_LES;
//判断ch是否是算术运算符
else//是其他字符
{//othertokens
i=NSYM;
//令i的值为NSYM
csym[0]=ch;
//令数组csym的0号元素为当前字符ch
while(csym[i--]!
=ch);
//在csym中查找是否存在ch,判断ch是否是运算符
if(++i)//存在,表示ch为运算符
sym=ssym[i];
else//出错ch为未知符号
FatalError:
Unknowncharacter.\n"
}//getsym
//generates(assembles)aninstruction.
//代码生成
voidgen(intx,inty,intz)//将x,y,z放入code数组
if(cx>
CXMAX)//cx的值大于CXMAX(sizeofcodearray)当前生成代码的行号大于允许的最大代码行数
//报错
Programtoolong.\n"
exit
(1);
//将x,y,z对应赋值给数组code中下标为cx的元素
//把代码写进当前目标代码数组当前cx所指的位置
code[cx].f=x;
code[cx].l=y;
code[cx++].a=z;
//并移动cx指向下一个空位
}//gen
//testsiferroroccursandskipsallsymbolsthatdonotbelongstos1ors2.
//测试是否出现错误并跳过所有不属于s1和s2的符号
//出错恢复过程
voidtest(symsets1,symsets2,intn)
//s1:
当语法分析进入或退出某一语法单元时当前单词符合应属于的集合
//s2:
在某一出错状态下,可恢复语法分析正常工作的补充单词集合
//n:
出错信息编号,当当前符号不属于合法的s1集合时发出的出错信息
symsets;
if(!
inset(sym,s1))//调用inset函数判断sym是否在s1中
//当前符号符号不在s1中
showset(s1);
//调用showset函数输出s1和s2中的元素
showset(s2);
sym=%d,id=%s\n"
sym,id);
error(n);
//报错
s=uniteset(s1,s2);
//将s1和s2合并并赋值给s
while(!
inset(sym,s))
getsym();
//通过循环找到下一个合法的符号,以恢复语法分析工作
destroyset(s);
//删除s
}//test
intdx;
//dataallocationindex数据分配指数
//enterobject(constant,variableorprocedre)intotable.
//登陆名字表过程
voidenter(intkind)
mask*mk;
//addedbyyzhang02-02-28
//id在table中已经存在报错标识符重复定义
if(position(id)>
0){
error(26);
//Redeclaredidentifier.
//end
//id在table中不存在
tx++;
//table中所含标识符个数+1
strcpy(table[tx].name,id);
//将id赋值给table中第tx号元素
table[tx].kind=kind;
switch(kind)//判别id类型
caseID_CONSTANT:
//常数
if(num>
MAXADDRESS)//该数中所含数字个数过多
//Thenumberistoogreat.
num=0;
table[tx].value=num;
break;
caseID_VARIABLE:
//变量
mk=(mask*)&
table[tx];
mk->
level=level;
address=dx++;
caseID_PROCEDURE:
//程序
}//switch
}//enter
//locatesidentifierinsymboltable.
//查找id在table中的位置,并将位置返回
//查询名字表过程
intposition(char*id)
strcpy(table[0].name,id);
//将id赋值给table中的0号元素
i=tx+1;
while(strcmp(table[--i].name,id)!
=0);
returni;
//返回id在table中对应的下标
}//position
//常量定义分析过程
voidconstdeclaration()
if(sym==SYM_IDENTIFIER)//当前为标识符
getsym();
//调用getsym函数,获取下一个token
if(sym==SYM_EQU||sym==SYM_BECOMES)//当前字符特征表示为=或:
if(sym==SYM_BECOMES)//若为:
=报错(常量声明中应为等号不是赋值号)
error
(1);
//Found'
whenexpecting'
.1号错误
//调用getsym(),获取下一个token
if(sym==SYM_NUMBER)//读取的是数字
{
enter(ID_CONSTANT);
//调用enter函数并传递参数ID_CONTANT常数,把这个常量登录到符号表
getsym();
}
else//读到的不是数字报错
error
(2);
//Theremustbeanumbertofollow'
.等号后应接数字
//常量标识符后接的不是=或:
else
error(3);
//Theremustbean'
tofollowtheidentifier.
//常量声明过程中遇到的第一个符号不是标识符报错
else//addedbyyzhang02-02-28
error(4);
//Theremustbeanidentifiertofollow'
const'
'
var'
or'
procedure'
.
}//constdeclaration
//变量定义分析过程
voidvardeclaration(void)
enter(ID_VARIABLE);
//将参数ID_VARIABLE传递给函数enter,登陆到符号表
//继续读取,获取下一个token
else//变量声明后遇到的第一个符号不是标识符报错
}//vardeclaration
//列出code代码过程
voidlistcode(intfrom,intto)
for(i=from;
to;
i++)//列出从from到to-1的代码
%5d%s\t%d\t%d\n"
i,mnemonic[code[i].f],code[i].l,code[i].a);
//同时打印进文件
}//listcode
//因子处理过程
voidfactor(symsetfsys)
voidexpression();
symsetset;
test(facbegsys,fsys,24);
//Thesymbolcannotbeasthebeginningofanexpression.
//开始因子处理前,先检查当前token是否在facbegsys集合中
while(inset(sym,facbegsys))//循环处理因子
if(sym==SYM_IDENTIFIER)//遇到的是标识符
if((i=position(id))==0)//查符号表,找到当前标识符在符号表中的位置
error(11);
//表示没有找到标识符
//Undeclaredidentifier.
else//如果在符号表中找到了当前标识符的位置,开始生成相应代码
switch(table[i].kind)
{
mask*mk;
caseID_CONSTANT:
//如果这个标识符对应的是常量,值为value,生成lit指令,把value放到栈顶
gen(LIT,0,table[i].value);
break;
caseID_VARIABLE:
//如果标识符是变量名,生成lod指令,
//把位于距离当前层level的层的偏移地址为address的变量放到栈顶
mk=(mask*)&
table[i];
gen(LOD,level-mk->
level,mk->
address);
caseID_PROCEDURE:
//如果在因子处理中遇到的标识符是过程名,出错,抛21号错
error(21);
//Procedureidentifiercannotbeinanexpression.
}//switch
//获取下一个token
elseif(sym==SYM_NUMBER)//遇到的是数字
if(num>
MAXADDRESS)//数字过大,抛出25号错误
error(25);
num=0;
//把数字按0处理
gen(LIT,0,num);
//生成lit指令,把这个数值常量放到栈顶
elseif(sym==SYM_LPAREN)//遇到的是左括号
set=uniteset(createset(SYM_RPAREN,SYM_NULL),fsys);
//合并
expression(set);
//调用expression表达式分析过程,分析set
destroyset(set);
//删除set
if(sym==SYM_RPAREN)//遇到的是右括号
else//否则抛出错误,缺少右括号
error(22);
//Missing'
)'
else//addedbyyzhang02-02-28
test(fsys,createset(SYM_LPAREN,SYM_NULL),23);
//一个因子处理完毕,遇到的token应在fsys集合中,如果不是,抛23号错,
//并找到下一个因子的开始,使语法分析可以继续运行下去
}//while
}//factor
//项处理过程
voidterm(symsetfsys)
intmulop;
set=uniteset(fsys,createset(SYM_TIMES,S