编译原理课作业要求自己写一个词法分析器,我尝试写了一下。
词法分析:计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫作词法分析器(Lexical analyzer),也叫扫描器(Scanner)。词法分析器一般以函数的形式存在,供语法分析器调用。 完成词法分析任务的程序称为词法分析程序或词法分析器或扫描器。完成词法分析任务的程序称为词法分析程序或词法分析器或扫描器。从左至右地对源程序进行扫描,按照语言的词法规则识别各类单词,并产生相应单词的属性字。
词法分析是编译器对源代码进行编译处理的第一步。编写指定程序语言的词法分析器需要构造相应的有限自动机,然后根据其编写。
目标:对下面的一段程序进行语法分析,输出分词。
var n, f; begin n := 0; f := 1; while n # 10 do begin n := n + 1; f := f * n; end; call print; end.
有限自动机在纸上手画的,这个语言的词法比较简单,算符界符表,保留字表比较少,我直接写到代码里了(*^▽^*)
#include<iostream> #include <fstream> #include <cassert> using namespace std; bool IsDigit(char ch); bool IsLetter(char ch); int Reserve(string s); int main(){ ifstream infile; //文件输入流 string file; //文件路径 int code; // char ch; // string strToken ; //字符串 cout<<"源程序路径:"<<endl; cin>>file; infile.open(file.data()); //将文件流对象与文件连接起来 assert(infile.is_open()); //若失败,则输出错误消息,并终止程序运行 infile >> noskipws ;//noskipws:no skip whitespace 不跳过空格回车 infile>>ch; while(!infile.eof()){ strToken = ""; while(ch==' '||ch==' '||ch==' '){ if(infile.eof()) break; infile>>ch;//若是空白字符跳过 } if(IsLetter(ch))//进入字母状态 { while((IsLetter(ch)||IsDigit(ch))) { strToken.append(1,ch); infile>>ch; } code = Reserve(strToken);//查询保留字 if(code==0) //不是保留字 { cout<<"< "<<strToken<<" , 标识符 >"<<endl; } else { cout<<"< "<<strToken<<" , 保留字 >"<<endl; } continue; } else if(IsDigit(ch))//进入数字状态 { while(IsDigit(ch)){ strToken.append(1,ch); infile>>ch; } cout<<"< "<<strToken<<" , 常量 >"<<endl; continue; } else if(ch == '+') cout<<"< + , 算符 >"<<endl; else if(ch == '-') cout<<"< - , 算符 >"<<endl; else if(ch == '*') cout<<"< * , 算符 >"<<endl; else if(ch == '/') cout<<"< / , 算符 >"<<endl; else if(ch == '<') cout<<"< < , 算符 >"<<endl; else if(ch == '>') cout<<"< > , 算符 >"<<endl; else if(ch == ':') { infile>>ch; if(ch == '=') cout<<"< := , 算符 >"<<endl; else cout<<"Error :"<<ch<<endl; } else if(ch == 0x23) cout<<"<# ; , 界符 >"<<endl; else if(ch == 0x28) cout<<"< ( , 界符 >"<<endl; else if(ch == 0x29) cout<<"< ) , 界符 >"<<endl; else if(ch == 0x2c) cout<<"< , , 界符 >"<<endl; else if(ch == 0x2e) cout<<"< . , 界符 >"<<endl; else if(ch == 0x3b) cout<<"< ; , 界符 >"<<endl; else if(ch==' '||ch==' '||ch==' ') continue; else cout<<"Error :"<<ch<<endl; infile>>ch; if(infile.eof()) break; } infile.close();//关闭文件输入流 return 0; } bool IsDigit(char ch) { if(ch>='0'&&ch<='9') return true; else return false; } bool IsLetter(char ch) { if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) return true; else return false; } int Reserve(string s) { if(s == "begin") return 1; else if(s == "call") return 2; else if(s == "const") return 3; else if(s == "do") return 4; else if(s == "end") return 5; else if(s == "if") return 6; else if(s == "odd") return 7; else if(s == "procedure") return 8; else if(s == "then") return 9; else if(s == "var") return 10; else if(s == "while") return 11; else return 0; }
最后的输出:
