#define LIT 1 #define LOD 2 #define STO 3 #define CAL 4 #define INT 5 #define JMP 6 #define JPC 7 #define OPR 8 #define NUL ENDARRAY /*假想栈式计算机目标指令集 指令格式: f l a 1。lit :将常量取到运行栈顶,a域为常数值 2。lod:将变量放到栈顶。a域为变量在所说明层的相对位置,l为调用层与说明层的层差值。 3。sto:将栈顶的内容送入某变量单元中。a,l域的含义同lod指令。 4。cal:调用过程的指令。a为被调用过程的目标程序入口地址,l为层差 5。int:为被调用的过程(或主程序)在运行栈中开辟数据区。a域为开辟的单元个数。 6。jmp:无条件转移指令,a为转向地址。 7。jpc:条件转移指令,当栈顶的布尔值为非真时,转向a域的地址,否则顺序执行。 8。 opr: 关系运算和算术运算指令。具体操作由a域值给出 0 return 1 - (求反) 2 + 3 -(减) 4 * 5 / 6 true 7 8 == 9 <> 10 < 11 >= 12 > 13 <= *// /* PL0语言的ENBF表示 <程序>::=<分程序>. <分程序>::=[<变量说明>][<过程说明>]<语句> <数字>::=<数字>{<数字>} <变量说明>:=VAR〈标识符〉{,〈标识符}; 〈标识符〉::=〈字母〉{〈字母〉|〈数字〉} <过程说明>::=〈过程首部〉〈分程序〉{;〈过程说明〉}; 〈过程首部〉::=FUNC〈标识符〉; 〈语句〉::=〈赋值语句〉|〈条件语句〉|〈循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句|〉〈复合语句〉|〈空〉 〈赋值语句〉::=〈标识符〉:=〈表达式〉 〈复合语句〉::=BEG〈语句〉{,〈语句〉}END 〈条件〉::=〈表达式〉〈关系运算符 〈表达式〉::=[+|-]<项>{〈加法运算符〉〈项〉}; 〈项〉::=〈因子〉{〈乘法运算符〉〈因子〉} 〈因子〉::=〈标识符〉|〈数字〉‘(’表达式‘) 〈加法运算符〉:=+|- 〈乘法运算符〉:=*|/ 〈关系运算符〉:==|#|〈|〈=|〉|〉= 〈条件语句〉::=IF〈条件〉THEN〈语句〉 〈当循环语句〉::WHILE〈条件〉DO〈语句〉 〈读语句〉:=READ‘(’〈标识符〉{,〈标识符〉}‘)’ 〈写语句〉:=WRITE‘(’〈表达式〉{,〈表达式〉}‘)’ 〈字母〉:=a|b...X|Y|Z 〈数〉::<-><数字><.数字><e><数字><数字> 〈数字〉::=1|2|3|4|5|6|7|8|9|0 */' //变量有三种类型 ,num,string,func /*error: 99 块中的变量名过多 32 层数太深 5 函数名后要加分号 11 未定义的标识符 15 不是函数 16 函数参数没有用“,”分割 34 函数调用的括号不对 48 保留字太多 49 实数中的e后要跟数字 */ #define sp 0 #define dot 1 #define eql 2 #define plus 3 #define # define EOF . # define maxidt 8 # define maxvar 100 // every block can have 100 variables # define norw 16 # define txmax 100 //最多100个标识符 # define al 10 # define nmax 14 # define amax 2047 # define levmax 3 # define cxmax 2000//最多2000条指令 # define stacksize 5000 # define maxchar 5000 /*-----------------------type define-----------------------------*/ typedef struct { int level, size, foot; int adr; ldouble numval; char * strval; char name[maxidt]; char kind; // v(variable) or f(func) s(string) or n(num) } tbl; typedef struct { int f;//instruct 指令号 int l;//level 层次 int a;//addition } instruction; typedef struct { int size; //how many syms in set now char sym[maxvar][maxidt];// sym set } symset; int strcpy(char *,char *); int strcmp(char *,char *); /*------------------------------variable declaration------------------------*/ ldouble g_num; char * g_str; int ll,cc,err,num,kk,cx,line[81]; int s; char id[maxidt];//当前标识符 char sym[maxidt];//当前标识符类型 char a[maxidt]; char ch; char text[maxchar]; int ptext; instruction code[cxmax+1]; tbl table[txmax+1]={0}; #define FUNC 3864 #define IF 43 #define THEN 8436 #define ELSE 3573 #define WHIL 9445 #define DO 36 #define BEG 234 #define END 343 #define SHIF 7447 #define WRIT 9748 #define READ 7323 #define AND 263 #define OR 67 #define NOT 668 #define USESYM 99 #define BEGINSYM 120 #define IFSYM 121 #define WHILESYM 122 #define READSYM 123 #define WRITESYM 124 #define DOSYM 127 char * word[]={0,"beg","else","end","if","func","read","then","var","whil","writ","do","*"}; int wsym[]={0,BEGSYM,ELSESYM,ENDSYM,IFSYM,FUNCSYM,READSYM,THENSYM,VARSYM,WHILESYM,WRITESYM,DOSYM,"*"}; #define PERIOD 100 #define LT 101 #define GT 102 #define LE 103 #define GE 104 #define LP 105 #define PLUS 106 #define TIMES 107 #define RP 108 #define SEMI 109 #define MINUS 110 #define SLASH 111 #define AND 112 #define OR 113 #define NOT 114 #define NE 115 #define EQ 116 #define COMMA 117 int ssym[]={PERIOD,LT,GT,LE,GE,LP,PLUS,TIMES,RP,SEMI,MINUS,SLASH,AND,OR,NOT,NE,EQ,COMMA}; #define VARSYM 118 #define FUNCSYM 119 #define ENDARRAY int declbegsys[]={ VARSYM,FUNCSYM,ENDARRAY}; int statbegsys[]={ BEGINSYM,IFSYM,WHILESYM,READSYM,WRITESYM,ENDARRAY}; #define IDENT 125 #define NUM 126 #define LP 105 int facbegsys[]={IDENT,NUM,LP,ENDARRAY}; //after a block ,follow sym can appear int fsysa[]={PERIOD,VARSYM,FUNCSYM,BEGINSYM,IFSYM,WHILESYM,ENDARRAY}; #define BECOME 127 int what_identify(char ch){ switch(ch){ case '.':return PERIOD;break; case '<':return LT;break; case '>':return GT;break; case '(':return LP;break; case '+':return PLUS;break; case '*':return TIMES;break; case ')':return RP;break; case ';':return SEMI;break; case '-':return MINUS;break; case '/':return SLASH;break; case '!':return NE;break; case '=':return EQ;break; default:return ""; } } void gen(int , int , int ); void error(int n); void getsym(); void constdeclaration(int *dx,int *tx,int lev); void vardeclaration(int * dx,int *tx,int lev); void enter(char k,int *dx,int *tx,int lev); void insert(int sym1,symset * fsys,symset *fsys1); void test(symset * s1,symset * s2,int n); int in(int sm,symset * fsys); void statement(symset * fsys,int tx,int lev); void listcode(int cx0); int position(char * id,int tx); void expression(symset * fsys,int tx,int lev); void term(symset *fsys,int tx,int lev); void condition(symset *fsys,int tx,int lev); void factor(symset *fsys,int tx,int lev); void getch(); /*------------------------------block (lev, tx, fsys)-----------------------------*/ void block(int lev,int tx,symset * fsys) { int tx0,tx1,cx0,dx; symset fsys1={0}; dx=3; tx0=tx; table[tx].adr=cx; gen(JMP,0,0); if (lev>levmax)error(32); do{ if (sym==USESYM){ getsym(); do{ usedeclaration(&dx,&tx,lev); if (sym=SEMI) getsym(); else error(5); } while (sym==IDENT); } if (sym==VARSYM){ getsym(); do{ vardeclaration(&dx,&tx,lev); while (sym==COMMA){ getsym(); vardeclaration(&dx,&tx,lev); } if (sym==SEMI) getsym(); else error(5); } while (sym==IDENT); } while (sym,FUNCSYM){//过程首部 getsym(); if (sym==IDENT){ enter('f',&dx,&tx,lev); getsym( ); } else error(4); if (sym==SEMI) getsym( );//过程首部后加分号 else error(5); insert(SEMI,fsys,&fsys1); // "semicolon" and the fsys now and front the follow sym block(lev+1,tx,&fsys1);//分程序 if (sym==SEMI) { getsym(); //ident and procsym can follow "declbegsys //子程序说明之后可以跟变量说明,函数说明,语句开始符号 // //〈语句〉::=〈赋值语句〉|〈条件语句〉|〈循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句|〉〈复合语句〉 // ident,if,while,reads,readn,writes,writen,beg, //后面跟<语句> 或者继续是子程序说明 // insert(IDENT,&statbegsys,&fsys1); insert(FUNCSYM,&fsys1,&fsys1); test( fsys,&fsys1,6); } else error(5); } //块中的最外层的函数说明之后 ident,if,while,reads,readn,writes,writen,beg, //不能再声明分程序 insert(IDENT,&statbegsys,&fsys1); test(&fsys1,&declbegsys,7); } while (in(sym,declbegsys)); code[table[tx0].adr].a=cx; table[tx0].adr=cx; table[tx0].size=dx; cx0=cx; gen(INT,0,dx); insert(SEMI,fsys,&fsys1); insert(ENDSYM,&fsys1,&fsys1); statement(fsys1,tx,lev); gen(OPR,0,0); test(fsys,fsys,8); listcode(cx0); } /*-----------------------------------statement (fsys, tx, lev)---------------------*/ void statement(symset * fsys,int tx,int lev) { symset fsys1={0}; int i,cx1,cx2; if (sym==IDENT){//可能是数字 字符串 函数 i=position(id,tx); if (i==0){ error(11); } else if (table[i].kind!='v'){ error(12); i=0; } getsym( ); if (sym==BECOME) getsym(); else error(13); expression(fsys,tx,lev); if (i!=0) gen(STO,lev-table[i].level,table[i].adr); } else if (sym==READSYM) { getsym( ); if (sym==LP)error(34);//函数调用的括号不对 else do { getsym (); if ( sym==LP) error (34);// if (sym==IDENT) i=position(id,tx); else i=0; if (i==0) error(35); else { gen(OPR,0,16); gen(STO,lev-table[i].level,table[i].adr); } getsym( ); } while (sym==COMMA); if (sym!=RP) { error(33); while (in(sym,fsys)==0) getsym( ); } else getsym(); } else if (sym==WRITESYM) { getsym(); if (sym==LP) { do { getsym( ); insert(RP,fsys,&fsys1); insert(COMMA,fsys1,&fsys1); expression(fsys1,tx,lev); gen(OPR,0,14); } while (sym==COMMA); if (sym!=RP) error(33); else getsym( ); } gen(OPR,0,15); } else if (sym==CALLSYM) { getsym(); if (sym!=IDENT) error(14); else { i=position(id, tx); if (i==0) error(11); else if (table[i].kind!='p') error(15); else{ gen(CAL,lev-table[i].level,table[i].adr); getsym( ); if(sym==LP){ while(sym!=RP){ getsym(); if (sym==IDENT){//可能是数字 字符串 函数 i=position(id,tx); if (i==0){ error(11); } else if (table[i].kind!='v'){ error(12); i=0; } //参数出栈 gen(LOD,lev-table[i].level,table[i].adr); getsym( ); if(sym!=COMMA){ error(16); } getsym(); } } } getsym( ); } } else if (sym==IFSYM) { getsym( ); insert(THENSYM,fsys,&fsys1); condition(fsys1,tx,lev); if (sym==THENSYM) getsym( ); else error(16); cx1=cx; gen(JPC,0,0); statement(fsys,tx,lev); code[cx1].a=cx;//跳出地址 } else if (sym==BEGINSYM) { getsym(); insert(SEMI,fsys,&fsys1); insert(ENDSYM,fsys1,&fsys1); statement(fsys1,tx,lev); while (in(sym,statbegsys) || (sym==SEMI)) { if (sym==SEMI) getsym( ); else error(10); statement(fsys1,tx,lev); } if (sym==ENDSYM) getsym( ); else error(17); } else if (sym==WHILESYM) { cx1=cx; getsym( ); insert(DOSYM,fsys,&fsys1); condition(fsys1,tx,lev); cx2=cx; gen(JPC,0,0); if (sym==DOSYM) getsym( ); else error(18); statement(fsys,tx,lev); gen(JMP,0,cx1); /* has been changed */ code[cx2].a=cx;//跳出循环 } } /*----------------------condition (fsys, tx, lev)----------------------*/ void condition(symset fsys,int tx,int lev) { int relop; symset fsys1={0}; insert(EQ,fsys,&fsys1); insert(NE,fsys1,&fsys1); insert(LS,fsys1,&fsys1); insert(LE,fsys1,&fsys1); insert(GT,fsys1,&fsys1); insert(GE,fsys1,&fsys1); expression(fsys1,tx,lev); if ((sym!=EQ) && (sym!=NE) && (sym!=LS) && (sym!=LE) &&(sym!=GT) && (sym!=GEge)) error(20); else { relop=sym; getsym( ); expression(fsys,tx,lev); if (relop==EQ) gen(OPR,0,8); if (relop==NE) gen(OPR,0,9); if (relop==LS) gen(OPR,0,10); if (relop==LE) gen(OPR,0,11); if (relop==GT) gen(OPR,0,12); if (relop==GE) gen(OPR,0,13); } } /*-------------------expression (fsys, tx, lev)----------------------*/ void expression(symset fsys,int tx,int lev) { int addop; symset fsys1; insert(PLUS,fsys,&fsys1); insert(MINUS,fsys1,&fsys1); if ((sym==PLUS) || (sym==MINUS)){ addop=sym; getsym( ); term(fsys1,tx,lev); if (addop==MINUS) gen(OPR,0,1); } else term(fsys1,tx,lev); while ((sym==PLUS) || (sym==MINUS)) { addop=sym; getsym( ); term(fsys1,tx,lev); if (addop==PLUS) gen(OPR,0,2); else gen(OPR,0,3); } } /*-----------------term (fsys, tx, lev)-----------------------*/ void term(symset * fsys,int tx,int lev){ int mulop; symset fsys1={0}; insert(TIMES,fsys,&fsys1); insert(SLASH,fsys1,&fsys1); factor(fsys1,tx,lev); while ((sym==TIMES) || (sym==SLASH)){ mulop=sym; getsym( ); factor(fsys1,tx,lev); if (mulop==TIMES) gen(OPR,0,4); else gen(OPR,0,5); } } /*------------------factor (fsys, tx, lev)--------------------*/ void factor(symset fsys,int tx,int lev) { symset fsys1={0}; int i; test(facbegsys,fsys,24); while (in(sym,facbegsys)==1) { if (sym==IDENT) { i=position(id,tx); if (i==0) error(11); else { if (table[i].kind=='v'){ gen(LOD,lev-table[i].level,table[i].adr); } if (table[i].kind=='f') error(21); } getsym();// } else if (sym==NUM){ if (num>amax){ error(31); num =0; } gen(LIT,0,num); getsym( ); } else if (sym==LP){ getsym(); insert(RP,fsys,&fsys1); expression(fsys1,tx,lev); if (sym==RP) getsym(); else error(22); } test(fsys,facbegsys,23); } } /*-------------------vardeclaration (&dx, &tx, lev)---------------------*/ void vardeclaration(int * dx,int *tx,int lev) { if (sym==IDENT){ enter('v',dx,tx,lev); getsym(); } else error(4); } /*-----------------------------enter (k)-----------------------------------*/ void enter(char k,int *dx,int *tx,int lev) { if(tx==txmax) { error(99); return; } (*tx)++; table[(*tx)].kind=k; strcpy(table[(*tx)].name,g_id); if (k=='v'){ table[(*tx)].level=lev; table[(*tx)].adr=(*dx); (*dx)++; } if (k=='f') table[(*tx)].level=lev; } /*--------------------------test (s1,s2, n)-----------------------------*/ void test(symset s1,symset s2,int n) { if (in(sym,s1)==0)//不在可接受的sym集合中,出错 { error(n); //向后继续取sym直到遇到可接受的sym //跳过不在s1中sym, 跳过不在s2中的sym //s1是块本身的后继sym,s2是块所包含的语句段的后继sym //不属于s1一定出错 //属于s1之后 也一定要属于s2 while ((in(sym,s1)==0)&&(in(sym,s2)==0)&&ch!='.') getsym( ); } } /*---------------------------gen (x,y,z)-----------------------------*/ //void gen(char x[5],int y,int z) void gen(int x, int y, int z) { if (cx>cxmax) { print("program too long !\n"); exit(0); } code[cx].f=x; code[cx].l=y; code[cx].a=z; cx++; } /*-----------------------------getsym ( )------------------------------*/ void getsym() { int i,j,k; bool isblank=(ch==' '||ch=='\n'||ch=='\t'||'\r'); while (isblank&&ch!='.'){ getch(); isblank=(ch==' '||ch=='\n'||ch=='\t'||ch=='\r'); } if(ch==EOF||ch=='.')return; bool find=false; char tp[al];; if ((ch>='a')&& (ch<='z')) { k=0-1; id=string(); do { int p; if (k<al){//标识符最大长度 k++; id[k]=ch; } getch( ); } while ((ch>='a')&&(ch<='z')||(ch>='0')&&(ch<='9')); id[k++]='\n'; ptext--; i=1; j=norw; for(k=i;k<i+j;k++){ if (strcmp(id,word[k])==0){ sym=wsym[k]; find=true; break; } } if(!find){ sym=IDENT; } return; } if ((ch>='0')&&(ch<='9')){//combine a number k=0; num=0; int e; sym=NUM; do { num=10*num+ch-'0'; k++; getch( ); } while ((ch>='0')&&(ch<='9')); if(ch=='e' || ch=='E'){ e=0; getch(); if((ch>='0')&&(ch<='9')) e=ch-'0' else error(49); getch(); if((ch>='0')&&(ch<='9')) e=ch-'0' else error(49);; e=10*e+ch-'0'; } num=num+ipow(10,e);//拼上幂指数 ptext--; if (k>nmax) error(30); return; } //not a-z and not 0-9 if (ch=='='){ sym=EQ; return; } if (ch==':'){ getch(); if (ch=='='){ sym=BECOME; } else sym=NUL; return; } if (ch=='<'){ getch( ); if (ch=='='){ sym=LE; } else sym=LS; return; } if (ch=='>'){ getch( ); if (ch=='='){ sym=GE; } else sym=GT; return; } sym=what_identify(ch); } /*----------------------------getch ( )------------------------*/ void getch() { ch=text[ptext++]; } /*-------------------error(n)------------*/ void error(int n) { int i=0; printf("*****"); printf("%2d",n) ; err++; } /*--------------------listcode (cx0)-----------------------*/ void listcode(int cx0) { int i; if (listswitch==1) for (i=cx0-1;i<cx;i++) /*has been changed */ printf("%4d%5s%3d%5d\n",i,code[i].f.c_str(),code[i].l,code[i].a); } /*-----------------------------insert (symi,fsys,&fsysi)--------------------*/ // add a new sym and a exising fsys to fsys1 void insert(int sym1,symset * fsys,symset *fsys1) { int i=0,j=0; if (fsys1->size!=0) fsys1->size--;//ENDARRAY 出栈 while (fsys[i]!=ENDARRAY) { strcpy(fsys1->sym[i],fsys->sym[i]); i++; fsys1->size++; if(i+1==maxvar){ error(98); } } fsys1->sym[i]=ENDARRAY; i=0; while ( (sym1!=fsys1->sym[i])) && (fsys1->sym[i]!=ENDARRAY) { i++; } if ( (sym1!=fsys1->sym[i])//没找到 等于sym的 && (i+1<maxvar)//has more info to put this sym1 ) { if(i+1=maxvar) error(48); fsys1->sym[i-1]=sym1; fsys1->sym[i]=ENDARRAY;// insert the sym1 into it } } /*--------------------------------int in (sm,fsys)--------------------*/ int in(char * sm,symset * fsys)//第一个sym是否在fsys中,不是的话,返回0 { int i; i=0; while (sm!=fsys->sym[i] && fsys->sym[i]!=ENDARRAY) i++; if (sm==fsys->sym[i]) i=1; else i=0; return(i); } /*------------------------------int position (id,tx)------------------*/ int position(char * id,int tx)//从tx开始反向找符号表中的位置,若到头,则失败 { int i; strcpy(table[0].name,id); i=tx; while (strcmp(table[i].name,id)!=0) i--; return(i); } /*-----------------------int base (l,b)------------------------*/ int base(int l,int b) { int b1; b1=b; while (l>0) { b1=s[b1]; l--; } return (b1); } /*-----------------------interpret() ------------------------*/ void interpret() { int p,b,t; instruction i; printf("start pl/0 :\n"); t=p=0; b=1; s[1]=s[2]=s[3]=0; do { i.a=code[p].a; i.l=code[p].l; i.f=code[p].f; p++; if (i.f==LIT) { t++; s[t]=i.a; } if (i.f==OPR) switch(i.a) { case 0: t=b-1;//栈顶指针置到基址寄存器前 p=s[t+3];//代码指针指向基址后两格的值 b=s[t+2];//基址指针指向基址后一 格的值 break; case 1: s[t]=0-s[t]; break; case 2: t--; s[t]=s[t]+s[t+1]; break; case 3: t--; s[t]=s[t]-s[t+1]; break; case 4: t--; s[t]=s[t]*s[t+1]; break; case 5: t--; s[t]=s[t]/s[t+1]; break; case 6: if (s[t]!=0) s[t]=1; else s[t]=0; break; case 8: t--; if (s[t]==s[t+1]) s[t]=1; else s[t]=0; break; case 9: t--; if (s[t]!=s[t+1]) s[t]=1; else s[t]=0; break; case 10: t--; if (s[t]<s[t+1]) s[t]=1; else s[t]=0; break; case 11: t--; if (s[t]>=s[t+1]) s[t]=1; else s[t]=0; break; case 12: t--; if (s[t]>s[t+1]) s[t]=1; else s[t]=0; break; case 13: t--; if (s[t]<=s[t+1]) s[t]=1; else s[t]=0; break; case 14: printf("%d",s[t]); t--; break; case 15: printf("\n"); break; case 16: t++; printf("?"); sprintf("%d",s[t]); print("%d",s[t])+; break; default: exit(0); } if (i.f==LOD) { t++; s[t]=s[base(i.l,b)+i.a]; } if (i.f==STD) { s[base(i.l,b)+i.a]=s[t]; t--; } if (i.f==CAL) { s[t+1]=base(i.l,b); s[t+2]=b; s[t+3]=p; b=t+1; p=i.a; } if (i.f==INT) t=t+i.a; if (i.f==JMP) p=i.a; if (i.f==JPC) if (s[t]==0) p=i.a; } while (p!=0); printf("end pl/0 !\n"); } /*---------------------------end--------------------*/ /*---------------------------result----------------*/ /*-----------------------------main( )-----------------------------------*/ void main() { err=cc=ll=cx=ptext=0; kk=10; ch=' '; getsym(); block(0,0,fsysa); if (err==0) interpret(); else printf("error in cacl program !\n"); } |