⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pl0.c

📁 C语言的pl/0编译器
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -