欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

pl/0词法分析器

发布时间:2025/6/15 编程问答 47 豆豆
生活随笔 收集整理的这篇文章主要介绍了 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,行+1syn = -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





总结

以上是生活随笔为你收集整理的pl/0词法分析器的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。