編譯原理——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;
}

 

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