编译原理:词法分析程序的设计与实现
词法分析程序(Lexical Analyzer)要求:
- 从左至右扫描构成源程序的字符流
- 识别出有词法意义的单词(Lexemes)
- 返回单词记录(单词类别,单词本身)
- 滤掉空格
- 跳过注释
- 发现词法错误
程序结构:
输入:字符流(什么输入方式,什么数据结构保存)
处理:
- 遍历(什么遍历方式)
- 词法规则
输出:单词流(什么输出形式)
- 二元组
单词类别:
- 标识符(10)
- 无符号数(11)
- 保留字(一词一码)
- 运算符(一词一码)
- 界符(一词一码)
单词符号 |
种别码 |
单词符号 |
种别码 |
begin |
1 |
: |
17 |
if |
2 |
:= |
18 |
then |
3 |
< |
20 |
while |
4 |
<= |
21 |
do |
5 |
<> |
22 |
end |
6 |
> |
23 |
l(l|d)* |
10 |
>= |
24 |
dd* |
11 |
= |
25 |
+ |
13 |
; |
26 |
– |
14 |
( |
27 |
* |
15 |
) |
28 |
/ |
16 |
# |
0 |
程序词法分析代码:
#include<stdio.h> #include<string.h> #include<stdlib.h>//关键字 string key[6]={"main","int","if","else","while","do"}; //关键字的种别码 int keyNum[6]={1,2,3,4,5,6}; //运算符和界符 string symbol[17]={"<",">","!=",">=","<=","==",",",";","(",")","{","}","+","-","*","/","="}; //char symbol[12]={\'<\',\'>\',\'!=\',\'>=\',\'<=\',\'==\',\',\',\';\',\'(\',\')\',\'{\',\'}\'}; //运算符和界符的种别码 int symbolNum[17]={7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23}; //存放文件取出的字符 string letter[1000]; //将字符转换为单词 string words[1000]; int length; //保存程序中字符的数目 int num; //判断运算符和界符 int isSymbol(string s){ int i; for(i=0;i<17;i++){ if(s==symbol[i]) return symbolNum[i]; } return 0; } //判断是否为数字 bool isNum(string s){ if(s>="0" && s<="9") return true; } //判断是否为字母 bool isLetter(string s){ if(s>="a" && s<="z") return true; } //判断是否为关键字,是返回种别码 int isKeyWord(string s){ int i; for(i=0;i<6;i++){ if(s==key[i]) return keyNum[i]; } return 0; } //返回单个字符的类型 int typeword(string str){ if(str>="a" && str<="z") // 字母 return 1; if(str>="0" && str<="9") //数字 return 2; if(str==">"||str=="="||str=="<"||str=="!"||str==","||str==";"||str=="("||str==")"||str=="{"||str=="}" ||str=="+"||str=="-"||str=="*"||str=="/") //判断运算符和界符 return 3; } string identifier(string s,int n){ int j=n+1; int flag=1; while(flag){ if(isNum(letter[j]) || isLetter(letter[j])){ s=(s+letter[j]).c_str(); if(isKeyWord(s)){ j++; num=j; return s; } j++; } else{ flag=0; } } num=j; return s; } string symbolStr(string s,int n){ int j=n+1; string str=letter[j]; if(str==">"||str=="="||str=="<"||str=="!") { s=(s+letter[j]).c_str(); j++; } num=j; return s; } string Number(string s,int n){ int j=n+1; int flag=1; while(flag){ if(isNum(letter[j])){ s=(s+letter[j]).c_str(); j++; } else{ flag=0; } } num=j; return s; } void print(string s,int n){ cout<<"("<<s<<","<<n<<")"<<endl; } //取单词 void TakeWord(){ int k; for(num=0;num<length;){ string str1,str; str=letter[num]; k=typeword(str); switch(k){ case 1: str1=identifier(str,num); if(isKeyWord(str1)) print(str1,isKeyWord(str1)); else print(str1,0); break; case 2: str1=Number(str,num); print(str1,24); break; case 3: str1=symbolStr(str,num); print(str1,isSymbol(str1)); break; } } } int main(){ char w; int i,j; freopen("test.txt","r",stdin);//读取本地文件 freopen("result.txt","w",stdout); //从控制台输出,而不是文本输出 length=0; while(cin>>w){ if(w!=\' \'){ letter[length]=w; length++; } //去掉程序中的空格 } TakeWord(); fclose(stdin);//关闭文件 fclose(stdout);//关闭文件 return 0; }
运行程序前准备一个分析文本test.txt内容如下:
int main() { int m,n; int num=0; n=10; if(n<0){ m=-n; } else{ m=n; } while(m!=0){ num=m*n; } }
执行程序会输出如下结果:
(int,2) (main,1) ((,15) (),16) ({,17) (int,2) (m,0) (,,13) (n,0) (;,14) (int,2) (num,0) (=,23) (0,24) (;,14) (n,0) (=,23) (10,24) (;,14) (if,3) ((,15) (n,0) (<,7) (0,24) (),16) ({,17) (m,0) (=,23) (-,20) (n,0) (;,14) (},18) (else,4) ({,17) (m,0) (=,23) (n,0) (;,14) (},18) (while,5) ((,15) (m,0) (!=,9) (0,24) (),16) ({,17) (num,0) (=,23) (m,0) (*,21) (n,0) (;,14) (},18) (},18)
版权声明:本文为zhif97原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。