编译原理实验---词法分析

转自


http://blog.csdn.net/violet_xrym/article/details/9120239

一、实验概述

1.1、实验要求

      选择计算机高级语言之一-----C语言,运用恰当的此法分析技术线路,设计和实现其对应的词法分析器。

建议:编程语言,选择《计算机程序设计》课程所采用的语言。

提示:技术线路选择如下两种之一:

正则式→NFA→DFA→minDFA→程序设计

         或正则文法→NFA→DFA→minDFA→程序设计。

     要求:分析器输出结果存入到磁盘文件中,具有出错处理功能。

1.2、实验目的

1)加深对编译原理及其构造词法分析器的原理和技术理解与应用,进一步提高学生编程能力;

2)培养、提高学生分析问题、解决问题的综合能力;

3)整理资料,撰写规范的实验报告;


二、系统分析

2.1、系统需求

   根据C语言语法,待分析的词可以分为如下几类:

(1)    关键字

如if, else, whlile, int 等。

(2)    标示符

开头只能为字母,后面可以接数字或者字母,用来表示各种名字,如变量名、常量名和过程名等

(3)    常数

各种类型的常数,如整型(1, 30),浮点型(2.16),字符串型(”AHD”),字符型(’A’)

(4)    运算符与界符

如+,  *, <= , 逗号等。

2.2、系统功能

       读入一个C语言源程序(经过预处理的),对每一个单词输出一些三元组的集合。

2.3、系统实现步骤

按照如下顺序构造词法分析器:

(1) 设计出各类单词的正规式,画出有限状态自动机。

(2) 将各类单词的正规式转换成相应的NFA M,并将其合并成一个NFA M`

(3) 将NFA M`转换成对应的DFA M``

(4) 将DFA M``最小化为DFA M```

(5) 根据DFA M```用C语言设计出相应的词法分析器。


三、系统设计

3.1、有限状态自动机设计

     状态机说明:由于单词的构成较为复杂,所以再设计时,边的变迁不再是一个字符,而是一个函数。若当前输入串满足该函数,则当前状态可以变迁到该边连接的下一状态。

根据终态可以看出自动机可以分离的状态有:

INT

整数

FLOAT

浮点数

CHAR

字符型

CHARS

字符串型

IDENT

标识符(包括关键字)

SYMBOL

符号

其中,关键字的分离在辅助程序中进行。


3.2、单词符号对应的种别码

种别码

单词符号及说明

种别码

单词符号及说明

0

INT(整数)

30

>=

1

FLOAT(浮点数)

31

<=

2

CHAR(字符型)

32

3

CHAR(字符串型)

33

4

IDENT(标识符)

34

==

5

if

35

=

6

else

36

!=

7

int

37

++

8

char

38

+=

9

float

39

+

10

double

40

/

11

long

41

-

12

short

42

\

13

return

43

;

14

while

44

(

15

break

45

)

16

 

46

{

17

 

47

}

18

 

48

[

19

 

49

]

20

 

50

:

21

 

51

->

22

 

52

?

23

 

53

,

24

 

54

.

25

 

55

*

26

 

56

 

27

 

57

 

28

 

58

 

29

 

59

 

3.3、基本数据结构及代码设计

      代码是用C++完成的。为状态机定义了两个基本的结构体,分别为STATE和LIST。其中STATE是LIST的友元,STATE表示的是状态机中的一个状态,包括error和start等状态。LIST的实例是依附于一个STATE的实例存在的,他表示一条边,边的值是一个函数指针,该边指向一个满足该函数的另一状态。

      另外用到了STL库中的MAP模板,定义为map<string,string>type用以存放关键字及其对应的种别码。

      程序的输出为三元组的集合,其中三元组定义为<单词名, 单词含义 ,种别码>。如一个标识符abc的三元组为<abc, IDENT , 4> 。若某个单词错误,则会输出 error: name。 输出的最后会显示共识别了多少单词,并发现多少错误。


四、系统实现

4.1 系统运行

l    在命令行里直接输入待翻译的文件和输出的文件名。如果没有给参数,缺省为输入”input.txt”,输出”output.txt”。

 

l    输出的结果。

 

4.2 系统结果

 input.txt

其中,第六行为错误行。

