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

📄 sxb2.c

📁 c语言编的PL/0的词法分析器
💻 C
📖 第 1 页 / 共 2 页
字号:
// pl0 compiler source code#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include "set.h"#include "sxb2.h"//////////////////////////////////////////////////////////////////////// print error message.void error(n){	int i;	printf("      ");	for (i = 1; i <= cc - 1; i++)
		printf(" ");		fprintf(outfile, " ");	fprintf(outfile, "^\n");	printf("^\n");	fprintf(outfile, "Error %3d: %s\n", n, err_msg[n]);	printf("Error %3d: %s\n", n, err_msg[n]);	err++;} // error//////////////////////////////////////////////////////////////////////void getch(void){	if (cc == ll)	{		if (feof(infile))		{			printf("\nPROGRAM INCOMPLETE\n");			exit(1);		}		ll = cc = 0;		fprintf(outfile, "%5d  ", cx);		printf("%5d  ", cx);		while ( (!feof(infile)) // added & modified by alex 01-02-09			    && ((ch = getc(infile)) != '\n'))		{			fprintf(outfile, "%c", ch);			printf("%c", ch);			line[++ll] = ch;		} // while		fprintf(outfile, "\n");		printf("\n");		line[++ll] = ' ';	}	ch = line[++cc];} // getch//////////////////////////////////////////////////////////////////////// gets a symbol from input stream.void getsym(void){	int i, k;	char a[MAXIDLEN + 1];	while (ch == ' '|| ch == '\t')		// modified by yzhang 02-03-12,add some white space		getch();	if (isalpha(ch))	{ // symbol is a reserved word or an identifier.		k = 0;		do		{			if (k < MAXIDLEN)				a[k++] = ch;			getch();		}		while (isalpha(ch) || isdigit(ch));		a[k] = 0;		strcpy(id, a);		word[0] = id;		i = NRW;		while (strcmp(id, word[i--]));		if (++i)			sym = wsym[i]; // symbol is a reserved word		else			sym = SYM_IDENTIFIER;   // symbol is an identifier	}	else if (isdigit(ch))	{ // symbol is a number.		k = num = 0;		sym = SYM_NUMBER;		do		{			num = num * 10 + ch - '0';			k++;			getch();		}		while (isdigit(ch));		if (k > MAXNUMLEN)			error(25);     // The number is too great.	}	else if (ch == ':')	{		getch();		if (ch == '=')		{			sym = SYM_BECOMES; // :=			getch();		}		else		{			sym = SYM_NULL;       // illegal?		}	}	else if (ch == '>')	{		getch();		if (ch == '=')		{			sym = SYM_GEQ;     // >=			getch();		}		else		{			sym = SYM_GTR;     // >		}	}	else if (ch == '<')	{		getch();		if (ch == '=')		{			sym = SYM_LEQ;     // <=			getch();		}		else if (ch == '>')		{			sym = SYM_NEQ;     // <>			getch();		}		else		{			sym = SYM_LES;     // <		}	}	else	{ // other tokens		i = NSYM;		csym[0] = ch;		while (csym[i--] != ch);		if (++i)		{			sym = ssym[i];			getch();		}		else		{			printf("Fatal Error: Unknown character.\n");			fprintf(outfile, "Fatal Error: Unknown character.\n");			exit(1);		}	}} // getsym//////////////////////////////////////////////////////////////////////// generates (assembles) an instruction.void gen(int x, int y, int z){	if (cx > CXMAX)	{		fprintf(outfile, "Fatal Error: Program too long.\n");		printf("Fatal Error: Program too long.\n");		exit(1);	}	code[cx].f = x;	code[cx].l = y;	code[cx++].a = z;} // gen//////////////////////////////////////////////////////////////////////// tests if error occurs and skips all symbols that do not belongs to s1 or s2.void test(symset s1, symset s2, int n){	symset s;	if (! inset(sym, s1))	{		showset(s1);		showset(s2);		printf("sym=%d, id=%s\n", sym, id);		error(n);		s = uniteset(s1, s2);		while(! inset(sym, s))			getsym();		destroyset(s);	}} // test//////////////////////////////////////////////////////////////////////int dx;  // data allocation index// enter object(constant, variable or procedre) into table.void enter(int kind){	mask* mk;// added by yzhang 02-02-28//	if ( position(id)> 0 ){//		error(26); //Redeclared identifier.//	}// end 	tx++;	strcpy(table[tx].name, id);	table[tx].kind = kind;	switch (kind)	{	case ID_CONSTANT:		if (num > MAXADDRESS)		{			error(25); // The number is too great.			num = 0;		}		table[tx].value = num;		break;	case ID_VARIABLE:		mk = (mask*) &table[tx];		mk->level = level;		mk->address = dx++;		break;	case ID_PROCEDURE:		mk = (mask*) &table[tx];		mk->level = level;		break;	} // switch} // enter//////////////////////////////////////////////////////////////////////// locates identifier in symbol table.int position(char* id){	int i;	strcpy(table[0].name, id);	i = tx + 1;	while (strcmp(table[--i].name, id) != 0);	return i;} // position//////////////////////////////////////////////////////////////////////void constdeclaration(){	if (sym == SYM_IDENTIFIER)	{		getsym();		if (sym == SYM_EQU || sym == SYM_BECOMES)		{			if (sym == SYM_BECOMES)				error(1); // Found ':=' when expecting '='.			getsym();			if (sym == SYM_NUMBER)			{				enter(ID_CONSTANT);				getsym();			}			else			{				error(2); // There must be a number to follow '='.			}		}		else		{			error(3); // There must be an '=' to follow the identifier.		}	}	else		//added by yzhang 02-02-28		error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.} // constdeclaration//////////////////////////////////////////////////////////////////////void vardeclaration(void){	if (sym == SYM_IDENTIFIER)	{		enter(ID_VARIABLE);		getsym();	}	else	{		error(4); // There must be an identifier to follow 'const', 'var', or 'procedure'.	}} // vardeclaration//////////////////////////////////////////////////////////////////////void listcode(int from, int to){	int i;		printf("\n");	fprintf(outfile, "\n");	for (i = from; i < to; i++)	{		printf("%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);		fprintf(outfile, "%5d %s\t%d\t%d\n", i, mnemonic[code[i].f], code[i].l, code[i].a);	}	printf("\n");	fprintf(outfile, "\n");} // listcode//////////////////////////////////////////////////////////////////////void factor(symset fsys){	void expression();	int i;	symset set;		test(facbegsys, fsys, 24); // The symbol can not be as the beginning of an expression.
	while (inset(sym, facbegsys))	{		if (sym == SYM_IDENTIFIER)		{			if ((i = position(id)) == 0)			{				error(11); // Undeclared identifier.			}			else			{				switch (table[i].kind)				{					mask* mk;				case ID_CONSTANT:					gen(LIT, 0, table[i].value);					break;				case ID_VARIABLE:					mk = (mask*) &table[i];					gen(LOD, level - mk->level, mk->address);					break;				case ID_PROCEDURE:					error(21); // Procedure identifier can not be in an expression.					break;				} // switch			}			getsym();		}		else if (sym == SYM_NUMBER)		{			if (num > MAXADDRESS)			{				error(25); // The number is too great.				num = 0;			}			gen(LIT, 0, num);			getsym();		}		else if (sym == SYM_LPAREN)		{			getsym();			set = uniteset(createset(SYM_RPAREN, SYM_NULL), fsys);			expression(set);			destroyset(set);			if (sym == SYM_RPAREN)			{				getsym();			}			else			{				error(22); // Missing ')'.			}		}		else	// added by yzhang 02-02-28			test(fsys, createset(SYM_LPAREN, SYM_NULL), 23);	} // while} // factor//////////////////////////////////////////////////////////////////////void term(symset fsys){	int mulop;	symset set;		set = uniteset(fsys, createset(SYM_TIMES, SYM_SLASH, SYM_NULL));	factor(set);	while (sym == SYM_TIMES || sym == SYM_SLASH)	{		mulop = sym;		getsym();		factor(set);		if (mulop == SYM_TIMES)		{			gen(OPR, 0, OPR_MUL);		}		else		{			gen(OPR, 0, OPR_DIV);		}	} // while	destroyset(set);} // term//////////////////////////////////////////////////////////////////////void expression(symset fsys){	int addop;	symset set;	set = uniteset(fsys, createset(SYM_PLUS, SYM_MINUS, SYM_NULL));	if (sym == SYM_PLUS || sym == SYM_MINUS)	{		addop = sym;		getsym();		term(set);		if (addop == SYM_MINUS)		{			gen(OPR, 0, OPR_NEG);		}	}	else	{		term(set);	}	while (sym == SYM_PLUS || sym == SYM_MINUS)	{		addop = sym;		getsym();		term(set);		if (addop == SYM_PLUS)		{			gen(OPR, 0, OPR_ADD);		}		else		{			gen(OPR, 0, OPR_MIN);		}	} // while	destroyset(set);} // expression//////////////////////////////////////////////////////////////////////void condition(symset fsys){	int relop;	symset set;	if (sym == SYM_ODD)	{		getsym();		expression(fsys);		gen(OPR, 0, 6);	}	else	{		set = uniteset(relset, fsys);		expression(set);		destroyset(set);		if (! inset(sym, relset))		{			error(20);		}		else		{			relop = sym;			getsym();			expression(fsys);			switch (relop)			{			case SYM_EQU:				gen(OPR, 0, OPR_EQU);				break;			case SYM_NEQ:				gen(OPR, 0, OPR_NEQ);				break;			case SYM_LES:				gen(OPR, 0, OPR_LES);				break;			case SYM_GEQ:				gen(OPR, 0, OPR_GEQ);				break;			case SYM_GTR:				gen(OPR, 0, OPR_GTR);				break;			case SYM_LEQ:				gen(OPR, 0, OPR_LEQ);				break;			} // switch		} // else	} // else} // condition//////////////////////////////////////////////////////////////////////void statement(symset fsys){	int i, cx1, cx2;	symset set1, set;	if (sym == SYM_IDENTIFIER)	{ // variable assignment		mask* mk;		if (! (i = position(id)))		{			error(11); // Undeclared identifier.		}		else if (table[i].kind != ID_VARIABLE)		{			error(12); // Illegal assignment.			i = 0;		}		getsym();		if (sym == SYM_BECOMES)		{			getsym();		}		else		{			error(13); // ':=' expected.		}		expression(fsys);		mk = (mask*) &table[i];		if (i)		{			gen(STO, level - mk->level, mk->address);		}	}	else if (sym == SYM_CALL)	{ // procedure call		getsym();		if (sym != SYM_IDENTIFIER)		{			error(14); // There must be an identifier to follow the 'call'.		}		else		{			if (! (i = position(id)))			{				error(11); // Undeclared identifier.			}			else if (table[i].kind == ID_PROCEDURE)			{				mask* mk;				mk = (mask*) &table[i];				gen(CAL, level - mk->level, mk->address);			}			else			{				error(15); // A constant or variable can not be called. 			}			getsym();		} // else	} 	else if (sym == SYM_IF)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -