孤独的猫

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

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

————————————————

 

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

 

原文链接:https://blog.csdn.net/judyge/article/details/52274690

posted on 2024-04-28 13:51  孤独的猫  阅读(35)  评论(0编辑  收藏  举报