编译原理——PL/0语言建立一个词法分程序GETSYM

整个PL/0编译器文件已上传:https://download.csdn.net/download/qq_41102235/12038487

PL/0 词法分析、语法分析、语义分析与中间代码生成、解释执行 最终结果输出目标代码、符号表、解释执行结果

 

Pl/0语言文法的BNF表示:

〈程序〉→〈分程序〉。

〈分程序〉→ [<常量说明部分>][<变量说明部分>][<过程说明部分>]〈语句〉

 <常量说明部分> → CONST<常量定义>{ ,<常量定义>};

 <常量定义> → <标识符>=<无符号整数>

 <无符号整数> → <数字>{<数字>}

 <变量说明部分> → VAR<标识符>{ ,<标识符>};

 <标识符> → <字母>{<字母>|<数字>}

 <过程说明部分> → <过程首部><分程度>;{<过程说明部分>}

 <过程首部> → procedure<标识符>;

 <语句> → <赋值语句>|<条件语句>|<当型循环语句>|<过程调用语句>|<读语句>|<写语句>|<复合语句>|<空>

 <赋值语句> → <标识符>:=<表达式>

 <复合语句> → begin<语句>{ <语句>}<end>

 <条件> → <表达式><关系运算符><表达式>|odd<表达式>

 <表达式> → [+|-]<项>{<加减运算符><项>}

 <项> → <因子>{<乘除运算符><因子>}

 <因子> → <标识符>|<无符号整数>|(<表达式>)

 <加减运符> → +|-

 <乘除运算符> → *|/

 <关系运算符> → =|#|<|<=|>|>=

 <条件语句> → if<条件>then<语句>

 <过程调用语句> → call<标识符>

 <当型循环语句> → while<条件>do<语句>

 <读语句> → read(<标识符>{ ,<标识符>})

 <写语句> → write(<标识符>{,<标识符>})

 <字母> → a|b|cx|y|z

 <数字> → 0|1|2…7|8|9

 

  • PL/0语言建立一个词法分程序GETSYM(函数)

把关键字、算符、界符称为语言固有的单词,标识符、常量称为用户自定义的单词。为此设置三个全程量:SYM,ID,NUM 。

 SYM:存放每个单词的类别,为内部编码的表示形式。

 ID:存放用户所定义的标识符的值,即标识符字符串的机内表示。

 NUM:存放用户定义的数。

 GETSYM要完成的任务:

  1. 滤掉单词间的空格。
  2. 识别关键字,用查关键字表的方法识别。当单词是关键字时,将对应的类别放在SYM中。如IF的类别为IFSYM,THEN的类别为THENSYM。
  3. 识别标识符,标识符的类别为IDENT,IDENT放在SYM中,标识符本身的值放在ID中。关键字或标识符的最大长度是10。
  4. 拼数,将数的类别NUMBER放在SYM中,数本身的值放在NUM中。
  5. 拼由两个字符组成的运算符,如:>=、<=等等,识别后将类别存放在SYM中。
  6. 打印源程序,边读入字符边打印。

由于一个单词是由一个或多个字符组成的,所以在词法分析程序GETSYM中定义一个读字符过程GETCH。

 

因为刚做完第一个,且只验证第一个的结果,就写了一个cpp文件,可以自己修改噢。

程序是从文件里读入的,结果输出到命令行

#include <iostream>
#include <string>
#include <cstdio>
#include <fstream>
#include <cstdlib>

using namespace std;

const int num_word = 13;//关键字
const int num_opt = 13;//操作符
const int MAXLEN = 10;//*str的最大长度
static int line = 0;//判断文件读到第几行
static string stable[100];
static int stlen = 0;
static string ntable[100];
static int ntlen = 0;
enum SYM
{
	SYMUNUSE,//0不设保留字
	SYMCONST,SYMVAR,SYMPROCEDURE,SYMBEGIN,SYMEND,SYMODD,SYMIF,SYMTHEN,SYMCALL,SYMWHILE,SYMDO,SYMREAD,SYMWRITE,
	SYMIDENTIFIER,SYMNUM,
	SYMPLUS,//+
	SYMMINUS,//-
	SYMMUL,//*
	SYMDIV,// /
	SYMASSI,//assignment :=
	SYMEQ,//=
	SYMNEQ,// #
	SYMLESS,// <
	SYMLESSEQ,// <=
	SYMBIG,//>
	SYMBIGEQ,//>=
	SYMLEFT,//(
	SYMRIGHT,//)
	SYMLEFTB,//{
	SYMRIGHTB,//}
	SYMSEM,//Semicolon ;
	SYMCOM,// ,
};
int array_word[num_word] = { SYMCONST,SYMVAR,SYMPROCEDURE,SYMBEGIN,SYMEND,SYMODD,SYMIF,SYMTHEN,SYMCALL,SYMWHILE,SYMDO,SYMREAD,SYMWRITE };



bool IsLetter(char ch) {
	if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return true;

	else return false;
}
bool IsDigit(char ch) {
	if (ch >= '0' && ch <= '9')
		return true;

	else return false;
}
//void GetBC(string str, char ch) 

int Reserve(char* str) {
	if (!strcmp(str, "const") )
//	if(str=="const")
		return SYMCONST;
	if (!strcmp(str, "var"))
		return SYMVAR;
	if (!strcmp(str, "procedure"))
		return SYMPROCEDURE;
	if (!strcmp(str, "begin")) 
		return SYMBEGIN;
	if (!strcmp(str, "end"))
		return SYMEND;
//	SYMODD, SYMIF, SYMTHEN, SYMCALL, SYMWHILE, SYMDO, SYMREAD, SYMWRITE
	if (!strcmp(str, "odd"))
		return SYMODD;
	if (!strcmp(str, "if") )
		return SYMIF;
	if (!strcmp(str, "then") )
		return SYMTHEN;
	if (!strcmp(str, "call") )
		return SYMCALL;
	if (!strcmp(str, "while"))
		return SYMWHILE;
	if (!strcmp(str, "do") )
		return SYMDO;
	if (!strcmp(str, "read") ) 
		return SYMREAD;
	if (!strcmp(str, "write"))
		return SYMWRITE;
	return 0;
}
int InsertId(char* str) {
	if (IsLetter(str[0])) {
		stable[stlen] = str;
		stlen++;
		return stlen - 1;
	}
	if (IsDigit(str[0])) {
		ntable[ntlen] = str;
		ntlen++;
		return ntlen - 1;
	}
	
}

int GETSYM(FILE *filename) {
//	string strToken = "";
	int code=0, value=0;
	int pos = 0;
	extern char id[MAXLEN];
	char str[MAXLEN + 1] = {};//strToken
	char ch = ' ';
	while (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') //GetBC
	{
		ch = fgetc(filename);
		if (ch == EOF)
		{
			return -1;
		}
		if (ch == '\n')
			line++;
	}
	
	if (IsLetter(ch)) {
		while (IsLetter(ch) || IsDigit(ch)) {
			if (pos > MAXLEN)return -1;
			str[pos++] = ch;
			ch = fgetc(filename);
		}
		ungetc(ch, filename);
	//	cout << "hhhhhhhhhhh    " << str << endl;
		code = Reserve(str);
	//	cout << "code is " << code << endl;
		if (code == 0) {
			value = InsertId(str);
		//	char a[20] = {};
		//	_itoa(value, a, 10);
//			printf("(%s , $ID , %d ) ", stable[value], a);
			cout << "(" + stable[value] + " , $ID , " << value<< ")" << endl;
		//	cout << "( $ID , " << value << ")" << endl;
			//printf( "(" + stable[value] + "," + "ID" + ","+to_string(value)+")");
		}
		else {
		//	char b[20] = {};
		//	_itoa(code, b, 10);
//			printf("(%s , code , - ) ", stable[value]);
			cout << "(" <<str << " , "<<code<<" , - )" << endl;
		//	cout << "( " << code << ", - )" << endl;
		}
	}
	else if (IsDigit(ch)) {
		while (IsDigit(ch)) {
			if (pos > MAXLEN)return -1;
			str[pos++] = ch;
			ch = fgetc(filename);
		}
		ungetc(ch, filename);
		value = InsertId(str);
	//	char a[20] = {};
	//	_itoa(value, a, 10);
//		printf("(%s , $INT , %d ) ", ntable[value], value);
		cout << "(" + ntable[value] + " $INT, " << value <<")" << endl;
	//	cout << "( $INT , " << value << " )" << endl;
	}
	else if (ch == '=') {
		printf("(= , SYMEQ , - )\n ");
	}
	//	SYMPLUS+  SYMMINUS- SYMMUL*  SYMDIV/   SYMASSI:=     SYMEQ=    SYMNEQ#   
	//	SYMLEFT(    SYMRIGHT)   SYMLEFTB{     SYMRIGHTB}  SYMSEM;
	else if (ch == '+') {
		printf("(+ , SYMPLUS , - )\n ");
	}
	else if (ch == '-') {
		printf("(- , SYMMINUS , - )\n ");
	}
	else if (ch == '*') {
		printf("(* , SYMMUL , - )\n ");
	}
	else if (ch == '/') {
		printf("(/ , SYMDIV , - )\n ");
	}
	else if (ch == '=') {
		printf("(= , SYMEQ , - )\n ");
	}
	else if (ch == '#') {
		printf("(# , SYMNEQ , - )\n ");
	}
	else if (ch == '(') {
		printf("(( , SYMLEFT , - )\n ");
	}
	else if (ch == ')') {
		printf("() , SYMRIGHT , - )\n ");
	}
	else if (ch == '{') {
		printf("({ , SYMLEFTB , - )\n ");
	}
	else if (ch == '}') {
		printf("(} , SYMRIGHTB , - )\n ");
	}
	else if (ch == ';') {
		printf("(; , SYMSEM , - )\n ");
	}
	else if (ch == ',') {
		printf("(, , SYMSEM , - )\n ");
	}
	else if (ch == ':') {
		ch = fgetc(filename);
		if (ch == '=') {
			printf("(:= , SYMASSI , - )\n ");
		}
		else {
			ungetc(ch, filename);
			printf("error! (: , UNDEFINED , - )\n ");
		}
	}
	//	SYMLESS <	SYMLESSEQ<=  SYMBIG>   SYMBIGEQ>=
	else if (ch == '<') {
		ch = fgetc(filename);
		if (ch == '=') {
			printf("(<= , SYMLESSEQ , - )\n");
		}
		else {
			ungetc(ch, filename);
			printf("(< , SYMLESS , - )\n ");
		}
	}
	else if (ch == '>') {
		ch = fgetc(filename);
		if (ch == '=') {
			printf("(>= , SYMBIGEQ , - )\n");
		}
		else {
			ungetc(ch, filename);
			printf("(> , SYMBIG , - )\n ");
		}
	}
	else printf("无法识别该符号");
	return 1;
}


int main(int argc, char* argv[]) {
	FILE* filename;
//	char fname[50] = "D:\study\Compilation\pro1.txt";
	filename = fopen("pro1.txt","r");  //这里使用的是绝对路径,修改的话把文件名改好就行
	if (filename == NULL)
	{
		perror("打开文件时发生错误");
		return(-1);
	}
	while (GETSYM(filename));
	
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章