📄 pl0.c
字号:
#include<stdio.h>
#include<string.h>
#include<ctype.h>
#include<stdarg.h>
#include<stdlib.h>
#define norw 13
#define txmax 100
#define nmax 14
#define al 10
#define amax 2047
#define levmax 3
#define cxmax 200
#define N 32
#define label 99
//用枚举类型定义集合元素的取值,在此基础上定义集合,详见程序说明1
//sym集合元素
enum symbol{null,ident,number,plus,minus, times, slash,oddsym, eql, neq,
lss, leq, gtr, geq, lparen,rparen,comma,semicolon,period,becomes,
beginsym,endsym,ifsym,thensym,whilesym,writesym,readsym,dosym,callsym,constsym,
varsym,procsym};
//wsym集合元素
enum wsymbol{begin,call,end,ifs,dos,consts,odd,procedure,read,then,
var,whiles,write};
typedef char alfa[al];
enum object{constant,variable,procedur};
struct set
{ int nn;
enum symbol element[N];
};
//自定义集合类型
typedef struct set symset;
enum fct{lit,opr,lod,sto,cal,intr,jmp,jpc};//因int是C的关键字,故用intr代替
/*typedef enum fctenum fct; */
struct instruction
{
enum fct f;
int l; /*l is range from 0 to levmax*/
int a; /*a is range from 0 to amax*/
};
/*The declaration of variable*/
FILE *fa,*fa1,*fa2;
FILE *fin;
int listswitch; /*the type of listswith is bool */
char ch;
enum symbol sym;
alfa id;
int num,cc,ll,kk,cx;
char line[81];
alfa a;
struct instruction code[cxmax];
char word[norw][10]={"begin","call","const","do","end","if","odd","procedure","read","then","var","while","write"};
enum symbol wsym[norw];
enum fct mnemonic[8];
symset declbegsys={0},statbegsys={0},facbegsys={0}; /*initialization of nn*/
symset tempset={0},nullset={0};
struct
{
alfa name;
enum object kind;
int val; /*if the kind is constant*/ /*???*/
int level,adr,size; /*if the kind is variable or procedur*/
}table[txmax];
//按课本程序原意,常量与变量和过程是共用的关系,因常量说明仅占一个值域,为方便起见,在此把
//他们的域均作结构体的项看
alfa fname;
int err;
//以下是关于集合的运算
//判断指定元素属不属于集合
int IN(symset y,enum symbol exam)
{
int i;
for(i=0;i<y.nn;i++)
if(y.element[i]==exam)
return 1;
return 0;
}
//向集合中插入若干个元素
symset ADD(symset y, ...)
{
int i=y.nn;
enum symbol *q;
va_list ap;
q=va_start(ap,y);
while(*q<N&&*q>0)
{
if(IN(y,*q)) q++;
else
{
y.element[i]=*q;
q++; i++; y.nn++;
}
}
va_end(ap);
return y;
}
//从集合中删除若干元素
symset DEL(symset y,...)
{
int i,j;
va_list ap;
enum symbol *q;
q=va_start(ap,y);
while(*q>=0&&*q<N)
{
for(i=0;i<N;i++)
if(*q==y.element[i])
{
for(j=i;j<y.nn-1;j++)
y.element[j]=y.element[j+1];
y.element[j]=-1;
}
q++;
}
va_end(ap);
return y;
}
//集合并
symset Union(symset y, symset z)
{
int i,j;
for(i=y.nn,j=0;j<z.nn;i++,j++)
y.element[i]=z.element[j];
y.nn=i;
return y;
}
//错误识别函数
void error(int n)
{
int i;
for(i=0;i<cc-1;i++)
printf(" ");
printf("! ");
printf("%d ",n);
for(i=0;i<cc-1;i++)
fprintf(fa1," ");
fprintf(fa1,"! ");
fprintf(fa1,"%d",n);
err++;
}
//取字符函数
int getch()
{
if(cc==ll)
{
if(feof(fin))
{
printf("program incomplete");
fclose(fa);
fclose(fa1);
fclose(fin);
exit(0);
//return 0; /**/
}
ll=0;
cc=0;
printf("\n%d",cx);
fprintf(fa1,"%d",cx);
do
{
ch=fgetc(fin);
printf("%c",ch);
fputc(ch,fa1);
line[ll]=ch;
ll++;
}while(ch!='\n'&&!feof(fin));
}
ch=line[cc];
cc=cc+1; //cc is the positon of next char to get
return 1;
}
/*因C语言中数组以0开始,且每行以CL(ASCII=10)结束
所以上面的语句与pascal的有些出入
*/
//查找 ssym ,见程序说明3(2)
int getssym(char ch) /* return type miss!*/
{
switch(ch)
{
case '+':return plus;
case '-':return minus;
case '*':return times;
case '/':return slash;
case '(':return lparen;
case ')':return rparen;
case '=':return eql;
case ',':return comma;
case '.':return period;
case '#':return neq;
case ';':return semicolon;
default: return null;
}
}
//查找 mnemonic 见说明3(2)
char *getmnemonic(int i) /* return type miss!*/
{
char *mnem;
switch(i)
{
case 0:mnem="lit";break;//lost break!!
case 1:mnem="opr";break;
case 2:mnem="lod";break;
case 3:mnem="sto";break;
case 4:mnem="cal";break;
case 5:mnem="intr";break;
case 6:mnem="jmp";break;
case 7:mnem="jpc";break;
}
return mnem;
}
//取单词函数
void getsym()
{
int i,j,k; //k is the number of the word geted!
while(ch==32||ch==10) //除了多余的空格,还要掠过换行(回车)!!以在getch()中说明过
getch();
if(ch<='z'&&ch>='a') //如果是字符串
{
k=0;
do
{
if(k<al)
{
a[k]=ch;
k++;
}
getch();
}while(ch<='z'&&ch>='a'||ch<='9'&&ch>='0');
if(k>=kk)
kk=k;
else
do
{
a[kk-1]=' '; //12/21:06 change kk to kk-1
kk--;
}while(k<kk);
for(i=0;i<k;i++) //change narrow to k at 12/22:53
id[i]=a[i];
for(i=k;i<al;i++) //change narrow to k at 12/22:53
id[i]=0;
i=0;
j=norw-1;
do //查找id在符号表中的位置
{
k=(i+j)/2;
if(strcmp(id,word[k])<=0) /*change!*/
j=k-1;
if(strcmp(id,word[k])>=0) /*chang!*/
i=k+1;
}while(i<=j);
if(i-1>j)
sym=wsym[k];
else
sym=ident;
}
else if(ch<='9'&&ch>='0') //如果是数字
{
k=0;
num=0;
sym=number;
do
{
num=10*num+(ch-'0');
k=k+1;
getch();
}while(ch<='9'&&ch>='0');
if(k>nmax)
error(30);
}
else if(ch==':') //其他符号
{
getch();
if(ch=='=')
{
sym=becomes;
getch();
}
else
sym=null;
}
else if(ch=='<')
{
getch();
if(ch=='=')
{
sym=leq;
getch();
}
else
sym=lss;
}
else if(ch=='>')
{
getch();
if(ch=='=')
{
sym=geq;
getch();
}
else
sym=gtr;
}
else
{
sym=getssym(ch);
getch();
}
}
//生成代码
void gen(enum fct x,int y,int z)
{
if(cx>cxmax)
{
printf("program too long");
exit(0);//
}
code[cx].f=x;
code[cx].l=y;
code[cx].a=z;
cx=cx+1;
}
void test(symset s1,symset s2,int n)
{
if(IN(s1,sym)==0)
{
error(n);
s1=Union(s1,s2); //
while(IN(s1,sym)==0)
getsym();
}
}
//block函数的全局变量和参数
int lev, tx;
//symset fsys;
int txtx;
int dx,tx0,cx0;
int dxdx,tx0tx0,cx0cx0;
//dxdx,tx0tx0,cx0cx0分别作dx,tx0,cx0的参数传递用,因为dx,tx0,cx0为block的局部参数
//block递归调用时需要保留其值:dxdx=dx,tx0tx0=tx0,cx0cx0=cx0,递归调用后返回调用前的值
//dx=dxdx,tx0=tx0tx0,cx0=cx0cx0;这样避免block的局部变量到statement,expression,term,
//factor以及codition的参数传递 另见说明4
//符号表登录
void enter(enum object k)
{
table[tx].kind=k;
strcpy(table[tx].name,id);//
if(k==constant)
{
if(num>amax)
{
error(31);
num=0;
}
table[tx].val=num;
}
if(k==variable)
{
table[tx].level=lev;
table[tx].adr=dx;
dx++;
}
if(k==procedur)
table[tx].level=lev;
tx=tx+1; //change the position of tx at 13/19
}
//查找符号在符号表中的位置
int position(alfa id)
{
int i;
// strcpy(table[0].name,id); //18号15:32
//课本上的语句没有必要!这是我修改后的。
i=tx;
while(strcmp(table[i].name,id)!=0)
{ i=i-1;
if(i<0)
return -1;
}
return i;
}
//常量声明
void constdeclaration()
{
if(sym == ident)
{
getsym();
if(sym==eql||sym==becomes)
{
if(sym==becomes)
error(1);
getsym();
if(sym==number)
{
enter(constant);
getsym();
}
else
error(2);
}
else
error(3);
}
else
error(4);
}
//变量声明
void vardeclaration()
{
if(sym==ident)
{
enter(variable);
getsym();
}
else
error(4);
}
//列代码
void listcode()
{
int i;
char *mnem;
if(listswitch)
{
for(i=cx0;i<= cx - 1;i++)
{
mnem=getmnemonic(code[i].f);//取得code[i].f所代表的字符串
printf("%d %s %d %d\n",i,mnem,code[i].l,code[i].a);
fprintf(fa,"%d %s,%d %d\n",i,mnem,code[i].l,code[i].a);
}
}
}
//the para of statement
int i,cx1,cx2;
//int ii,cx1cx1,cx2cx2;
//the para of expression term
enum symbol addop,mulop;
//函数声明
void expression(symset fsys);
//因子
void factor(symset fsys)
{
int i;
symset tempset={0};
test(facbegsys, fsys, 24);
while(IN(facbegsys,sym))
{
if(sym==ident)
{
i=position(id);
if(i<0) //sucess! change i=0 to i==0 at 16号0:00
error(11);
else
{
if(table[i].kind==constant)
gen(lit, 0, table[i].val);
else if(table[i].kind==variable)
gen(lod, lev - table[i].level, table[i].adr);
else if(table[i].kind==procedur)
error(21);
}
getsym();
}
else if(sym==number)
{
if(num > amax)
{
error(31);
num = 0;
}
gen(lit, 0, num);
getsym();
}
else if(sym==lparen)
{
getsym();
tempset=ADD(fsys,rparen);
expression(tempset);
if(sym == rparen)
getsym();
else
error(22);
}
test(fsys, facbegsys, 23);
}
}
//项
void term(symset fsys)
{
symset tempset=fsys;
tempset=ADD(tempset,times,slash);
factor(tempset);
while(sym==times||sym==slash)
{
mulop=sym;
getsym();
factor(tempset);
if(mulop == times)
gen(opr, 0, 4);
else
gen(opr, 0, 5);
}
}
//表达式
void expression(symset fsys)
{
symset tempset=fsys;
tempset=ADD(tempset,plus,minus);
if(sym==plus||sym==minus)
{
addop= sym;
getsym();
term(tempset);
if(addop == minus)
gen(opr, 0, 1);
}
else
term(tempset);
while(sym==plus||sym==minus)
{
addop= sym;
getsym();
term(tempset);
if(addop == plus)
gen(opr, 0, 2);
else
gen(opr, 0, 3);
}
}
//条件表达式
void condition(symset fsys)
{
enum symbol relop;
symset tempset;
if (sym == oddsym)
{
getsym();
expression(fsys);
gen(opr, 0, 6);
}
else
{
tempset=fsys;
tempset=ADD(tempset,eql, neq, lss, leq, gtr, geq);
expression(tempset);
if(sym!=eql&&sym!=neq&&sym!=lss&&sym!=leq&&sym!=gtr&&sym!=geq)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -