PL0文法编译器C语言源代码

转自我的CSDN博客: http://blog.csdn.net/njdragonfly

对PL0文法进行了扩充,主要增加了数组及结构体的功能,并用C语言实现了之。

#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "ctype.h"
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
typedef int BOOL;
#define cxmax 2000
#define amax 16383
#define imax 100 /* length of identifier table */
#define tmax 100 /* length of type table */
#define lmax 10  /* maximum level */
#define al 10  /* length of identifiers */
#define norw 27  /* number of reserverd words */
/* standard function */
#define fabs 0
#define fsqr 1
#define fodd 2
#define fchr 3
#define ford 4
#define fwrite 5
#define fwriteln 6
#define fread 7
#define freadln 8
#define feoln 9
/* standard types */
#define intip 1
#define booltip 2
#define chartip 3
/*指令码*/
typedef enum opcode{
	add, neg, mul, divd, remd, div2, rem2, eqli, neqi, lssi,
	leqi, gtri, geqi, dupl, swap, andb, orb,
	load, stor, hhalt, wri, wrc, wrl, rdi, rdc, rdl, eol,
	ldc, ldla, ldl, ldg, stl, stg, move, copy, addc, mulc,
	jump, jumpz, call, adjs, sets, pexit
}opcode;
/*指令结构体*/
typedef struct instr{
	opcode op;
	int a;
}instr;
/*词法类别*/
typedef enum symbol{
	ident, number, sstring, plus, minus, star, lbrack, rbrack,
	colon, eql, neq, lss, leq, gtr, geq, lparen, rparen, comma, 
	semicolon, period, becomes,
	beginsym, endsym, ifsym, thensym, elsesym, whilesym, dosym,
	casesym, repeatsym, untilsym, forsym, tosym, downtosym,
	notsym, divsym, modsym, andsym, orsym, constsym, varsym,
	typesym, arraysym, ofsym, recordsym, progsym, funcsym,
	procsym
}symbol;
/*变量类型*/
typedef enum idkind{
	konst, varbl, field, tipe, funkt
}idkind;
/*类型的种类,简单的,数组,记录类型*/
typedef enum tpkind{
	simple, arrays, records
}tpkind;
typedef char alfa[al+1];
instr code[cxmax + 1];
int m[amax + 1];
/*词法分析相关全局变量*/
char ch;
int cc = 0, ll = 0;
char line[129];
symbol sym;
alfa id;
int num;
char str[81];
int slen;
/*alfa word[norw + 1];*/
int cx;
int lev;
int dx;
BOOL labeled;
int nl; /* as namelist[-1] */
int namelist[lmax];
int ix, tx; /* indices in tables */
/* identifier table */
typedef struct ITAB{
	alfa name;
	int link;
	int tip;
	idkind kind;
	union{
		int val; /*常量类型的值*/
		struct{
			int vlevel;
			int vadr;
			BOOL refpar;
		};   /*变量类型的属性*/
		int offset; /*域类型的偏移地址*/
		struct{
			int flevel;
			int fadr;
			int lastpar;
			int resultadr;
			BOOL inside;
		};   /*函数类型的属性*/
	};
}ITAB;
ITAB itab[imax + 1];
/* type table */
typedef struct TTAB{
	int size;
	tpkind kind;
	union{
		struct{
			int low;
			int high;
			int elemtip;
		}; /*数组类型的属性*/
		int fields; /*记录类型最后一个域的地址*/
	};
}TTAB;
TTAB ttab[tmax + 1];
/*保留字*/
static struct{
	alfa name;
	symbol lex;
}word[] = {
	{ "", -1 },
	{ "begin", beginsym },
	{ "end", endsym },
	{ "if", ifsym },
	{ "then", thensym },
	{ "else", elsesym },
	{ "while", whilesym },
	{ "do", dosym },
	{ "case", casesym },
	{ "repeat", repeatsym },
	{ "until", untilsym },
	{ "for", forsym },
	{ "to", tosym },
	{ "downto", downtosym },
	{ "not", notsym },
	{ "div", divsym },
	{ "mod", modsym },
	{ "and", andsym },
	{ "or", orsym },
	{ "const", constsym },
	{ "var", varsym },
	{ "type", typesym },
	{ "array", arraysym },
	{ "of", ofsym },
	{ "record", recordsym },
	{ "program", progsym },
	{ "function", funcsym },
	{ "procedure", procsym }
};
FILE * source;
BOOL eof_flag = FALSE;
symbol search()
{
	int i;
	for(i = norw; i >= 1; i--)
	{
		if(strcmp(id, word[i].name) == 0)
			return word[i].lex;
	}
	return ident;
}
void error(int n)
{
	int i;
	for(i = 0; i < ll; i++)
		putchar(line[i]);
	for(i = 0; i <= cc - 1; i++)
		putchar(' ');
	printf("^/n");
	printf("error %d detected/n", n);
	exit(1);
}
void getch()
{
	if (cc == ll)
	{
		memset(line, 0, 129);
		if(feof(source))
		{
			fprintf(stderr, "program incomplete/n");
			exit(0);
		}
		ll = 0;
		cc = 0;
		while(!feof(source) && (ch = getc(source)) != '/n')
		{
			line[ll] = ch;
			ll++;
		}
		if(ch == '/n')
		{
			line[ll] = ch;
			ll++;
		}
	}
	ch = line[cc];
	cc++;
}
void getsym()
{
	int k;
	int strend;
	while(ch == ' ' || ch == '/t' || ch == '/n')
		getch();
	if(isalpha(ch))
	{
		memset(id, 0, al+1);
		k = 0;
		do{
			if(k != al)
			{
				id[k] = ch;
				k++;
			}
			getch();
		}while(isalnum(ch));
		sym = search();
	}
	else if(isdigit(ch))
	{
		num = 0;
		sym = number;
		do{
			num = 10 * num + (ch - '0');
			getch();
		}while(isdigit(ch));
	}
	else if(ch == ':')
	{
		getch();
		if(ch == '=')
		{
			getch();
			sym = becomes;
		}
		else
			sym = colon;
	}
	else if(ch == '>')
	{
		getch();
		if(ch == '=')
		{
			getch();
			sym = geq;
		}
		else
			sym = gtr;
	}
	else if(ch == '<')
	{
		getch();
		if(ch == '=')
		{
			getch();
			sym = leq;
		}
		else if(ch == '>')
		{
			getch();
			sym = neq;
		}
		else
			sym = lss;
	}
	else if(ch == '.')
	{
		getch();
		if(ch == '.')
		{
			getch();
			sym = colon;
		}
		else
			sym = period;
	}
	else if(ch == '/'')
	{
		slen = 0;
		strend = FALSE;
		sym = sstring;
		do{
			if(cc == ll)
				error(101);
			getch();
			if(ch == '/'')
			{
				getch();
				if(ch == '/'')
				{
					str[slen] = ch;
					slen++;
				}
				else
					strend = TRUE;
			}
			else
			{
				str[slen] = ch;
				slen++;
			}
		}while(strend == FALSE);
		if(slen == 0)
			error(102); /*不允许空字符串*/
		str[slen++] = '/0';
	}
	else if(ch == '+')
	{
		getch();
		sym = plus;
	}
	else if(ch == '-')
	{
		getch();
		sym = minus;
	}
	else if(ch == '*')
	{
		getch();
		sym = star;
	}
	else if(ch == '(')
	{
		getch();
		sym = lparen;
	}
	else if(ch == ')')
	{
		getch();
		sym = rparen;
	}
	else if(ch == '[')
	{
		getch();
		sym = lbrack;
	}
	else if(ch == ']')
	{
		getch();
		sym = rbrack;
	}
	else if(ch == '=')
	{
		getch();
		sym = eql;
	}
	else if(ch == ',')
	{
		getch();
		sym = comma;
	}
	else if(ch == ';')
	{
		getch();
		sym = semicolon;
	}
	else if(ch == '{')
	{
		do{
			getch();
		}while(ch != '}');
		getch();
		getsym();
	}
	else
		error(104);
}
void check(symbol s)
{
	if(sym != s)
		error(s);
}
void skip(symbol s)
{
	check(s);
	getsym();
}
/*将符号串登记入符号表*/
void enter(alfa id, idkind k, int t)
{
	int j;
	if(ix == imax)
		error(104);
	else
	{
		ix++;
		strcpy(itab[0].name, id);
		if(lev == -1)
			j = nl;
		else
			j = namelist[lev];
		while(strcmp(itab[j].name, id) != 0)
			j = itab[j].link;
		if(j != 0)
			error(105);
		else
		{
			strcpy(itab[ix].name, id);
			if(lev == -1)
				itab[ix].link = nl;
			else
				itab[ix].link = namelist[lev];
			itab[ix].tip = t;
			itab[ix].kind = k;
			if(lev == -1)
				nl = ix;
			else
				namelist[lev] = ix;
		}
	}
}
/*在符号表中查找符号,返回位置*/
int position()
{
	int i , j;
	strcpy(itab[0].name, id);
	i = lev;
	do{
		if(i == -1)
			j = nl;
		else
			j = namelist[i];
		while(strcmp(itab[j].name, id) != 0)
			j = itab[j].link;
		i = i - 1;
	}while(i >= -1 && j == 0);
	if(j == 0)
		error(106);
	return j;
}
void gen(instr i)
{
	switch(i.op)
	{
	case dupl:
	case eol:
	case ldc:
	case ldla:
	case ldl:
	case ldg:
		dx = dx - 1;
		break;
	case add:
	case mul:
	case divd:
	case remd:
	case eqli:
	case neqi:
	case lssi:
	case leqi:
	case gtri:
	case geqi:
	case andb:
	case orb:
	case wrc:
	case rdi:
	case rdc:
	case stl:
	case stg:
	case jumpz:
		dx = dx + 1;
		break;
	case stor:
	case wri:
	case move:
		dx = dx + 2;
		break;
	case copy:
		dx = dx - i.a + 1;
		break;
	case adjs:
		dx = dx + i.a;
		break;
	}
	if(!(((i.op == addc || i.op == adjs) && (i.a == 0)) || ((i.op == mulc) && (i.a == 1))))
	{
		if(labeled)
		{
			code[cx] = i;
			cx = cx +1;
			labeled = FALSE;
		}
		else if(code[cx - 1].op == ldc && i.op == add)
		{
			code[cx - 1].op = addc;
		}
		else if(code[cx - 1].op == ldc && i.op == mul)
		{
			code[cx - 1].op = mulc;
		}
		else if(code[cx - 1].op == ldc &&  i.op == neg)
		{
			code[cx - 1].a = -code[cx - 1].a;
		}
		else if(code[cx - 1].op == ldc && code[cx - 1].a == 2 && i.op == divd)
		{
			code[cx - 1].op = div2;
		}
		else if(code[cx - 1].op == ldc && code[cx - 1].a == 2 && i.op == remd)
		{
			code[cx - 1].op = rem2;
		}
		else if(code[cx - 1].op == ldc && i.op == stor)
		{
			code[cx - 1].op = stg;
		}
		else if(code[cx - 1].op == ldc && i.op == load)
		{
			code[cx - 1].op = ldg;
		}
		else if(code[cx - 1].op == ldla && i.op == stor)
		{
			code[cx - 1].op = stl;
		}
		else if(code[cx - 1].op == ldla && i.op == load)
		{
			code[cx - 1].op = ldl;
		}
		else
		{
			code[cx] = i;
			cx = cx + 1;
		}
	}
}
void gen0(opcode op)
{
	instr i;
	i.op = op;
	gen(i);
}
void gen1(opcode op, int a)
{
	instr i;
	i.op = op;
	i.a = a;
	gen(i);
}
int codelabel()
{
	labeled = TRUE;
	return cx;
}
void address(int lv, int ad)
{
	if(lv == 0)
		gen1(ldc, ad);
	else if(lv == lev)
		gen1(ldla, ad - dx);
	else
	{
		gen1(ldl, -dx);
		while(lv + 1 != lev)
		{
			gen0(load);
			lv = lv + 1;
		}
		gen1(addc, ad);
	}
}
void addressvar(int ref)
{
	address(itab[ref].vlevel, itab[ref].vadr);
	if(itab[ref].refpar)
		gen0(load);
}
void mustbe(int x, int y)
{
	if(x != y)
	{
		if((ttab[x].kind == arrays) && (ttab[y].kind == arrays) && 
			(ttab[x].low == ttab[y].low) && (ttab[x].high == ttab[y].high))
			mustbe(ttab[x].elemtip, ttab[y].elemtip);
		else
			error(107);/*类型不匹配*/
	}
}
void expression(int * x);
void selector(int * t, int * ref)
{
	int j, x;
	*t = itab[*ref].tip;
	getsym();
	if(sym == period ||sym == lbrack)
	{
		addressvar(*ref);
		*ref = 0;
		while(sym == period || sym == lbrack)
		{
			switch(sym)
			{
			case period:
				if(ttab[*t].kind != records)
					error(108);
				else
				{
					getsym();
					check(ident);
					j = ttab[*t].fields;
					strcpy(itab[0].name, id);
					while(strcmp(itab[0].name, id) != 0)
						j = itab[j].link;
					if(j == 0)
						error(109);
					else
					{
						gen1(addc, itab[j].offset);
						*t = itab[j].tip;
						getsym();
					}
				}
				break;
			case lbrack:
				do{
					if(ttab[*t].kind != arrays)
						error(110);
					else
					{
						getsym();
						expression(&x);
						mustbe(intip, x);
						gen1(addc, -(ttab[*t].low));
						*t = ttab[*t].elemtip;
						gen1(mulc, ttab[*t].size);
						gen0(add);
					}
				}while(sym == comma);
				skip(rbrack);
				break;
			}
		}
	}
}
void varpar(int * t)
{
	int j;
	check(ident);
	j = position();
	selector(t, &j);
	if(j != 0)
		addressvar(j);
}
/*标准函数*/
void standfct(int n)
{
	int x, l;
	switch(n)
	{
	case fabs:
		skip(lparen);
		expression(&x);
		mustbe(intip, x);
		gen0(dupl);
		gen1(ldc, 0);
		gen0(lssi);
		l = codelabel();
		gen1(jumpz, 0);
		gen0(neg);
		code[l].a = codelabel();
		skip(rparen);
		break;
	case fsqr:
		skip(lparen);
		expression(&x);
		mustbe(intip, x);
		gen0(dupl);
		gen0(mul);
		skip(rparen);
		break;
	case fodd:
		skip(lparen);
		expression(&x);
		mustbe(intip, x);
		gen0(rem2);
		skip(rparen);
		break;
	case fchr:
		skip(lparen);
		expression(&x);
		mustbe(intip, x);
		skip(rparen);
		break;
	case ford:
		skip(lparen);
		expression(&x);
		mustbe(chartip, x);
		skip(rparen);
		break;
	case fwrite:
	case fwriteln:
		if(n == fwrite)
			check(lparen);
		if(sym == lparen)
		{
			do{
				getsym();
				if(sym == sstring)
				{
					for(x = 0; x < slen; x++)
					{
						gen1(ldc, str[x]);
						gen0(wrc);
					}
					getsym();
				}
				else
				{
					expression(&x);
					if(sym == colon)
					{
						mustbe(intip, x);
						getsym();
						expression(&x);
						mustbe(intip, x);
						gen0(wri);
					}
					else if(x == intip)
					{
						gen1(ldc, 8);
						gen0(wri);
					}
					else if(x == chartip)
					{
						gen0(wrc);
					}
					else
						error(111);
				}
			}while(sym == comma);
			skip(rparen);
		}
		if(n == fwriteln)
			gen0(wrl);
		break;
	case fread:
	case freadln:
		if(n == fread)
			check(lparen);
		if(sym == lparen)
		{
			do{
				getsym();
				varpar(&x);
				if(x == intip)
					gen0(rdi);
				else if(x == chartip)
					gen0(rdc);
				else
					error(112);
			}while(sym == comma);
			skip(rparen);
		}
		if(n == freadln)
			gen0(rdl);
		break;
	case feoln:
		gen0(eol);
		break;
	}
}
/*函数,过程调用*/
void funcall(int i)
{
	int d, p, x;
	getsym();
	if(itab[i].flevel < 0)
		standfct(itab[i].fadr);
	else
	{
		if(itab[i].tip != 0)
			gen1(ldc, 0);
		p = i;
		d = dx;
		if(sym == lparen)
		{
			do{
				getsym();
				if(p == itab[i].lastpar)
					error(113);
				else
				{
					p = p + 1;
					if(itab[p].refpar == TRUE)
						varpar(&x);
					else
					{
						expression(&x);
						if(ttab[x].kind != simple)
							gen1(copy, ttab[x].size);
					}
				}
				mustbe(itab[p].tip, x);
			}while(sym == comma);
			skip(rparen);
		}
		if(p != itab[i].lastpar)
			error(114);
		if(itab[i].flevel != 0)
			address(itab[i].flevel, 0);
		gen1(call, itab[i].fadr);
		dx = d;
	}
}
/*因子*/
void factor(int * t)
{
	int i;
	if(sym == ident)
	{
		i = position();
		*t = itab[i].tip;
		switch(itab[i].kind)
		{
		case konst:
			getsym();
			gen1(ldc, itab[i].val);
			break;
		case varbl:
			selector(t, &i);
			if(i != 0)
				addressvar(i);
			if(ttab[i].kind == simple)
				gen0(load);
			break;
		case funkt:
			if(*t == 0)
				error(115);
			else
				funcall(i);
			break;
		case tipe:
			error(116); /*类型名不能作为因子*/
			break;
		}
	}
	else if(sym == number)
	{
		gen1(ldc, num);
		*t = intip;
		getsym();
	}
	else if(sym == sstring && slen == 2)
	{
		gen1(ldc, str[0]);
		*t = chartip;
		getsym();
	}
	else if(sym == lparen)
	{
		getsym();
		expression(t);
		skip(rparen);
	}
	else if(sym == notsym)
	{
		getsym();
		factor(t);
		mustbe(booltip, *t);
		gen0(neg);
		gen1(addc, 1);
	}
	else
		error(117);
}
/*表达式的项*/
void term(int * x)
{
	int y;
	factor(x);
	while(sym == andsym || sym == star || sym == divsym || sym == modsym)
	{
		if(sym == andsym)
			mustbe(booltip, *x);
		else
			mustbe(intip, *x);
		switch(sym)
		{
		case star:
			getsym();
			factor(&y);
			gen0(mul);
			break;
		case divsym:
			getsym();
			factor(&y);
			gen0(divd);
			break;
		case modsym:
			getsym();
			factor(&y);
			gen0(remd);
			break;
		case andsym:
			getsym();
			factor(&y);
			gen0(andb);
			break;
		}
		mustbe(*x, y);
	}
}
/*简单表达式*/
void simpleexpression(int * x)
{
	int y;
	if(sym == plus)
	{
		getsym();
		term(x);
		mustbe(intip, *x);
	}
	else if(sym == minus)
	{
		getsym();
		term(x);
		mustbe(intip, *x);
		gen0(neg);
	}
	else
		term(x);
	while(sym == orsym || sym == plus || sym == minus)
	{
		if(sym == orsym)
			mustbe(booltip, *x);
		else
			mustbe(intip, *x);
		switch(sym)
		{
		case plus:
			getsym();
			term(&y);
			gen0(add);
			break;
		case minus:
			getsym();
			term(&y);
			gen0(neg);
			gen0(add);
			break;
		case orsym:
			getsym();
			term(&y);
			gen0(orb);
			break;
		}
		mustbe(*x, y);
	}
}
/*表达式*/
void expression(int * x)
{
	symbol op;
	int y;
	simpleexpression(x);
	if(sym == eql ||sym == neq || sym == lss || sym == leq || sym == gtr ||sym == geq)
	{
		if(ttab[*x].kind != simple)
			error(118);
		else
		{
			op = sym;
			getsym();
			simpleexpression(&y);
			mustbe(*x, y);
			switch(op)
			{
			case eql:
				gen0(eqli);
				break;
			case neq:
				gen0(neqi);
				break;
			case lss:
				gen0(lssi);
				break;
			case leq:
				gen0(leqi);
				break;
			case gtr:
				gen0(gtri);
				break;
			case geq:
				gen0(geqi);
				break;
			}
			*x = booltip;
		}
	}
}
/*语句*/
void statement()
{
	int i, j, t, x;
	if(sym == ident)
	{
		i = position();
		switch(itab[i].kind)
		{
		case varbl:
			selector(&t, &i);
			skip(becomes);
			expression(&x);
			mustbe(t, x);
			if(i == 0)
				gen0(swap);
			else
				addressvar(i);
			if(ttab[i].kind == simple)
				gen0(stor);
			else
				gen1(move, ttab[i].size);
			break;
		case funkt:
			if(itab[i].tip == 0)
				funcall(i);
			else
			{
				if(itab[i].inside == FALSE)
					error(119);/*此处不能对函数赋值*/
				else
				{
					getsym();
					skip(becomes);
					expression(&x);
					mustbe(itab[i].tip, x);
					address(itab[i].flevel + 1, itab[i].resultadr);
					gen0(stor);
				}
			}
			break;
		case konst:
		case field:
		case tipe:
			error(120); /*变量不能用在此处*/
			break;
		}
	}
	else if(sym == ifsym)
	{
		getsym();
		expression(&t);
		mustbe(booltip, t);
		skip(thensym);
		i = codelabel();
		gen1(jumpz, 0);
		statement();
		if(sym == elsesym)
		{
			getsym();
			j = codelabel();
			gen1(jump, 0);
			code[i].a = codelabel();
			i = j;
			statement();
		}
		code[i].a = codelabel();
	}
	else if(sym == whilesym)
	{
		getsym();
		i = codelabel();
		expression(&t);
		mustbe(booltip, t);
		skip(dosym);
		j = codelabel();
		gen1(jumpz, 0);
		statement();
		gen1(jump, i);
		/*这里表写错了*/
		code[j].a = codelabel();
	}
	else if(sym == repeatsym)
	{
		i = codelabel();
		do{
			getsym();
			statement();
		}while(sym == semicolon);
		skip(untilsym);
		expression(&t);
		mustbe(booltip, t);
		gen1(jumpz, i);
	}
	else if(sym == beginsym)
	{
		do{
			getsym();
			statement();
		}while(sym == semicolon);
		skip(endsym);
	}
}
void block(int l);
/*常量*/
void constant(int * c, int * t)
{
	int i, s;
	if(sym == sstring && slen == 2)
	{
		*c = str[0];
		*t = chartip;
	}
	else
	{
		if(sym == plus)
		{
			getsym();
			s = +1;
		}
		else if(sym == minus)
		{
			getsym();
			s = -1;
		}
		else
			s = 0;
		if(sym == ident)
		{
			i = position();
			if(itab[i].kind != konst)
				error(121);
			else
			{
				*c = itab[i].val;
				*t = itab[i].tip;
			}
		}
		else if(sym == number)
		{
			*c = num;
			*t = intip;
		}
		else
			error(122);
		if(s != 0)
		{
			mustbe(*t, intip);
			(*c) = (*c) * (s);
		}
	}
	getsym();
}
/*常量声明*/
void constdeclaration()
{
	alfa a;
	int t, c;
	strcpy(a, id);
	getsym();
	skip(eql);
	constant(&c, &t);
	skip(semicolon);
	enter(a, konst, t);
	itab[ix].val = c;
}
void typ(int * t);
/*数组类型*/
void arraytyp(int * t)
{
	int x;
	ttab[*t].kind = arrays;
	getsym();
	constant(&(ttab[*t].low), &x);
	mustbe(intip, x);
	skip(colon);
	constant(&(ttab[*t].high), &x);
	mustbe(intip, x);
	if(ttab[*t].low > ttab[*t].high)
		error(123); /*数组边界问题*/
	if(sym == comma)
		arraytyp(&(ttab[*t].elemtip));
	else
	{
		skip(rbrack);
		skip(ofsym);
		typ(&(ttab[*t].elemtip));
	}
	ttab[*t].size = (ttab[*t].high - ttab[*t].low + 1) * ttab[ttab[*t].elemtip].size;
}
/*类型定义*/
void typ(int * t)
{
	int i, j, sz, ft;
	if(sym == ident)
	{
		i = position();
		if(itab[i].kind != tipe)
			error(124); /*这个标识符不是类型能够*/
		else
		{
			*t = itab[i].tip;
			getsym();
		}
	}
	else
	{
		if(tx == tmax)
		{
			error(125); /*溢出,应退出*/
		}
		else
		{
			tx = tx + 1;
			*t = tx;
		}
		if(sym == arraysym)
		{
			getsym();
			check(lbrack);
			arraytyp(t);
		}
		else
		{
			skip(recordsym);
			if(lev == lmax)
			{
				error(126); /*深度超过限度,应退出*/
			}
			else
			{
				lev = lev + 1;
				if(lev == -1)
					nl = 0;
				else
					namelist[lev] = 0;
				check(ident);
				sz = 0;
				do{
					enter(id, field, 0);
					i = ix;
					getsym();
					while(sym == comma)
					{
						getsym();
						check(ident);
						enter(id, field, 0);
						getsym();
					}
					j = ix;
					skip(colon);
					typ(&ft);
					do{
						itab[i].tip = ft;
						itab[i].offset = sz;
						sz = sz + ttab[ft].size;
						i = i + 1;
					}while(i <= j);
					if(sym == semicolon)
						getsym();
					else
						check(endsym);
				}while(sym == ident);
				ttab[*t].size = sz;
				ttab[*t].kind = records;
				if(lev == -1)
					ttab[*t].fields = nl;
				else
					ttab[*t].fields = namelist[lev];
				lev = lev - 1;
				skip(endsym);
			}
		}
	}
}
/*类型声明,type保留字处*/
void typedeclaration()
{
	alfa a;
	int t;
	strcpy(a, id);
	getsym();
	skip(eql);
	typ(&t);
	skip(semicolon);
	enter(a, tipe, t);
}
/*变量声明*/
void vardeclaration()
{
	int p, q, t;
	enter(id, varbl, 0);
	p = ix;
	getsym();
	while(sym == comma)
	{
		getsym();
		check(ident);
		enter(id, varbl, 0);
		getsym();
	}
	q = ix;
	skip(colon);
	typ(&t);
	skip(semicolon);
	do{
		itab[p].vlevel = lev;
		dx = dx - ttab[t].size;
		itab[p].tip = t;
		itab[p].vadr = dx;
		itab[p].refpar = FALSE;
		p = p + 1;
	}while(p <= q); 
}
/*参数列表*/
void paramlist(int *p, int * ps)
{
	BOOL r;
	int t;
	if(sym == varsym)
	{
		r = TRUE;
		getsym();
	}
	else
		r = FALSE;
	check(ident);
	*p = ix;
	enter(id, varbl, 0);
	getsym();
	while(sym == comma)
	{
		getsym();
		check(ident);
		enter(id, varbl, 0);
		getsym();
	}
	skip(colon);
	check(ident);
	typ(&t);
	while(*p < ix)
	{
		*p = *p + 1;
		itab[*p].tip = t;
		itab[*p].refpar = r;
		if(r)
			*ps = *ps + 1; /*传地址*/
		else
			*ps = *ps + ttab[t].size; /*传值*/
	}
}
void funcdeclaration(BOOL isf)
{
	int f, p, ps, odx;
	getsym();
	check(ident);
	enter(id, funkt, 0);
	getsym();
	f = ix;
	itab[f].flevel = lev;
	itab[f].fadr = codelabel();
	gen1(jump, 0);
	if(lev == lmax)
	{
		error(127); /*深度超过限度,应退出*/
	}
	lev = lev + 1;
	if(lev == -1)
		nl = 0;
	else
		namelist[lev] = 0;
	ps = 1;
	odx = dx;
	if(sym == lparen)
	{
		do{
			getsym();
			paramlist(&p, &ps);
		}while(sym == semicolon);
		skip(rparen);
	}
	if(lev > 1)
		dx = -1;
	else
		dx = 0;
	itab[f].resultadr = ps;
	p = f;
	while(p < ix)
	{
		p = p + 1;
		if(itab[p].refpar)
			ps = ps - 1;
		else
			ps = ps - ttab[itab[p].tip].size;
		itab[p].vlevel = lev;
		itab[p].vadr = ps;
	}
	if(isf == TRUE)
	{
		skip(colon);
		check(ident);
		typ(&(itab[f].tip));
		if(ttab[itab[f].tip].kind != simple)
			error(128); /*只能返回简单类型*/
	}
	skip(semicolon);
	itab[f].lastpar = ix;
	itab[f].inside = TRUE;
	block(itab[f].fadr);
	itab[f].inside = FALSE;
	gen1(pexit, itab[f].resultadr - dx);
	lev = lev - 1;
	dx = odx;
	skip(semicolon);
}
void block(int l)
{
	int d, odx, oix;
	odx = dx;
	oix = ix;
	if(sym == constsym)
	{
		getsym();
		check(ident);
		do{
			constdeclaration();
		}while(sym == ident);
	}
	if(sym == typesym)
	{
		getsym();
		check(ident);
		do{
			typedeclaration();
		}while(sym == ident);
	}
	if(sym == varsym)
	{
		getsym();
		check(ident);
		do{
			vardeclaration();
		}while(sym == ident);
	}
	while(sym == funcsym || sym == procsym)
	{
		if(sym == funcsym)
			funcdeclaration(TRUE);
		else
			funcdeclaration(FALSE);
	}
	if(l + 1 == codelabel())
		cx = cx -1;
	else
		code[l].a = codelabel();
	if(lev == 0)
		gen1(sets, dx);
	else
	{
		d = dx - odx;
		dx = odx;
		gen1(adjs, d);
	}
	statement();
	if(lev != 0)
		gen1(adjs, odx - dx);
	ix = oix;
}
void listcode(FILE * fi)
{
	int i;
	for(i = 0; i < cx; i++)
	{
		fprintf(fi, "%-4d :   ", i);
		switch(code[i].op)
		{
		case add:
			fprintf(fi, "add/n");
			break;
		case neg:
			fprintf(fi, "neg/n");
			break;
		case mul:
			fprintf(fi, "mul/n");
			break;
		case divd:
			fprintf(fi, "divd/n");
			break;
		case remd:
			fprintf(fi, "remd/n");
			break;
		case div2:
			fprintf(fi, "div2/n");
			break;
		case rem2:
			fprintf(fi, "rem2/n");
			break;
		case eqli:
			fprintf(fi, "eqli/n");
			break;
		case neqi:
			fprintf(fi, "neqi/n");
			break;
		case lssi:
			fprintf(fi, "lssi/n");
			break;
		case leqi:
			fprintf(fi, "leqi/n");
			break;
		case gtri:
			fprintf(fi, "gtri/n");
			break;
		case geqi:
			fprintf(fi, "geqi/n");
			break;
		case dupl:
			fprintf(fi, "dupl/n");
			break;
		case swap:
			fprintf(fi, "swap/n");
			break;
		case andb:
			fprintf(fi, "andb/n");
			break;
		case orb:
			fprintf(fi, "orb/n");
			break;
		case load:
			fprintf(fi, "load/n");
			break;
		case stor:
			fprintf(fi, "stor/n");
			break;
		case hhalt:
			fprintf(fi, "hhalt/n");
			break;
		case wri:
			fprintf(fi, "wri/n");
			break;
		case wrc:
			fprintf(fi, "wrc/n");
			break;
		case wrl:
			fprintf(fi, "wrl/n");
			break;
		case rdi:
			fprintf(fi, "rdi/n");
			break;
		case rdc:
			fprintf(fi, "rdc/n");
			break;
		case rdl:
			fprintf(fi, "rdl/n");
			break;
		case eol:
			fprintf(fi, "eol/n");
			break;
		case ldc:
			fprintf(fi, "ldc   %d/n", code[i].a);
			break;
		case ldla:
			fprintf(fi, "ldla  %d/n", code[i].a);
			break;
		case ldl:
			fprintf(fi,"ldl   %d/n", code[i].a);
			break;
		case ldg:
			fprintf(fi, "ldg   %d/n", code[i].a);
			break;
		case stl:
			fprintf(fi, "stl   %d/n", code[i].a);
			break;
		case stg:
			fprintf(fi, "stg   %d/n", code[i].a);
			break;
		case move:
			fprintf(fi, "move  %d/n", code[i].a);
			break;
		case copy:
			fprintf(fi, "copy  %d/n", code[i].a);
			break;
		case addc:
			fprintf(fi, "addc  %d/n", code[i].a);
			break;
		case mulc:
			fprintf(fi, "mulc  %d/n", code[i].a);
			break;
		case jump:
			fprintf(fi, "jump  %d/n", code[i].a);
			break;
		case jumpz:
			fprintf(fi, "jumpz %d/n", code[i].a);
			break;
		case call:
			fprintf(fi, "call  %d/n", code[i].a);
			break;
		case adjs:
			fprintf(fi, "adjs  %d/n", code[i].a);
			break;
		case sets:
			fprintf(fi, "sets  %d/n", code[i].a);
			break;
		case pexit:
			fprintf(fi, "exit  %d/n", code[i].a);
			break;
		}
	}
}
void compile()
{
	ttab[intip].size = 1;
	ttab[intip].kind = simple;
	ttab[chartip].size = 1;
	ttab[chartip].kind = simple;
	ttab[booltip].size = 1;
	ttab[booltip].kind = simple;
	tx = 3;
	nl = 0; /* namelist[-1] = 0; */
	lev = -1;
	ix = 0;
	enter("false", konst, booltip);
	itab[ix].val = FALSE;
	enter("true", konst, booltip);
	itab[ix].val = TRUE;
	enter("maxint", konst, intip);
	itab[ix].val = 32767;
	enter("integer", tipe, intip);
	enter("char", tipe, chartip);
	enter("boolean", tipe, booltip);
	enter("abs", funkt, intip);
	itab[ix].flevel = -1;
	itab[ix].fadr = fabs;
	itab[ix].inside = FALSE;
	enter("sqr", funkt, intip);
	itab[ix].flevel = -1;
	itab[ix].fadr = fsqr;
	itab[ix].inside = FALSE;
	enter("odd", funkt, booltip);
	itab[ix].flevel = -1;
	itab[ix].fadr = fodd;
	itab[ix].inside = FALSE;
	enter("chr", funkt, chartip);
	itab[ix].flevel = -1;
	itab[ix].fadr = fchr;
	itab[ix].inside = FALSE;
	enter("ord", funkt, intip);
	itab[ix].flevel = -1;
	itab[ix].fadr = ford;
	itab[ix].inside = FALSE;
	enter("write", funkt, 0);
	itab[ix].flevel = -1;
	itab[ix].fadr = fwrite;
	enter("writeln", funkt, 0);
	itab[ix].flevel = -1;
	itab[ix].fadr = fwriteln;
	enter("read", funkt, 0);
	itab[ix].flevel = -1;
	itab[ix].fadr = fread;
	enter("readln", funkt, 0);
	itab[ix].flevel = -1;
	itab[ix].fadr = freadln;
	enter("eoln", funkt, booltip);
	itab[ix].flevel = -1;
	itab[ix].fadr = feoln;
	itab[ix].inside = FALSE;
	namelist[0] = 0;
	lev = 0;
	cc = 0;
	ll = 0;
	getch();
	getsym();
	labeled = FALSE;
	cx = 0;
	dx = amax + 1;
	skip(progsym);
	skip(ident);
	check(lparen);
	do{
		getsym();
		check(ident);
		if(strcmp(id, "input") != 0 && strcmp(id, "output") != 0)
			error(129);
		getsym();
	}while(sym == comma);
	skip(rparen);
	skip(semicolon);
	gen1(jump, 0);
	block(0);
	gen0(hhalt);
	check(period);
}
/*解释执行*/
void interpret()
{
	int pc, sp, j, k, n;
	instr i;
	char c;
	BOOL h;
	pc = 0;
	h = FALSE;
	do{
		i = code[pc];
		pc = pc + 1;
		switch(i.op)
		{
		case add:
			m[sp + 1] = m[sp + 1] + m[sp];
			sp = sp + 1;
			break;
		case neg:
			m[sp] = -m[sp];
			break;
		case mul:
			m[sp + 1] = m[sp + 1] * m[sp];
			sp = sp + 1;
			break;
		case divd:
			m[sp + 1] = m[sp + 1] / m[sp];
			sp = sp + 1;
			break;
		case remd:
			m[sp + 1] = m[sp + 1] % m[sp];
			sp = sp + 1;
			break;
		case div2:
			m[sp] = m[sp] / 2;
			break;
		case rem2:
			m[sp] = m[sp] % 2;
			break;
		case eqli:
			m[sp + 1] = (m[sp + 1] == m[sp]);
			sp = sp + 1;
			break;
		case neqi:
			m[sp + 1] = (m[sp + 1] != m[sp]);
			sp = sp + 1;
			break;
		case lssi:
			m[sp + 1] = (m[sp + 1] < m[sp]);
			sp = sp + 1;
			break;
		case leqi:
			m[sp + 1] = (m[sp + 1] <= m[sp]);
			sp = sp + 1;
			break;
		case gtri:
			m[sp + 1] = (m[sp + 1] > m[sp]);
			sp = sp + 1;
			break;
		case geqi:
			m[sp + 1] = (m[sp + 1] >= m[sp]);
			sp = sp + 1;
			break;
		case dupl:
			sp = sp - 1;
			m[sp] = m[sp + 1];
			break;
		case swap:
			k = m[sp];
			m[sp] = m[sp + 1];
			m[sp + 1] = k;
			break;
		case andb:
			if(m[sp] == 0)
				m[sp + 1] = 0;
			sp = sp + 1;
			break;
		case orb:
			if(m[sp] == 1)
				m[sp + 1] = 1;
			sp = sp + 1;
			break;
		case load:
			m[sp] = m[m[sp]];
			break;
		case stor:
			m[m[sp]] = m[sp + 1];
			sp = sp + 2;
			break;
		case hhalt:
			h = TRUE;
			break;
		case wri:
			/*待定*/
			fprintf(stdout, "%d", m[sp + 1]);
			sp = sp + 2;
			break;
		case wrc:
			fprintf(stdout, "%c", m[sp]);
			sp = sp + 1;
			break;
		case wrl:
			fprintf(stdout, "/n");
			break;
		case rdi:
			fprintf(stdout, "input integer: ");
			fscanf(stdin, "%d", &(m[m[sp]]));
			sp = sp + 1;
			break;
		case rdc:
			fprintf(stdout, "input character: ");
			fscanf(stdin, "%c", &c);
			m[m[sp]] = c;
			sp = sp + 1;
			break;
		case rdl:
			/*待定*/
			break;
		case eol:
			sp = sp - 1;
			m[sp] = feof(stdin);
			break;
		case ldc:
			sp = sp - 1;
			m[sp] = i.a;
			break;
		case ldla:
			sp = sp - 1;
			m[sp] = sp + 1 + i.a;
			break;
		case ldl:
			sp = sp - 1;
			m[sp] = m[sp + 1 + i.a];
			break;
		case ldg:
			sp = sp - 1;
			m[sp] = m[i.a];
			break;
		case stl:
			m[sp + i.a] = m[sp];
			sp = sp + 1;
			break;
		case stg:
			m[i.a] = m[sp];
			sp = sp + 1;
			break;
		case move:
			k = m[sp];
			j = m[sp + 1];
			sp = sp + 2;
			n = i.a;
			do{
				n = n - 1;
				m[k + n] = m[j + n];
			}while(n > 0);
			break;
		case copy:
			j = m[sp];
			n = i.a;
			sp = sp - n + 1;
			do{
				n = n - 1;
				m[sp + n] = m[j + n];
			}while(n > 0);
			break;
		case addc:
			m[sp] = m[sp] + i.a;
			break;
		case mulc:
			m[sp] = m[sp] * i.a;
			break;
		case jump:
			pc = i.a;
			break;
		case jumpz:
			if(m[sp] == 0)
				pc = i.a;
			sp = sp + 1;
			break;
		case call:
			sp = sp - 1;
			m[sp] = pc;
			pc = i.a;
			break;
		case adjs:
			sp = sp + i.a;
			break;
		case sets:
			sp = i.a;
			break;
		case pexit:
			pc = m[sp];
			sp = sp + i.a;
			break;
		}
	}while(h == FALSE);
}
void main(int argc, char **argv)
{
	char filename[81], save;
	FILE * sf;
	memset(filename, 0, 81);
	if(argc == 1)
	{
		fprintf(stdout, "please enter source file name: ");
		fscanf(stdin, "%s", filename);
	}
	else
		strcpy(filename, argv[1]);
	source = fopen(filename, "r");
	if(source == NULL)
	{
		fprintf(stderr, "cann't open file: %s/n", filename);
		return;
	}
	fprintf(stdout, "compiling.../n");
	compile();
	fclose(source);
	fprintf(stdout, "no errors, compile succeed./n");
	fprintf(stdout, "--------------------------------/n");
	listcode(stdout);
	fprintf(stdout, "--------------------------------/n");
	fprintf(stdout, "Run>/n");
	interpret();
	fprintf(stdout, "program exit./n");
	fprintf(stdout, "do you want to save the code(y or n): ");
	do{
		scanf("%c", &save);
	}while(save != 'y' && save != 'Y' && save != 'n' && save != 'N');
	if(save == 'y' || save == 'Y')
	{
		fprintf(stdout, "enter file name: ");
		scanf("%s", filename);
		sf = fopen(filename, "w");
		if(sf)
		{
			listcode(sf);
			fclose(sf);
		}
		else
			fprintf(stdout, "open file error, code not saved./n");
	}
}
此条目发表在代码片段, 编译原理分类目录。将固定链接加入收藏夹。