《编译原理》第一次实验:词法分析

发布时间 2023-04-30 16:34:58作者: Hell0er

该分类为本人在本学期《编译原理》课程上的实验报告,实验对象语言为教学用PL/0语言,实验所用语言为C++。全部报告仅供参考,如有缺漏或错误,烦请指出,Thanks ♪(・ω・)ノ


一. 设计思想

根据 PL/0 语言的文法规范,编写 PL/0 语言的词法分析程序。

1.单词种类及其正规式

(1)基本字

单词的值 单词类型  正规式 r 
begin beginsym begin
call callsym call
const  constsym const
do dosym do
end endsym end
if  ifsym if
odd oddsym odd
procedure proceduresym procedure 
read readsym read
then thensym then
var varsym var
while whilesym while
write  writesym write

(2)标识符

单词的值 单词类型 正规式 r
标识符 Ident (字母)(字母|数字)*

(3)常数

单词的值 单词类型 正规式 r
常数 number (数字)(数字)*

(4)运算符

单词的值 单词类型 正规式 r
+ plus +
- minus -
* times *
/ slash /
= eql =
<> neq <>
< lss <
<= leq <=
> gtr >
>= geq >=
:= becomes :=

(5)界符

单词的值 单词类型 正规式 r
( lparen (
) rparen )
, comma ,
; semicolon ;
. period .

2.NFA

3.DFA

4.最小化 DFA

二. 算法流程

三. 源程序

  1 #include <iostream>
  2 #include <string>
  3 #include <vector>
  4 using namespace std;
  5 
  6 void getChar(const string s,int& idx,char& ch)   // 取下个字符
  7 {
  8     ch=s[idx++];
  9     return;
 10 }
 11 
 12 void getBC(const string s,int& idx,char& ch)   // 跳过空格
 13 {
 14     while (ch==' ')
 15     {
 16         getChar(s,idx,ch);
 17     }
 18     return;
 19 }
 20 
 21 void concat(string& strToken,const char ch)   // 字符拼接
 22 {
 23     strToken+=ch;
 24     return;
 25 }
 26 
 27 void retract(int& idx,char& ch)   // 退一格
 28 {
 29     --idx;
 30     ch=' ';
 31     return;
 32 }
 33 // 基本字数组
 34 string basicWord[13]={"begin","call","const","do","end",
 35                         "if","odd","procedure","read",
 36                         "then","var","while","write"};
 37 // 处理基本字
 38 string basic(const string strToken)
 39 {
 40     bool isbasic=false;
 41     for (int i=0;i<13;++i)
 42     {
 43         if (strToken==basicWord[i])
 44         {
 45             isbasic=true;
 46             break;
 47         }
 48     }
 49     if (isbasic)   // 如果是基本字
 50     {
 51         return strToken;
 52     }
 53     else   // 否则是标识符
 54     {
 55         return "ident";
 56     }
 57 }
 58 
 59 
 60 int main()
 61 {
 62     vector<string> v;
 63     string s="";
 64     string str;
 65     while (cin>>str)   // 循环读入
 66     {
 67         s=s+' '+str;
 68     }
 69 
 70     int idx=0;
 71     while (idx<(int)s.length()){   // 处理每个字符
 72         char ch=' ';
 73         string strToken="";
 74         getChar(s,idx,ch);
 75         getBC(s,idx,ch);
 76         if (isalpha(ch))   // 如果是字母
 77         {
 78             while (isalnum(ch))   // 读字母或数字
 79             {
 80                 concat(strToken,ch);
 81                 getChar(s,idx,ch);
 82             }
 83             retract(idx,ch);
 84             string ret=basic(strToken);
 85             if (ret=="ident")
 86             {
 87                 v.push_back(string("(ident,"+strToken+')'));
 88             }
 89             else
 90             {
 91                 v.push_back(string('('+ret+"sym"+','+strToken+')'));
 92             }
 93         }
 94         else if (isdigit(ch))   // 如果是数字
 95         {
 96             while (isdigit(ch))   // 持续获取数字
 97             {
 98                 concat(strToken,ch);   // 将所有数字拼起来
 99                 getChar(s,idx,ch);   // 下一个字符
100             }
101             retract(idx,ch);
102             v.push_back(string(+"(number,"+strToken+')'));
103         }
104         else if (ch=='+')
105         {
106             v.push_back("(plus,+)");
107         }
108         else if (ch=='-')
109         {
110             v.push_back("(minus,-)");
111         }
112         else if (ch=='*')
113         {
114             v.push_back("(times,*)");
115         }
116         else if (ch=='/')
117         {
118             v.push_back("(slash,/)");
119         }
120         else if (ch=='=')
121         {
122             v.push_back("(eql,=)");
123         }
124         else if (ch=='<')   // '<'后有 <>、<= 两种可能
125         {
126             getChar(s,idx,ch);
127             if (ch=='>')
128             {
129                 v.push_back("(neq,<>)");
130             }
131             else if (ch=='=')
132             {
133                 v.push_back("(leq,<=)");
134             }
135             else
136             {
137                 retract(idx,ch);
138                 v.push_back("(les,<)");
139             }
140         }
141         else if (ch=='>')   // '>'后有 >= 的可能
142         {
143             getChar(s,idx,ch);
144             if (ch=='=')
145             {
146                 v.push_back("(geq,>=)");
147             }
148             else
149             {
150                 retract(idx,ch);
151                 v.push_back("(gtr,>)");
152             }
153         }
154         else if (ch==':')
155         {
156             getChar(s,idx,ch);
157             if (ch=='=')
158             {
159                 v.push_back("(becomes,:=)");
160             }
161         }
162         else if (ch=='(')
163         {
164             v.push_back("(lparen,()");
165         }
166         else if (ch==')')
167         {
168             v.push_back("(rparen,))");
169         }
170         else if (ch==',')
171         {
172             v.push_back("(comma,,)");
173         }
174         else if (ch==';')
175         {
176             v.push_back("(semicolon,;)");
177         }
178         else if (ch=='.')
179         {
180             v.push_back("(period,.)");
181         }
182         else
183         {
184             v.push_back("(OTHER,"+ch+')');
185         }
186     }
187     for (int i=0;i<(int)v.size();++i)   // 输出
188     {
189         cout<<v[i]<<endl;
190     }
191     return 0;
192 }
View Code

四. 调试数据

1.样例输入:

1 const a=10;
2 var b,c;
3 begin
4 read(b);
5 c:=a+b;
6 write(c)
7 end.

样例输出:

(constsym,const)
(ident,a)
(eql,=)
(number,10)
(semicolon,;)
(varsym,var)
(ident,b)
(comma,,)
(ident,c)
(semicolon,;)
(beginsym,begin)
(readsym,read)
(lparen,()
(ident,b)
(rparen,))
(semicolon,;)
(ident,c)
(becomes,:=)
(ident,a)
(plus,+)
(ident,b)
(semicolon,;)
(writesym,write)
(lparen,()
(ident,c)
(rparen,))
(endsym,end)
(period,.)

图片展示:

2. 样例输入:

1 const a=10;
2 var b,c,d;
3 begin
4 read(b);
5 read(c);
6 d:=a+b+c;
7 write(d)
8 end.

样例输出:

 1 (constsym,const)
 2 (ident,a)
 3 (eql,=)
 4 (number,10)
 5 (semicolon,;)
 6 (varsym,var)
 7 (ident,b)
 8 (comma,,)
 9 (ident,c)
10 (comma,,)
11 (ident,d)
12 (semicolon,;)
13 (beginsym,begin)
14 (readsym,read)
15 (lparen,()
16 (ident,b)
17 (rparen,))
18 (semicolon,;)
19 (readsym,read)
20 (lparen,()
21 (ident,c)
22 (rparen,))
23 (semicolon,;)
24 (ident,d)
25 (becomes,:=)
26 (ident,a)
27 (plus,+)
28 (ident,b)
29 (plus,+)
30 (ident,c)
31 (semicolon,;)
32 (writesym,write)
33 (lparen,()
34 (ident,d)
35 (rparen,))
36 (endsym,end)
37 (period,.)

图片展示:

3.样例输入:

1 const a=10;
2 const b=10;
3 var c;
4 begin
5 c:=a+b;
6 write(c)
7 end.

样例输出:

 1 (constsym,const)
 2 (ident,a)
 3 (eql,=)
 4 (number,10)
 5 (semicolon,;)
 6 (constsym,const)
 7 (ident,b)
 8 (eql,=)
 9 (number,10)
10 (semicolon,;)
11 (varsym,var)
12 (ident,c)
13 (semicolon,;)
14 (beginsym,begin)
15 (ident,c)
16 (becomes,:=)
17 (ident,a)
18 (plus,+)
19 (ident,b)
20 (semicolon,;)
21 (writesym,write)
22 (lparen,()
23 (ident,c)
24 (rparen,))
25 (endsym,end)
26 (period,.)

图片展示:

五. 实验调试情况及体会


参考博客: