编译实验(一)词法分析

 编译原理课程即将结束,开始了在校中最麻烦的实验,编译实验......同在一个系,其他班的编译实验分成好几块,简短的文法,
完成一些小功能,就我们班的老师,撂下一句话:参考书本,把编译器实现了,可以一组两人分工合作。
源代码连接:http://download.csdn.net/download/supersmart_dong/10224159
词法分析流程图:
 
首先要做的第一步就是写数据结构以及完成单词表。词法分析的任务就是将一段程序代码,分割单词,把单词信息写出来。
例如在代码: while A<2 do A:=A+1;  中进行词法分析得出来结果,(while,关键字) (A,标识符) (<,算符)(2,整数) (do,关键字) (A,标识符)
(:=,算符) (A,标识符)(+,算符) (1,整数) (;,界符) 将代码中单词一个个的取出来进行分析便是词法分析的任务。输出内容是符号表文件和
token文件。
单词表如下图:
 

单词

编码

单词

编码

单词

编码

单词

编码

end

1

or

11

21

:=

31

begin

2

program

12

22

=

32

bool

3

real

13

+

23

<=

33

do

4

then

14

-

24

<

34

else

5

true

15

*

25

<>

35

end

6

var

16

/

26

>

36

false

7

while

17

.

27

>=

37

if

8

标识符

18

28

 

 

integer

9

整数

19

:

29

 

 

not

10

实数

20

30

 

 

单词表可以用一维对象数组实现,根据编码或者数组索引来判断该单词是不是关键字还是算符或界符。
之后写一些判断的函数,判断是否是关键字,是否是数字,是否是算符,是否是界符
然后按照流程来,读取文件,一个字符一个字符的读,如果读到第i=0个字符是字母,则读第i+1个,一直读到不是字母或数字为止,
将这i个字符构成一个单词,查询是不是关键字,如果不是则为标识符。如果读到的第i=0个字符是数字,则继续读第i+1个,一直读到不是
字母或数字为止。判断这单词是不是数字(浮点数,整数),如果读到第i=0字符既不是字母也不是数字,则读取下一个字符(记为变量A)和下
两个字符(记为变量B),判断这A或B中有没有算符,判断A是不是界符,如果都不是则为非法字符。像这样读完整个程序结束输出符号表文件。
 
