一、实验目的
设计、编写和调试词法分析程序,加深对词法分析原理的理解。
二、实验内容
2.1要分析的简单字句
)1)关键词:
begin if then while do end
所有关键字都是小写的。
)2)运算符和边界符号
()-)/==; () #
)3)其他单词为标识符(ID )和整数常量(SUM ),用以下正则表达式定义。
id=letter(letter|digit ) *
NUM=digit digit*
)4)空格有空白、制表符和换行符。 空格通常用于分隔ID、SUM、运算符、边界字符和关键字,并在词法分析阶段被忽略。
2.2各单词符号对应的类别代码:
表2.1各单词符号对应的类别代码
单词符号
类别代码
单词符号
类别代码
bgin
1
:
17
国际足联
2
() )=
18
Then
3
20
维鲁
4
21
do
5
=
22
结束
6
23
lettet(letter|digit ) *
10
=
24
构件构件*
11
=
25
style="margin-left:0pt;">13;
26
—
14
(
27
*
15
)
28
/
16
#
0
2.3 词法分析程序的功能:
输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
例如:对源程序begin x:=9: if x>9 then x:=2*x+1/3; end #的源文件,经过词法分析后输出如下序列:
(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)……
程序中需要用到的主要变量为syn,token和sum。
①token用来存放构成单词符号的字符串;②sum用来整型单词;③syn用来存放单词符号的种别码。
#include <iostream>#include <string.h>using namespace std;char key[6][20] = {"begin","if","then","while","do","end"};//定义一个二维数组存放关键字 char token[20];//存放字符(单词) //判断关键字 int isKey(char s[]){for(int i = 0; i<6;i++){if(strcmp(s,key[i]) == 0){return i+1;//关键字的种别码依次为 begin=1,if=2,then=3,while=4,do=5,end=6即为 i+1 的值 }}return -1;}//判断是不是字母 bool isChar(char ch){if((ch>='a' && ch<='z') || (ch>='A' && ch<='Z'))return true;else return false;}//判断是不是数字 bool isNum(char ch){if(ch>='0' && ch<='9')return true;elsereturn false;}//核心子程序void scanner(int &syn,int &p,char s[]){int count = 0;if(s[p] == ' ') p++;//开头是字母if(isChar(s[p])){while(isNum(s[p]) || isChar(s[p])){token[count++] = s[p];p++;}token[count] = ' ';//' '作为结束符 ,将单词分隔开 syn = isKey(token);if(syn == -1){syn = 10;//标识符letter(letter|digit) *}}//开头是数字else if(isNum(s[p])){while(isNum(s[p])){token[count++] = s[p];p++;}token[count] = ' ';//结束标识 syn = 11;//数字digit(digit) *}//如果是运算符或者界符else{//先处理没有争议的字符 switch(s[p]){case '+': syn = 13;token[0] = s[p];token[1]=' ';break;case '-': syn = 14;token[0] = s[p];token[1]=' ';break;case '*': syn = 15;token[0] = s[p];token[1]=' ';break;case '/': syn = 16;token[0] = s[p];token[1]=' ';break;case '=': syn = 25;token[0] = s[p];token[1]=' ';break;case ';': syn = 26;token[0] = s[p];token[1]=' ';break;case '(': syn = 27;token[0] = s[p];token[1]=' ';break;case ')': syn = 28;token[0] = s[p];token[1]=' ';break;case '#': syn = 0 ;token[0] = s[p];token[1]=' ';break;}//处理有争议的//: :=if(s[p] == ':'){token[count++] = s[p];if(s[p+1] == '='){p++;token[count++] = s[p];syn = 18;}else{syn = 17;}token[count] = ' ';}//< <> <=if(s[p] == '<'){token[count++] = s[p];if(s[p+1] == '>'){p++;token[count++] = s[p];syn = 21;}else if(s[p+1] == '='){p++;token[count++] = s[p];syn = 22;}else{syn = 20;}token[count] = ' ';}//> >=if(s[p] == '>'){token[count++] = s[p];if(s[p+1] == '='){p++;token[count++] = s[p];syn = 24;}else{syn = 23;}token[count] = ' ';}//后移 p++;//判断运算符和界符的这部分由于指针 p 没有向后指,所以需要将指针 p 向后移一位 } } int main(){char s[100];//输入字符串 while(cin>>s){int p = 0;int syn;while(p < strlen(s))//循环条件 ,p还未指到字符串最后{scanner(syn,p,s);cout<<'<'<<token<<','<<syn<<'>'<<endl;}}return 0;}输入begin x:=9: if x>9 then x:=2*x+1/3; end #
运行结果为: