pl/0词法分析器


下面是这个分析器的功能:

1、    待分析的简单语言的词法

(1)    关键字:

begin  if   then   while   do   end

所有关键字都是小写。

(2)    运算符和界符:

:=   +   –   *   /   <   <=   <>   >   >=   =   ;   (   )   #

(3)    其他单词是标识符(ID)和整型常数(NUM),通过以下正规式定义:

ID=letter(letter| digit)*

NUM=digit digit *

(4)    空格由空白、制表符和换行符组成。空格一般用来分隔ID、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。

2、  各种单词符号对应的种别码

词法分析程序的功能

输入:所给文法的源程序字符串。

输出:二元组(syn,token或sum)构成的序列。

其中:syn为单词种别码;

token为存放的单词自身字符串;

sum为整型常数。







#include <iostream>
#include <fstream>
#include <string>
#include <windows.h>

using namespace std;

#define CODE "E:\\code\\code.txt"
#define RESULT "E:\\code\\result.txt"

//token数组用来接收关键字,变量,运算符和界符
//这里限制变量名的长度最多为9
//prog数组存储的是源代码字符串长度
char *prog, token[10];
char ch;
//syn是各个单词符号对应的数字
int syn, p, m = 0, n, line, sum = 0;
//rwtab数组存储的是关键字
char *rwtab1[10] = { "begin","if","then","while","do","end" };
char *rwtab2[4] = { "const","var","procedure","call" };

void scaner()
{
	//规定,标识符只能由字母或数字构成

	/*
	共分为三大块,分别是标示符、数字、符号,对应下面的 if   else if  和 else
	*/

	//将全部置空
	for (n = 0; n<10; n++)
		//token为已捕获的字符数
		token[n] = NULL;
	ch = prog[p++];

	//这样处理,可以去除空格
	while (ch == ' ')
	{
		ch = prog[p];
		p++;
	}
	//在这个if判断中,范围是a-z或者A-Z,因为规定变量只能以字母开头
	if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'))  //可能是标示符或者变量名
	{
		m = 0;
		//这里,是变量的第一个字符以后,可以是字母,数字
		while ((ch >= '0'&&ch <= '9') || (ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z'))
		{
			token[m++] = ch;
			ch = prog[p++];
		}
		//变量的字符串结束标志
		token[m++] = '\0';
		p--;
		syn = 10;

		//将识别出来的字符和已定义的标示符作比较, 判断是否是关键字,所有关键字都是小写
		for (n = 0; n<6; n++)
			if (strcmp(token, rwtab1[n]) == 0)
			{
				syn = n + 1;
				break;
			}
		for (n = 0; n < 4;n++)
		{
			if (strcmp(token, rwtab2[n]) == 0)
			{
				syn = n + 31;
				break;
			}
		}
	}
	else if ((ch >= '0'&&ch <= '9'))  //数字 ,如果是数字,就用sum来保存这个数字
	{
		sum = 0;
		while ((ch >= '0'&&ch <= '9'))
		{
			//这里*10是只考虑十进制数
			sum = sum * 10 + ch - '0';
			ch = prog[p++];
		}
		p--;
		syn = 11;
		//可接收的数字的最大值为32767,如果更大,会报错
		if (sum>32767)
			syn = -1;
	}
	else switch (ch)   //如果是其他的字符
	{
	case '<':
		m = 0;
		token[m++] = ch;
		ch = prog[p++];
		if (ch == '>')
		{
			//说明是不等号
			syn = 21;
			token[m++] = ch;
		}
		else if (ch == '=')
		{
			//说明是<=
			syn = 22;
			token[m++] = ch;
		}
		else
		{
			//否则,就只是一个<符号
			syn = 23;
			//此时p回退一个
			p--;
		}
		break;
	case '>':
		m = 0;
		token[m++] = ch;
		ch = prog[p++];
		if (ch == '=')
		{
			syn = 24;
			token[m++] = ch;
		}
		else
		{
			syn = 20;
			p--;
		}
		break;
	case ':':
		m = 0;
		token[m++] = ch;
		ch = prog[p++];
		if (ch == '=')
		{
			//说明是赋值运算符
			syn = 18;
			token[m++] = ch;
		}
		else
		{
			//否则就只是个:
			syn = 17;
			p--;
		}
		break;
	case '*':
		syn = 13;
		token[0] = ch;
		break;
	case '/':
		syn = 14;
		token[0] = ch;
		break;
	case '+':
		syn = 15;
		token[0] = ch;
		break;
	case '-':
		syn = 16;
		token[0] = ch;
		break;
	case '=':
		syn = 25;
		token[0] = ch;
		break;
	case ';':
		syn = 26;
		token[0] = ch;
		break;
	case '(':
		syn = 27;
		token[0] = ch;
		break;
	case ')':
		syn = 28;
		token[0] = ch;
		break;
	case ',':
		syn = 29;
		token[0] = ch;
		break;
	case '!':
		syn = 30;
		token[0] = ch;
		break;
	case '.':
		//如果接收到的是.,说明到了源代码的结尾,置syn=0,函数结束
		syn = 0;
		token[0] = ch;
		break;
	case '\n':
		//如果接收到的是换行符,则syn=-2,行+1
		syn = -2;
		break;
	default:
		//如果接收到的是其他未定义的字符,置syn=-1,会报错。
		syn = -1;
		break;
	}
}

/*
读取源代码文件(.txt)
*/
void read()
{
	FILE *fp;
	fp = fopen(CODE, "r");
	fseek(fp, 0, SEEK_END);
	int file_size;
	file_size = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	prog = (char *)malloc(file_size * sizeof(char));
	fread(prog, file_size, sizeof(char), fp);

	//关闭文件流
	fclose(fp);
}

int main()
{
	int p = 0;
	int line = 1;
	ofstream outfile(RESULT);

	cout<< "加载代码文件中......" << endl;
	Sleep(3000);
	//读取源代码文件
	read();

	p = 0;
	outfile << "词法分析的结果为:" << endl;
	do
	{
		scaner();
		switch (syn)
		{
		case 11:
			//cout << "(" << syn << "," << sum << ")" << endl;
			outfile << "(" << syn << "," << sum << ")" << endl;
			break;
		case -1:
			//cout << "Error in line " << line << "!" << endl;
			outfile << "Error in line" << line << "!" << endl;
			break;
		case -2:
			line = line++;
			break;
		default:
			//cout << "(" << syn << "," << token << ")" << endl;
			outfile << "(" << syn << "," << token << ")" << endl;
			break;
		}
	} while (syn != 0);

	outfile.close();

	cout << "词法分析完毕,请在result.txt中查看" << endl;

	system("pause");
	return 0;
}

pl/0 程序


var m, n, r, q;
procedure gcd;
begin
while r#0 do
begin
q := m / n;
r := m - q * n;
m := n;
n := r;
end;
end;
begin
read(m);
read(n);
if m < n then
begin
r := m;
m := n;
n := r;
end;
begin
r:=1;
call gcd;
write(m);
end;
end.

输出结果


#
#
using---->25
namespace---->25
std---->25
;------->41
int---->7
main---->1
(------->42
)------->43
const---->18
string---->25
str---->25
=------->38
hello---->25
;------->41
const---->18
string---->25
str2---->25
=------->38
world---->25
;------->41
string---->25
n_str---->25
;------->41
n_str---->25
=------->38
str---->25
;------->41
n_str---->25
+------->27
=------->38
str2---->25
;------->41
cout---->25
<------>33
<------>33
n_str---->25
<------>33
<------>33
endl---->25
;------->41
return---->17
0------>26
;------->41






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值