- 在文件指针指向EOF时,seekg()函数已经不好用了,可以in.clear()清除流,或者找别的方法解决。
- 不要相信书上的predict集合,很多坑等着你跳。
- 使用Boost库,好多好用的轮子。
- 最好不要using namespace xxx;
- 文件用完一定要in.close(),不然就算直接打开别的文件,in这个文件指针也会有问题。
最后奉上SNL部分编译程序(MAC + XCODE + C++ + BOOST)
//
// main.cpp
// SNL
//
// Created by apple on 16/5/26.
// Copyright © 2016年 Tony_LB. All rights reserved.
// 仅仅进行词法分析,语法分析(并不生成语法树)
#include <iostream>
#include <vector>
#include <list>
#include <tuple>
#include <map>
#include <fstream>
#include <stdlib.h>
#include <regex>
#include <boost/algorithm/string.hpp>
//只用了单一命名空间
using namespace std;
typedef tuple<int, string, string> token;
ifstream codeFile;
enum state{START, INASSIGN, INCOMMENT, INNUM, INID, INCHAR, INRANGE, DONE};
vector<string> reserWord;
vector<token> tokenList;
//分析表
map<pair<string, string>, int> analysisTable;
//语法表
vector< vector<string> > grammaTable;
//记录Predict集
vector<vector<string>> predicts;
//记录行号,列号
int lines = 1, row = 0;
//初始化函数
void init(ifstream & codeFile)
{
char buffer[256];
//这个文件里放保留字,每一行放一个
ifstream in("/Users/apple/Documents/SNL/reserWord.txt");
if (! in.is_open())
{
cout << "CANT FIND reserWord.txt";
exit(-1);
}
//初始化保留字表
while (!in.eof() )
{
in.getline(buffer,256);
reserWord.push_back(buffer);
}
in.close();
string fileName;
/*cout << "请输入文件名";
cin >> fileName;*/
fileName = "/Users/apple/Documents/SNL/SCAN.txt";
codeFile.open(fileName);
if (! codeFile.is_open())
{
cout << "cant find "+ fileName << endl;
exit(-1);
}
in.close();
//初始化语法分析需要的
in.open("/Users/apple/Documents/SNL/gramma.txt");
if (! in.is_open())
{
cout << "CANT FIND gramma.txt";
exit(-1);
}
string gramma;
regex re(".* ::= .*\\s");
vector<string> icon;
string befCom;
while (!in.eof() )
{
getline(in, gramma);
if(gramma.size() <= 0)
continue;
boost::split(icon, gramma, boost::is_any_of(" "));
//带有::=
if(regex_match(gramma, re))
{
icon.erase(icon.begin());
befCom = icon[0];
}
//不带有::=
else
{
icon.erase(icon.begin(), icon.begin() + 2);
icon.insert(icon.begin(), "::=");
icon.insert(icon.begin(), befCom);
}
string::iterator it = icon[icon.size() - 1].end() - 1;
if(*it == '\r')
{
icon[icon.size() - 1].erase(it);
}
grammaTable.push_back(icon);
icon.clear();
}
in.close();
//处理predict集合
in.open("/Users/apple/Documents/SNL/predict.txt");
if (! in.is_open())
{
cout << "CANT FIND predict.txt";
exit(-