int main()

{

   freopen("input.txt","r",stdin);

    char input[255],*s = input;

    int t = 1;

    floatp = 12.4;

    int 0a = 2;

 

    init();

 

    while(gets(s))

    {

       curn = 0;

       printf("Line %d:\n",t++);

       while((*s)!= 0)  

       {

          while((*s) == ' ') s++;  

          curn = 0;

          curtype = 0;

          print(s,start->start(s));

          s += curn;

       }

    }

 

    return 0;

}

 output.txt


********Line 1*********:

<int, int, 7>

<main, IDENT, 3>

<(, (, 34>

<), ), 35>

 

********Line 2*********:

<{, {, 36>

 

********Line 3*********:

<freopen, IDENT, 3>

<(, (, 34>

<"input.txt",CHARS, 2>

<,, ,, 43>

<"r", CHARS, 2>

<,, ,, 43>

<stdin, IDENT, 3>

<), ), 35>

<;, ;, 33>

 

********Line 4*********:

<char, char, 8>

<input, IDENT, 3>

<[, [, 38>

<255, INT, 0>

<], ], 39>

<,, ,, 43>

<*, *, 45>

<s, IDENT, 3>

<=, =, 25>

<input, IDENT, 3>

<;, ;, 33>

 

********Line 5*********:

<int, int, 7>

<t, IDENT, 3>

<=, =, 25>

<1, INT, 0>

<;, ;, 33>

 

********Line 6*********:

<float, float, 9>

<p, IDENT, 3>

<=, =, 25>

<12.4, FLOAT, 1>

<;, ;, 33>

 

********Line 7*********:

<int, int, 7>

error: 0a

<=, =, 25>

<2, INT, 0>

<;, ;, 33>

 

********Line 8*********:

 

********Line 9*********:

<init, IDENT, 3>

<(, (, 34>

<), ), 35>

<;, ;, 33>

 

********Line 10*********:

 

********Line 11*********:

<while, while, 14>

<(, (, 34>

<gets, IDENT, 3>

<(, (, 34>

<s, IDENT, 3>

<), ), 35>

<), ), 35>

 

********Line 12*********:

<{, {, 36>

 

********Line 13*********:

<curn, IDENT, 3>

<=, =, 25>

<0, INT, 0>

<;, ;, 33>

 

********Line 14*********:

<printf, IDENT, 3>

<(, (, 34>

<"Line %d:\n",CHARS, 2>

<,, ,, 43>

<t, IDENT, 3>

<++, ++, 27>

<), ), 35>

<;, ;, 33>

 

********Line 15*********:

<while, while, 14>

<(, (, 34>

<(, (, 34>

<*, *, 45>

<s, IDENT, 3>

<), ), 35>

<!=, !=, 26>

<0, INT, 0>

<), ), 35>

 

********Line 16*********:

<{, {, 36>

 

********Line 17*********:

<while, while, 14>

<(, (, 34>

<(, (, 34>

<*, *, 45>

<s, IDENT, 3>

<), ), 35>

<==, ==, 24>

<' ', CHAR, 2>

<), ), 35>

<s, IDENT, 3>

<++, ++, 27>

<;, ;, 33>

 

********Line 18*********:

<curn, IDENT, 3>

<=, =, 25>

<0, INT, 0>

<;, ;, 33>

 

********Line 19*********:

<curtype, IDENT, 3>

<=, =, 25>

<0, INT, 0>

<;, ;, 33>

 

********Line 20*********:

<print, IDENT, 3>

<(, (, 34>

<s, IDENT, 3>

<,, ,, 43>

<start, IDENT, 3>

<-, -, 31>

<>, >, 23>

<start, IDENT, 3>

<(, (, 34>

<s, IDENT, 3>

<), ), 35>

<), ), 35>

<;, ;, 33>

 

********Line 21*********:

<s, IDENT, 3>

<+=, +=, 28>

<curn, IDENT, 3>

<;, ;, 33>

 

********Line 22*********:

<}, }, 37>

 

********Line 23*********:

<}, }, 37>

 

********Line 24*********:

 

********Line 25*********:

<return, return, 13>

<0, INT, 0>

<;, ;, 33>

 

********Line 26*********:

<}, }, 37>

 

