/* Further modified, 20 Feb 2002, parser only This works This compiler supports only lower-case chracters sign != given by # sign <= given by $ sign >= given by % */ #include #include struct namerecord{ int kind; char name[10]; }; int i,ii,j,k,m, n,kind; char line[81]; int norw=11; /* no. of reserved words */ int txmax=100; /* length of indentifier table */ int nmax=14; /* max. no. of digits in numbers */ int al=10; /* length of identifier */ int amax=2047; /* maximum address */ /* The following is for symbol type */ int nul=1; int ident=2; int number=3; int plus=4 ; int minus=5; int mult=6; int slash=7; int oddsym=8; int eql=9; int neq=10; int lss=11; int leq=12; int gtr=13; int geq=14; int lparen=15; int rparen=16; int comma=17; int semicolon=18; int period=19; int becomes=20; int beginsym=21; int endsym=22; int ifsym=23; int thensym=24; int whilesym=25; int dosym=26; int callsym=27; int constsym=28; int varsym=29; int procsym=30; int constant=1; int variable=2; int procedure=3; int null=0; char ch,ch1,dummy; /*last character read */ int sym ; /* last symbol read */ char *id; /* last identifier read */ int num; /* last number read */ int cc; /* character count */ int ll; /* line length */ int kk,ii; char a[20]; struct namerecord table[1000]; char *word[100]; int wsym[1000]; int ssym[1000]; char *mnemonic[100]; FILE *f; char c; void error(i) int i; { printf("error %d\n",i); } getline1() { cc=0; ll=0; n=0; while (((c=getc(f))!=10)) { if (c==EOF){ch=-1; return 0;} n++; ll++; line[n]=c; } n++; ll++; line[n]=' '; for (i=1; i<=n; i++)printf("%c", line[i]); printf("\n"); return 1; } getch() /* get one character */ { if (cc==ll){ if (ch==-1) {printf("PROGRAM INCOMPLETE"); getchar(); return 0;} getline1(); } cc=cc+1; ch=line[cc]; } search() { int i, j, len; char *s; for (i=norw; i>=1; i--) { s=word[i]; len=strlen(s); for (j=1; j<=len; j++){ if(a[j]!=*s) break; s++; } if (j>len){ return i;} } return 0; } getsym() /* gets one symbol */ { while (ch==' ') getch(); if ((ch >= 'A') && (ch <= 'z')) { k=0; do{ if (k='0') && (ch<='9')) || ((ch>='A') && (ch<='z'))); a[k+1]=0; id=a+1; if ((i=search())!=0)sym=wsym[i]; else sym=ident; } else if ((ch>='0') && (ch <= '9')) { k=0; num=0; sym=number; do { num=10*num + (ch - '0'); k++; getch(); } while ((ch >= '0') && (ch <= '9')); if (k > nmax) error(30); } else if (ch==':') { getch(); if (ch=='='){ sym=becomes; getch(); } else sym=null; } else if (ch==-1) {return;} else { sym=ssym[ch]; getch(); } } enter(k,ptx) /* This enters a symbol into the table */ int k; int *ptx; { char *id1; int ii,len; (*ptx)++; id1=id; len=strlen(id); for (ii=0;ii<=len;ii++) {table[*ptx].name[ii]=*id1; id1++;} table[*ptx].kind=k; } mismatch(a,b) char *a; char *b; { int i; int len1; int len2; len1=strlen(a); len2=strlen(b); i=0; if (len1!=len2) return 1; else { while(i<=len2-1) { if (a[i]!=b[i]) return 1; i++; /* a++; */ } return 0; } } int position(id,ptx) /* This finds the position of id */ char *id; int *ptx; { char buf[10]; char *id1; int i,ii,len; id1=id; len=strlen(id); for (i=0;i<=len;i++) {table[0].name[i]=*id1; id1++;} i=*ptx; do { len=strlen(table[i].name); for (ii=0;ii<=len-1;ii++) { buf[ii]=table[i].name[ii]; } buf[ii]=0; i--;} while (mismatch(buf, id)); return i+1; } constdeclaration(ptx) int *ptx; { if (sym==ident) { getsym(); if ((sym==eql) || (sym==becomes)) { if (sym==becomes) error(1); getsym(); if (sym==number) {enter(constant,ptx); getsym();} } } } vardeclaration(ptx) int *ptx; { if (sym==ident) {enter(variable, ptx); getsym();} else error(4); } factor(ptx) int *ptx; { int i; if (sym==ident) { i=position(id,ptx); if (i==0) error(11); else { kind=table[i].kind; if (kind==procedure) error(21); getsym(); } } else if(sym==number) getsym(); else if(sym==lparen) { getsym(); expression(ptx); if (sym==rparen)getsym(); else error(22); } } term(ptx) int *ptx; { factor(ptx); while((sym==mult)||(sym==slash)) { getsym(); factor(ptx); } } expression(ptx) int *ptx; { if ((sym==plus) ||(sym==minus)){ getsym();} term(ptx); while ((sym==plus)||(sym==minus)) { getsym(); term(ptx); } } condition(ptx) int *ptx; { if(sym==oddsym) { getsym(); expression(ptx); } else { expression(ptx); if ((sym!=eql)&&(sym!=neq)&&(sym!=lss)&& (sym!=leq)&&(sym!=gtr)&&(sym!=geq)) error(20); else { getsym(); expression(ptx); } } } statement(ptx) int *ptx; { int i; if (sym==ident){ i=position(id,ptx); if(i==0) error(11); else if (table[i].kind!=variable) { error(12); i=0; }; getsym(); if (sym==becomes) getsym(); else error(13); expression(ptx); } else if (sym==callsym) { /* procedure call */ getsym(); if (sym!=ident) error(14); else { i=position(id, ptx); if(i==0) error(11); else if (table[i].kind!=procedure) error(15); getsym(); } } else if (sym==ifsym) { /* if statement */ getsym(); condition(ptx); if (sym==thensym) getsym(); else error(16); statement(ptx); } else if (sym==beginsym) { /* begin ... end */ getsym(); statement(ptx); while(sym==semicolon) { getsym(); statement(ptx);} if (sym==endsym) getsym(); else error(17); } else if (sym==whilesym) { /* while statement */ getsym(); condition(ptx); if (sym==dosym) getsym(); else error(18); statement(ptx); } } block(tx) int tx; { int tx0; tx0=tx; // printf("here"); getchar(); do { if (sym==constsym) { getsym(); constdeclaration(&tx); while(sym==comma) { getsym(); constdeclaration(&tx); } if(sym==semicolon)getsym(); else error(5); } if (sym==varsym) { getsym(); vardeclaration(&tx); while (sym==comma) { getsym(); vardeclaration(&tx); } if(sym==semicolon) getsym(); else error(5); } while(sym==procsym) { getsym(); if(sym==ident){ enter(procedure,&tx); getsym(); } else error(4); if (sym==semicolon) getsym(); else error(5); block(tx); if(sym==semicolon) { getsym(); } else error(5); } }while ((sym==constsym)||(sym==varsym)||(sym==procsym)); statement(&tx); } main(argc, argv) int argc; char *argv[]; { word[1]="begin"; word[2]="call"; word[3]="const"; word[4]="do"; word[5]="end"; word[6]="if"; word[7]="odd"; word[8]="procedure"; word[9]="then"; word[10]="var"; word[11]="while"; wsym[1]=beginsym; wsym[2]=callsym; wsym[3]=constsym; wsym[4]=dosym; wsym[5]=endsym; wsym[6]=ifsym; wsym[7]=oddsym; wsym[8]=procsym; wsym[9]=thensym; wsym[10]=varsym; wsym[11]=whilesym; ssym['+']=plus; ssym['-']=minus; ssym['*']=mult; ssym['/']=slash; ssym['(']=lparen; ssym[')']=rparen; ssym['=']=eql; ssym[',']=comma; ssym['.']=period; ssym['#']=neq; ssym['<']=lss; ssym['>']=gtr; ssym['$']=leq; ssym['%']=geq; ssym[';']=semicolon; f=fopen(*++argv,"r"); kk=al; cc=0; ll=0; ch=' '; getsym(); block(0); getchar(); if (sym!=period) error(9); printf("no errors"); getchar(); exit:; }