不用自动机
没怎么测试,只测试了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;
//跳回步骤0
step0(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());
}