*******************************

1       error!

116 Word Have Been Found Out!


源代码:

  1. #include <iostream>  
  2. #include <string.h>  
  3. #include <map>  
  4. #include <stdio.h>  
  5. #define num_before_symbol 20  
  6.   
  7. using namespace std;  
  8.   
  9. bool isNum(char *a);  
  10. bool isWord(char *a);  
  11. bool isSymbol(char *a);  
  12. bool isNULL(char *a);  
  13.   
  14. map<string,string>type;  
  15.   
  16. char symbol[][10] = {">=","<=","<",">","==","=","!=","++","+=","+","/","-","\\",";","(",")","{","}",  
  17.                      "[","]",":","->","?",",",".","*","\0"};  
  18. int curn = 0;  
  19. int curtype = 0;  
  20. int nerror = 0;  
  21.   
  22.   
  23. class STATE;  
  24. class LIST;  
  25.   
  26. class STATE  
  27. {  
  28.     LIST *list;  
  29.     static STATE *error;  
  30.  public:  
  31.     static int count;  
  32.     int type;  
  33.     char *name;  
  34.     void enlist(bool (*fun)(char *),STATE *out);  
  35.     const STATE *next(char *in)const;  
  36.     const STATE *start(char *)const;  
  37.     STATE(char *name);  
  38.     ~STATE();  
  39. };  
  40.   
  41. class LIST{  
  42.   LIST *next;  
  43.   bool (*fun)(char *);  
  44.   STATE *output;  
  45.   LIST(bool (*fun)(char *),STATE *out);  
  46.   ~LIST();  
  47.   friend class STATE;  
  48. };  
  49.   
  50. STATE *STATE::error = 0;  
  51. int STATE::count = 0;  
  52.   
  53.   
  54. LIST::LIST(bool (*fun)(char *),STATE *out)  
  55. {  
  56.     this->next = NULL;  
  57.     this->fun = fun;  
  58.     this->output = out;  
  59. }  
  60. LIST::~LIST()   //怎么delete????  
  61. {  
  62.     if(this->next!=NULL)  
  63.         delete this->next;  
  64. }  
  65.   
  66. const STATE *STATE::next(char *in)const  
  67. {  
  68.     LIST *p = list;  
  69.     //if(this == error) return error;  
  70.     while(p!=NULL)  
  71.     {  
  72.         if(p->fun(in))  
  73.           return p->output;  
  74.   
  75.         else  
  76.           p = p->next;  
  77.     }  
  78.     return error;  
  79. }  
  80.   
  81. const STATE *STATE::start(char *s)const  
  82. {  
  83.     const STATE *p;  
  84.   
  85.     if(list == NULL)  
  86.     {  
  87.         if(this != error)  
  88.            count++;  
  89.         else  
  90.         {  
  91.             while(isWord(s))  
  92.               curn++;  
  93.         }  
  94.         return this;  
  95.     }  
  96.   
  97.     p = this->next(s);  
  98.     if(p == error)  
  99.       return error;          //error是否要加前缀  
  100.     return p->start(s+1);  
  101. }  
  102.   
  103. STATE::STATE(char *name)  
  104. {  
  105.     if(name == 0)  
  106.     {  
  107.        error = this;  
  108.        this->type = 1;  
  109.        return;  
  110.     }  
  111.   
  112.     if(strcmp(name,"SYMBOL"))  
  113.       this->type = 0;  
  114.     else  
  115.       this->type = 1;  
  116.   
  117.     this->name = new char[strlen(name)]; //strlen+1  
  118.     strcpy(this->name,name);  
  119.     this->list = NULL;  
  120. }  
  121.   
  122. STATE::~STATE()  
  123. {  
  124.     if(list)  
  125.     {  
  126.       delete list;  
  127.       list = 0;  
  128.     }  
  129.   
  130.     if(name)  
  131.     {  
  132.         delete name;  
  133.         name = 0;  
  134.     }  
  135. }  
  136.   
  137. void STATE::enlist(bool (*fun)(char *),STATE *out)  
  138. {  
  139.     LIST *p = new LIST(fun,out);  
  140.     LIST *cur = this->list;  
  141.     if(cur == NULL)  
  142.      this->list = p;  
  143.     else  
  144.     {  
  145.        while(cur->next!=NULL)  
  146.           cur = cur->next;  
  147.        cur->next = p;  
  148.     }  
  149. }  
  150.   
  151. bool mystrcmp(char *a,char *s)  
  152. {  
  153.    int i = 0;  
  154.    while(s[i]!='\0')  
  155.    {  
  156.       if(a[i]!=s[i])  
  157.         return false;  
  158.       i++;  
  159.    }  
  160.    return true;  
  161. }  
  162.   
  163. bool isNum(char *a)  
  164. {  
  165.    if(a[0]<='9' && a[0]>='0')  
  166.    {  
  167.        curn++;  
  168.        return true;  
  169.    }  
  170.    return false;  
  171. }  
  172.   
  173. bool isDot(char *a)  
  174. {  
  175.     if(a[0] == '.')  
  176.     {  
  177.        curn++;  
  178.        return true;  
  179.     }  
  180.     return false;  
  181. }  
  182.   
  183. bool isWord(char *a)  
  184. {  
  185.    if((a[0]<='Z' && a[0]>='A') || (a[0]>='a' && a[0]<='z'))  
  186.     {  
  187.        curn++;  
  188.        return true;  
  189.     }  
  190.     return false;  
  191. }  
  192.   
  193. bool isNotNumOrWord(char *a)  
  194. {  
  195.    if((!(a[0]<='9' && a[0]>='0')) && !isWord(a))  
  196.    {  
  197.        return true;  
  198.    }  
  199.    curn--;  
  200.    return false;  
  201. }  
  202.   
  203. bool isSymbol(char *a)  
  204. {  
  205.     int i = 0;  
  206.     while(strcmp(symbol[i],"\0"))  
  207.     {  
  208.        if(mystrcmp(a,symbol[i]))  
  209.        {  
  210.          curtype = i;  
  211.          curn = strlen(symbol[i]);  
  212.          break;  
  213.        }  
  214.        i++;  
  215.     }  
  216. }  
  217.   
  218. bool isDQuotation(char *a)  
  219. {  
  220.    if(a[0] == '"')  
  221.    {  
  222.        curn++;  
  223.        return true;  
  224.    }  
  225.    return false;  
  226. }  
  227.   
  228. bool isNotDQuotation(char *a)  
  229. {  
  230.    if(a[0] != '"')  
  231.    {  
  232.        curn++;  
  233.        return true;  
  234.    }  
  235.    return false;  
  236. }  
  237.   
  238. bool isNotSQuotation(char *a)  
  239. {  
  240.    if(a[0]!='\'')  
  241.    {  
  242.        curn++;  
  243.        return true;  
  244.    }  
  245.    return false;  
  246. }  
  247.   
  248. bool isSQuotation(char *a)  
  249. {  
  250.    if(*(a-1)!='\\' && (*a)== '\'')  
  251.    {  
  252.        curn++;  
  253.        return true;  
  254.    }  
  255.    return false;  
  256. }  
  257.   
  258.   
  259. STATE *start = new STATE("start");  
  260. STATE *s1 = new STATE("s1");  
  261. STATE *s2 = new STATE("s2");  
  262. STATE *s3 = new STATE("s3");  
  263. STATE *s4 = new STATE("s4");  
  264. STATE *s5 = new STATE("s5");  
  265. STATE *s6 = new STATE("s6");  
  266. STATE *INT = new STATE("INT");  
  267. STATE *FLOAT = new STATE("FLOAT");  
  268. STATE *IDENT = new STATE("IDENT");  
  269. STATE *SYMBOL = new STATE("SYMBOL");  
  270. STATE *CHAR = new STATE("CHAR");  
  271. STATE *CHARS = new STATE("CHARS");  
  272. STATE error(0);  
  273.   
  274.   
  275. void init()  
  276. {  
  277.     start->enlist(isNum,s1);  
  278.     start->enlist(isWord,s3);  
  279.     start->enlist(isSymbol,SYMBOL);  
  280.     start->enlist(isDQuotation,s4);  
  281.     start->enlist(isSQuotation,s5);  
  282.     s1->enlist(isNum,s1);  
  283.     s1->enlist(isDot,s2);  
  284.     s1->enlist(isNotNumOrWord,INT);  
  285.     s1->enlist(isWord,&error);   //需要将错误部分剩下的跳过,对error类型进行标识。  
  286.   
  287.     s2->enlist(isNum,s2);  
  288.     s2->enlist(isNotNumOrWord,FLOAT);  
  289.     s2->enlist(isWord,&error);  
  290.   
  291.     s3->enlist(isWord,s3);  
  292.     s3->enlist(isNum,s3);  
  293.     s3->enlist(isNotNumOrWord,IDENT);  
  294.   
  295.     s4->enlist(isNotDQuotation,s4);  //if is """ will get wrong answer  
  296.     s4->enlist(isDQuotation,CHARS);  
  297.   
  298.     s5->enlist(isNotSQuotation,s6);  
  299.     s5->enlist(isSQuotation,&error);  
  300.     s6->enlist(isSQuotation,CHAR);  
  301.   
  302.     type["INT"] = "0";  
  303.     type["FLOAT"] = "1";  
  304.     type["CHAR"] = "2";  
  305.     type["CHARS"] = "2";  
  306.     type["IDENT"] = "3";  
  307.     type["if"] = "5";  
  308.     type["else"] = "6";  
  309.     type["int"] = "7";  
  310.     type["char"] = "8";  
  311.     type["float"] = "9";  
  312.     type["double"] = "10";  
  313.     type["long"] = "11";  
  314.     type["short"] = "12";  
  315.     type["return"] = "13";  
  316.     type["while"] = "14";  
  317.     type["break"] = "15";  
  318.   
  319.   
  320.     //引号算什么??  
  321. }  
  322.   
  323. void print(char *s,const STATE *p)  
  324. {  
  325.     int i = 0;  
  326.     char temp[255];  
  327.   
  328.     for(i = 0;i<curn;i++)  
  329.       temp[i] = s[i];  
  330.     temp[i] = '\0';  
  331.   
  332.     if(p->name == 0)  
  333.     {  
  334.       printf("error: %s\n",temp);  
  335.       nerror++;  
  336.       return;  
  337.     }  
  338.   
  339.     printf("<");  
  340.     for(i = 0;i<curn;i++)  
  341.       printf("%c",*(s+i));  
  342.     if(curtype == 0)  
  343.     {  
  344.        if(type.find(temp) == type.end())  
  345.           cout<<", "<<p->name<<", "<<type[p->name]<<">"<<endl;  
  346.        else  
  347.          cout<<", "<<temp<<", "<<type[temp]<<">"<<endl;  
  348.     }  
  349.     else  
  350.       printf(", %s, %d>\n",symbol[curtype],num_before_symbol+curtype);  
  351. }  
  352.   
  353. int main(int argv,char *argc[])  
  354. {  
  355.     char temp[2][255];  
  356.     if(argv<2)  
  357.         strcpy(temp[0],"input.txt");  
  358.     else  
  359.         strcpy(temp[0],argc[1]);  
  360.     if(argv<3)  
  361.         strcpy(temp[1],"output.txt");  
  362.     else  
  363.         strcpy(temp[1],argc[2]);  
  364.     freopen((const char*)temp[0],"r",stdin);  
  365.     freopen((const char*)temp[1],"w",stdout);  
  366.   
  367.     char input[255],*s = input;  
  368.     int t = 1;  
  369.   
  370.     init();  
  371.   
  372.     while(gets(s))  
  373.     {  
  374.        curn = 0;  
  375.        printf("********Line %d*********:\n",t++);  
  376.        if(t == 18)  
  377.          t = 18;  
  378.        while((*s)!='\0')    //n is last edit  
  379.        {  
  380.           while((*s) == ' ') s++;   //滤掉空格  
  381.           curn = 0;  
  382.           curtype = 0;  
  383.           print(s,start->start(s));  
  384.           s += curn;  
  385.           while((*s) == ' ') s++;   //滤掉空格  
  386.        }  
  387.        s = input;  
  388.        printf("\n");  
  389.     }  
  390.     printf("*******************************\n%d error!\n%d Word Have Been Found Out!\n",nerror,STATE::count);  
  391.   
  392.     return 0;  
  393. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值