词法分析(C++实现)不使用状态机

来源:互联网 发布:java jsch jar下载 编辑:程序博客网 时间:2024/06/05 09:51

不用自动机

没怎么测试,只测试了2个文件都没问题.= =

 先是头文件


#include<string>#include<set>#include<fstream>using namespace std;class Analyse{public:Analyse();char getNowChar();char nextChar();void setNowChar(char);bool isEnd;void start();private:void step0(char);void stringStep();void charStep();void noteStep();string getRemainBlock();string getRemainLine();void digitStep();void letterStep();void signStepOrIllegal();char nowChar;ifstream *reader;string *token;static const string keyWorkStr[];static const string operaStr[];static const string specialStr[];static const set<string> *keyWork;static const set<string> *special;static const set<string> *opera;};



然后是CPP文件



#include"CompliExam.h"#include<iostream>#include<ctype.h>const string Analyse::keyWorkStr[] = {"asm","auto","bool","break","delete","case","catch","char","const","class","continue","default","do","double","else","enum","dynamic_cast","explicit","extern","float","for","goto","if","friend","inline","mutable","int","namespace","long","operator","new","register","private","protected","public","return","short","static","signed","static_cast","switch","sizeof","this","struct","template","throw","try","void","true","while","const_cast","typedef","typeid","typename","union","unsigned","using","virtual","volatile","wchar_t","export","reinterpret_cast","false",//以上为语言关键字"include","main","cin","cout","define","elif","endif","ifdef","ifndef","undef","line","error","pragma","endl","ends",//以上为预处理指令以及关键操作"assert.h","ctype.h","errno.h","float.h","iso646.h","limits.h","locale.h","math.h","setjmp.h","signal.h","stdarg.h","stddef.h","stdio.h","stdlib.h","string.h","time.h","wchar.h","wctype.h","fstream.h","iomanip.h","iostream.h","vector","complex.h","queue","stack","set","istream","iostream","ctype.h","algorithm","bitset","iomanip","ios","string","ostream","iterator","utility","cmath","complex","memory","map","list","fstream","exception","deque","cstring","ctime","new"//以上为常用库.不完全,超出字符串长度限制};//关键字字符串const string Analyse::operaStr[] = {"+","-","*","/","++","--","<<",">>","<",">",">=","<=","==","=","*=","+=","-=","/=","%=","&=","|=","^=","&","&&","||","!=","~","<<=",">>=","%"};//操作符字串const string Analyse::specialStr[] = {"(",")","[","]","!",":",".",",","{","}","#",";","@","?"};//特殊符号字串char Analyse::getNowChar(){return nowChar;};void Analyse::setNowChar(char c){nowChar = c;}/** *构造函数,初始化set */Analyse::Analyse(){isEnd = false;reader = NULL;token = NULL;cout<<"生成分析实例:"<<endl;}const set<string>* Analyse::keyWork = new set<string>(keyWorkStr,keyWorkStr + sizeof(Analyse::keyWorkStr) / sizeof(keyWorkStr[0]));const set<string>* Analyse::special = new set<string>(specialStr,specialStr + sizeof(specialStr) / sizeof(specialStr[0]));const set<string>* Analyse::opera = new set<string>(operaStr,operaStr + sizeof(operaStr) / sizeof(operaStr[0]));/** * 读取下一个字符,并且更新当前字符 * 读取相应输入文件,没有取默认文件 * 如果到达文件尾则将isEnd标志为true */char Analyse::nextChar(){if(reader == NULL){reader = new ifstream("Knight.cpp");}char c;if((c = reader->get()) != EOF){setNowChar(c);return c;}isEnd = true;return NULL;}/** * 接收一个字符判断: * 如果该字符是换行,空字符,制表符则忽略取下一个字符 * 程序总体把分析分成6种种类去分析,并由初始模块根据第一字符原则判断进入哪个类别,.分别是 * 1.字符串:双引号关联起来的字串 * 2.单个字符:单引号关联起来的字符 * 3.注释:行注释以及块注释 * 4.数字:自然数以及小数 * 5.文字(letter):标识符以及关键字 * 6.符号:操作符以及特殊符号或非法字符 */void Analyse::step0(char c){if(isEnd){cout<<"分析结束"<<endl;reader->close();return;}while(c == '\n' || c == ' ' || c == '' || c == '\r'){c = nextChar();}if(c == '\"'){stringStep();}else if(c == '\''){charStep();}else if(c == '/'){noteStep();}else if(isdigit(c)){digitStep();}else if(isalpha(c) || c == '_'){letterStep();}else{signStepOrIllegal();}};/** * 进入字符串步骤 * 过滤第一种缺陷情况就是"\"",但是不能过滤第二重转义字符出现的缺陷. * 因为这种情况不多,所以忽略 */void Analyse::stringStep(){token = new string("\"");char c;do{c = nextChar();token->append(1,c);if(c == '\"' && !(token->compare("\"\\\"") == 0 )){break;}}while(true);cout<<token->c_str()<<" :字符串"<<endl;step0(nextChar());}/** * 进入单字符步骤 * 可能出现转义字符打印错误,故提供一重修复. * 鉴于深层情况少见,忽略 */void Analyse::charStep(){token = new string("\'");char c;do{c = nextChar();token->append(1,c);if(c == '\'' && !(token->compare("'\\'") == 0)){break;}}while(true);cout<<token->c_str()<<" :单字符"<<endl;step0(nextChar());}/** * 进入注释步骤 * 行注释以及块注释 */void Analyse::noteStep(){token = new string("/");char c = nextChar();if(c == '/'){//行注释token->append(1,'/');token->append(getRemainLine());}else if(c == '*'){//块注释token->append(1,'*');token->append(getRemainBlock());}else{cout<<"注释代码未知情况"<<endl;}cout<<token->c_str()<<" :注释"<<endl;step0(nextChar());}/** * 返回注释块字符串 * 策略是一直扫描直到扫描到*和/符号 *  * @return String */string Analyse::getRemainBlock(){string buffer("");char c;char c2;while(true){c = nextChar();if(c == '\t')continue;buffer.append(1,c);if(c == '*'){c2 = nextChar();if(c2 == '\t')continue;if(c2 == '/'){//如果继*后的符号是斜杠,那么就退出循环buffer.append(1,c2);break;}buffer.append(1,c2);}}return buffer;}/** * 返回行注释的字符串 * 扫描策略是直接扫描直到换行符 * @return */string Analyse::getRemainLine(){string buffer("");char c;while(true){c = nextChar();if(c == '\n' || c == '\r'){break;}buffer.append(1,c);}return buffer;}/** * 进入数字过程 * 不包括正负号 * 最多只能出现一个点. */void Analyse::digitStep(){bool dot = false;token = new string(1,getNowChar());//把当前数字加入char c = nextChar();while(c == '.' || isdigit(c)){if(c == '.'){if(dot){//就是点已经出现过了break;}dot = true;}token->append(1,c);//点或者数字都加入字串c = nextChar();}cout<<token->c_str()<<" :数字"<<endl;//跳回步骤0step0(getNowChar());}/** * 进入文字过程 */void Analyse::letterStep(){bool dot = false;token = new string(1,getNowChar());//吧当前的字符串加入char c = nextChar();while(c == '_' || isdigit(c) || isalpha(c) || c == '.'){if(c == '.'){if(dot){//就是点已经出现过了break;}dot = true;}token->append(1,c);c = nextChar();}if(keyWork->find(*token) != keyWork->end()){cout<<token->c_str()<<" :关键字"<<endl;}else{cout<<token->c_str()<<" :标识符"<<endl;}step0(getNowChar());}/** * 进入符号阶段 * 在这里分别区分非法字符 * 操作符,特殊字符 */void Analyse::signStepOrIllegal(){token = new string();char c = getNowChar();string buffer(1,getNowChar());while((opera->find(buffer) != opera->end()) || (special->find(buffer) != special->end())){token->append(1,c);c = nextChar();buffer.append(1,c);}if(token->size() != 0){//非法字符if(special->find(buffer) != special->end()){cout<<token->c_str()<<" :特殊字符"<<endl;}else{cout<<token->c_str()<<" :操作符"<<endl;}}else{cout<<token->c_str()<<" :非法字符"<<endl;}step0(getNowChar());}/** * 启动分析 */void Analyse::start(){step0(nextChar());}


0 0
原创粉丝点击