#include<iostream> #include<string> #include<fstream> #include <cassert> using namespace std; struct WordToken { string name; int code; }; struct WordSymble { string name; // int code; string type; int addr = -1; //符号表位置 int linenum; //行号 }; struct symble { int number; //序号 string type; //类型 string name; //名字 }; #pragma region 单词表 WordToken keyword[] = { { "and", 1 }, { "begin", 2 }, { "bool", 3 }, { "do", 4 }, { "else", 5 }, { "end", 6 }, { "false", 7 }, { "if", 8 }, { "integer", 9 }, { "not", 10 }, { "or", 11 }, { "program", 12 }, { "real", 13 }, { "then", 14 }, { "true", 15 }, { "var", 16 }, { "while", 17 } }; WordToken operatorword[] = { { "+", 23 }, { "-", 24 }, { "*", 25 }, { "/", 26 }, { ">", 31 }, { ":=", 38 }, { "=", 32 }, { "<=", 33 }, { "<", 34 }, { "<>", 35 }, { ">", 36 }, { ">=", 37 } }; WordToken delimeter[] = { { "(", 21 }, { ")", 22 }, { ".", 27 }, { ",", 28 }, { ":", 29 }, { ";", 30 } }; #pragma endregion int iskeyword(string s)//关键字 { int i = 0; if (s != "") { if (((s[0] >= 'A') && (s[0] <= 'Z')) || ((s[0] >= 'a') && (s[0] <= 'z'))) { while (i<17) { if (keyword[i].name == s) { return keyword[i].code; } i++; } return 18; //标识符 } } return -1; } int isoperator(string s)//算符 { int i = 0; if (s != "") { while (i<12) { if (s == operatorword[i].name) { return operatorword[i].code; break; } i++; } } return -1; } int isdelimeter(string s)//界符 { int i = 0; if (s != "") { while (i<6) { if (s == delimeter[i].name) { return delimeter[i].code; break; } i++; } } return -1; } int isdight(string &s, int n)//整数 { int i = 0; int j = 0; string ss; bool a = true; string wrong; while (i< s.length()) { if (j <= 1 && a) { if (s[i] == '.') { j++; } if (((s[i] >= 'A') && (s[i] <= 'Z')) || ((s[i] >= 'a') && (s[i] <= 'z'))) { a = false; } i++; } else { for (int k = 0; k < i - 1; k++) { ss += s[k]; s = ss; } for (int k = i - 1; k < s.length(); k++) { wrong += s[k]; } break; } } if (j == 2 || !a) { cout << "错误行号为" << n + 1 << " "; cout << "错误内容为" << wrong << " "; cout << "错误类型为" << "错误单词" << endl; } if (j == 0) { return 19; } else if (j >= 1) { return 20; } return -1; } int length = 0; extern int line = 0; string word; string text; int k = 0; //wordSysmble个数 1开始 int l = 0; string alltext[100]; WordSymble wss[1000]; symble fuhaobiao[1000]; void get_token() //生成符号表和token { for (; alltext[line] != ""; line++) { text = alltext[line]; length = text.length(); for (int i = 0; i < length; i++) { if (text[i] != ' ') { word = ""; if (((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z'))) { while (((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z')) || ((text[i] >= 48) && (text[i] <= 57))) { word += text[i]; i++; } i--; if (iskeyword(word) != -1) { if (iskeyword(word) == 18) { wss[k].name = word; wss[k].code = iskeyword(word); wss[k].type = "标识符"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "标识符"; fuhaobiao[l].number = l; l++; k++; } else { wss[k].name = word; wss[k].code = iskeyword(word); wss[k].type = "关键字"; wss[k].linenum = line; k++; } } } else if ((text[i] >= 48) && (text[i] <= 57)) { while (((text[i] >= 48) && (text[i] <= 57)) || (text[i] == '.') || ((text[i] >= 'A') && (text[i] <= 'Z')) || ((text[i] >= 'a') && (text[i] <= 'z'))) { word += text[i]; i++; } i--; int a = isdight(word, line); if (a == 19) { wss[k].name = word; wss[k].code = 19; wss[k].type = "整数"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "整数"; fuhaobiao[l].number = l; l++; k++; } else if (a == 20) { wss[k].name = word; wss[k].code = 20; wss[k].type = "浮点数"; wss[k].addr = l; wss[k].linenum = line; fuhaobiao[l].name = word; fuhaobiao[l].type = "浮点数"; fuhaobiao[l].number = l; l++; k++; } } else { word += text[i]; string ss = word; ss += text[i + 1]; if (isoperator(ss) != -1) { word += text[i + 1]; i = i + 1; wss[k].name = word; wss[k].code = isoperator(word); wss[k].type = "算符"; wss[k].linenum = line; k++; } else if (isdelimeter(word) != -1) { wss[k].name = word; wss[k].code = isdelimeter(word); wss[k].type = "界符"; wss[k].linenum = line; k++; } else if (isoperator(word) != -1) { wss[k].name = word; wss[k].code = isoperator(word); wss[k].type = "算符"; wss[k].linenum = line; k++; } else { wss[k].name = word; wss[k].code = 100; wss[k].type = "非法字符"; wss[k].linenum = line; k++; } } } } } } void readtext(string file) { ifstream infile; infile.open(file.data()); //将文件流对象与文件连接起来 assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行 int i = 0; string s; while (getline(infile, s)) { alltext[i] += s; i++; } infile.close(); } void printReadtext(string url = "D: / a.txt") { readtext(url); cout << "程序如下:" << endl; for (int i = 0; alltext[i] != ""; i++) { cout << alltext[i] << endl; } cout << endl; cout << "下面进行词法分析" << endl; cout << endl; get_token(); } void printTokenResult() { int j = 0; cout << endl; while (wss[j].name != "") { cout << "(" << wss[j].name << "," << wss[j].code << "," << wss[j].type << "," << wss[j].addr << "," << wss[j].linenum << ")" << endl; j++; } j = 0; cout << endl; cout << "符号表为" << endl; while (fuhaobiao[j].name != "") { cout << "(" << fuhaobiao[j].number << "," << fuhaobiao[j].name << "," << fuhaobiao[j].type << ")" << endl; j++; } cout << endl; } 

 

部分输出结果如图所示:
 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值