Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
424def7590 |
|
|
@ -1,2 +1,3 @@
|
||||||
*/build/
|
*/build/
|
||||||
build/
|
build/
|
||||||
|
.vscode/settings.json
|
||||||
|
|
|
||||||
|
|
@ -4,46 +4,8 @@
|
||||||
"iterator": "cpp",
|
"iterator": "cpp",
|
||||||
"ostream": "cpp",
|
"ostream": "cpp",
|
||||||
"vector": "cpp",
|
"vector": "cpp",
|
||||||
"*.tcc": "cpp",
|
|
||||||
"iostream": "cpp",
|
|
||||||
"map": "cpp",
|
|
||||||
"array": "cpp",
|
|
||||||
"atomic": "cpp",
|
|
||||||
"cctype": "cpp",
|
|
||||||
"clocale": "cpp",
|
|
||||||
"cmath": "cpp",
|
|
||||||
"cstdarg": "cpp",
|
|
||||||
"cstddef": "cpp",
|
|
||||||
"cstdint": "cpp",
|
|
||||||
"cstdio": "cpp",
|
|
||||||
"cstdlib": "cpp",
|
|
||||||
"cstring": "cpp",
|
|
||||||
"cwchar": "cpp",
|
|
||||||
"cwctype": "cpp",
|
|
||||||
"deque": "cpp",
|
|
||||||
"unordered_map": "cpp",
|
|
||||||
"unordered_set": "cpp",
|
|
||||||
"exception": "cpp",
|
|
||||||
"algorithm": "cpp",
|
|
||||||
"memory": "cpp",
|
|
||||||
"memory_resource": "cpp",
|
|
||||||
"optional": "cpp",
|
|
||||||
"set": "cpp",
|
|
||||||
"string": "cpp",
|
|
||||||
"string_view": "cpp",
|
|
||||||
"system_error": "cpp",
|
|
||||||
"tuple": "cpp",
|
|
||||||
"type_traits": "cpp",
|
|
||||||
"utility": "cpp",
|
|
||||||
"fstream": "cpp",
|
|
||||||
"initializer_list": "cpp",
|
|
||||||
"iosfwd": "cpp",
|
|
||||||
"istream": "cpp",
|
|
||||||
"limits": "cpp",
|
|
||||||
"new": "cpp",
|
|
||||||
"sstream": "cpp",
|
"sstream": "cpp",
|
||||||
"stdexcept": "cpp",
|
"queue": "cpp",
|
||||||
"streambuf": "cpp",
|
"set": "cpp"
|
||||||
"typeinfo": "cpp"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,23 +2,26 @@ cmake_minimum_required(VERSION 3.10)
|
||||||
project(compiler-bin)
|
project(compiler-bin)
|
||||||
|
|
||||||
# 收集所有的cpp源文件
|
# 收集所有的cpp源文件
|
||||||
file(GLOB SOURCES_LL1 "LL1/src/*.cpp")
|
file(GLOB SOURCES_LL "LL1/*.cpp")
|
||||||
file(GLOB SOURCES_NFA "nfa/src/*.cpp")
|
file(GLOB SOURCES_NFA "nfa/*.cpp")
|
||||||
file(GLOB SOURCES_MAIN "main/*.cpp")
|
file(GLOB SOURCES_MAIN "main/*.cpp")
|
||||||
|
|
||||||
# 设置输出目录为 bin
|
# 设置输出目录为 bin
|
||||||
# set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
|
||||||
|
|
||||||
# 创建静态链接库
|
# 创建静态链接库
|
||||||
add_library(LL1 STATIC ${SOURCES_LL1})
|
add_library(LL STATIC ${SOURCES_LL})
|
||||||
add_library(nfa STATIC ${SOURCES_NFA})
|
add_library(nfa STATIC ${SOURCES_NFA})
|
||||||
|
|
||||||
# 添加头文件目录
|
# 添加头文件目录
|
||||||
target_include_directories(LL1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/LL1/include)
|
target_include_directories(LL PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/LL)
|
||||||
target_include_directories(nfa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/nfa/include)
|
target_include_directories(nfa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/nfa)
|
||||||
|
|
||||||
# 添加可执行文件
|
# 添加可执行文件
|
||||||
add_executable(main ${SOURCES_MAIN})
|
add_executable(main ${SOURCES_MAIN})
|
||||||
|
|
||||||
# 链接静态库
|
# 链接静态库
|
||||||
target_link_libraries(main PRIVATE LL1 nfa)
|
target_link_libraries(main PRIVATE LL nfa)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
project(LL1)
|
project(LL)
|
||||||
|
|
||||||
# 收集所有的cpp源文件
|
# 收集所有的cpp源文件
|
||||||
file(GLOB SOURCES "src/*.cpp")
|
file(GLOB SOURCES "*.cpp")
|
||||||
|
|
||||||
|
# 设置输出目录为 bin
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
# 创建静态链接库
|
# 创建静态链接库
|
||||||
add_library(LL1 STATIC ${SOURCES})
|
add_library(LL STATIC ${SOURCES})
|
||||||
|
|
||||||
# Test:添加可执行文件并链接目标库
|
|
||||||
add_executable(test_LL1 test/test_main.cpp)
|
|
||||||
target_link_libraries(test_LL1 LL1)
|
|
||||||
|
|
||||||
# 添加头文件目录
|
# 添加头文件目录
|
||||||
target_include_directories(LL PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(LL PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
cmake_minimum_required(VERSION 3.10)
|
|
||||||
project(LL)
|
|
||||||
|
|
||||||
# 收集所有的cpp源文件
|
|
||||||
file(GLOB SOURCES "*.cpp")
|
|
||||||
|
|
||||||
# 设置输出目录为 bin
|
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
|
||||||
|
|
||||||
# 创建静态链接库
|
|
||||||
add_library(LL STATIC ${SOURCES})
|
|
||||||
|
|
||||||
# 添加头文件目录
|
|
||||||
target_include_directories(LL PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
352
LL1/src/LL1.cpp
352
LL1/src/LL1.cpp
|
|
@ -1,352 +0,0 @@
|
||||||
#include <set>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <stack>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include "LL1.h"
|
|
||||||
|
|
||||||
|
|
||||||
LL1::LL1()
|
|
||||||
{
|
|
||||||
read_grammar();
|
|
||||||
|
|
||||||
init_grammar_set();
|
|
||||||
}
|
|
||||||
|
|
||||||
LL1::~LL1()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LL1::IsLL1()
|
|
||||||
{
|
|
||||||
string symbol;
|
|
||||||
vector<string> right_first = vector<string>();
|
|
||||||
vector<string> left_follow;
|
|
||||||
for (int i = 0; i < grammar_rules.size(); i++) {
|
|
||||||
symbol.clear();
|
|
||||||
right_first.clear();
|
|
||||||
left_follow.clear();
|
|
||||||
|
|
||||||
symbol = grammar_rules[i].first;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 计算 产生式左侧 FOLLOW 集
|
|
||||||
left_follow = follow[symbol];
|
|
||||||
|
|
||||||
// 计算 产生式右侧 FIRST 集
|
|
||||||
|
|
||||||
// 对 X1 的 非 $ 符号 加入
|
|
||||||
for (int j = 0; j < first[grammar_rules[i].second[0]].size(); j++) {
|
|
||||||
if (first[grammar_rules[i].second[0]][j] == "$") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
right_first.push_back(first[grammar_rules[i].second[0]][j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cnt;
|
|
||||||
for (cnt = 1; cnt < grammar_rules[i].second.size(); cnt++) {
|
|
||||||
|
|
||||||
// 当且仅当 有 $ 符号时 继续加入
|
|
||||||
if (!infer_empty[grammar_rules[i].second[cnt - 1]]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < first[grammar_rules[i].second[cnt]].size(); j++) {
|
|
||||||
if (first[grammar_rules[i].second[cnt]][j] == "$") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
right_first.push_back(first[grammar_rules[i].second[cnt]][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若都能推导至 $ 符号时 加入
|
|
||||||
if (cnt == grammar_rules[i].second.size() && infer_empty[grammar_rules[i].second[0]]) {
|
|
||||||
right_first.push_back("$");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对产生式右侧 FIRST 集 进行 去重
|
|
||||||
set<string> sright_first(right_first.begin(), right_first.end());
|
|
||||||
right_first.clear();
|
|
||||||
right_first.resize(sright_first.size());
|
|
||||||
right_first.assign(sright_first.begin(), sright_first.end());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
vector<string> symbol_select;
|
|
||||||
|
|
||||||
// 若产生式右侧 FIRST 集为 {$} 时
|
|
||||||
if (right_first.size() == 1 && right_first[0] == "$") {
|
|
||||||
|
|
||||||
// SELECT 集为 产生式右侧 FOLLOW 集 与 {$} 的交集
|
|
||||||
symbol_select = left_follow;
|
|
||||||
if (find(left_follow.begin(), left_follow.end(), "$") == left_follow.end()) {
|
|
||||||
symbol_select.push_back("$");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// SELECT 集为 产生式左侧 FIRST 集
|
|
||||||
symbol_select = right_first;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对 SELECT 集 进行排序 方便接下来进行集合运算
|
|
||||||
sort(symbol_select.begin(), symbol_select.end());
|
|
||||||
|
|
||||||
vector<string> new_select = vector<string>();
|
|
||||||
|
|
||||||
// 判断 SELECT 表中有无现有数据
|
|
||||||
if (select.find(symbol) == select.end()) {
|
|
||||||
|
|
||||||
select[symbol] = symbol_select;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
// 判断两个相同产生式左侧 SELECT 集 是否相交
|
|
||||||
set_intersection(symbol_select.begin(), symbol_select.end(), select[symbol].begin(), select[symbol].end(), back_inserter(new_select));
|
|
||||||
|
|
||||||
if (new_select.size() == 0) {
|
|
||||||
// 不相交,继续运算,存入两者并集
|
|
||||||
set_union(symbol_select.begin(), symbol_select.end(), select[symbol].begin(), select[symbol].end(), back_inserter(new_select));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 非 LL(1) 文法,退出
|
|
||||||
cout << "This grammar is not LL (1) grammar" << endl;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// cout << "该文法为 LL(1) 文法!" << endl;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LL1::build_LL1_predict()
|
|
||||||
{
|
|
||||||
// 对每一个 非终结符 进行初始化行
|
|
||||||
for (int i = 0; i < VNs.size(); i++) {
|
|
||||||
if (LL1_predict.find(VNs[i]) == LL1_predict.end()) {
|
|
||||||
LL1_predict[VNs[i]] = unordered_map<string, int>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string symbol;
|
|
||||||
vector<string> right_first = vector<string>();
|
|
||||||
vector<string> left_follow;
|
|
||||||
|
|
||||||
// 遍历 产生式 构建 预测分析表
|
|
||||||
for (int i = 0; i < grammar_rules.size(); i++) {
|
|
||||||
symbol.clear();
|
|
||||||
right_first.clear();
|
|
||||||
left_follow.clear();
|
|
||||||
|
|
||||||
symbol = grammar_rules[i].first;
|
|
||||||
|
|
||||||
|
|
||||||
// 计算 产生式左侧 FOLLOW 集
|
|
||||||
left_follow = follow[symbol];
|
|
||||||
|
|
||||||
unordered_map<string, int> &symbol_predict = LL1_predict[symbol];
|
|
||||||
|
|
||||||
|
|
||||||
// 计算 产生式右侧 FIRST 集
|
|
||||||
|
|
||||||
// 对 X1 的 非 $ 符号 加入
|
|
||||||
for (int j = 0; j < first[grammar_rules[i].second[0]].size(); j++) {
|
|
||||||
if (first[grammar_rules[i].second[0]][j] == "$") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
right_first.push_back(first[grammar_rules[i].second[0]][j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
int cnt;
|
|
||||||
for (cnt = 1; cnt < grammar_rules[i].second.size(); cnt++) {
|
|
||||||
|
|
||||||
// 当且仅当 有 $ 符号时 继续加入
|
|
||||||
if (!infer_empty[grammar_rules[i].second[cnt - 1]]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
for (int j = 0; j < first[grammar_rules[i].second[cnt]].size(); j++) {
|
|
||||||
if (first[grammar_rules[i].second[cnt]][j] == "$") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
right_first.push_back(first[grammar_rules[i].second[cnt]][j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若都能推导至 $ 符号时 加入
|
|
||||||
if (cnt == grammar_rules[i].second.size() && infer_empty[grammar_rules[i].second[0]]) {
|
|
||||||
right_first.push_back("$");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对产生式右侧 FIRST 集 进行 去重
|
|
||||||
set<string> sright_first(right_first.begin(), right_first.end());
|
|
||||||
right_first.clear();
|
|
||||||
right_first.resize(sright_first.size());
|
|
||||||
right_first.assign(sright_first.begin(), sright_first.end());
|
|
||||||
|
|
||||||
// 循环遍历 FIRST 集进行初始化
|
|
||||||
for (int j = 0; j < right_first.size(); j++) {
|
|
||||||
if (right_first[j] == "$") {
|
|
||||||
pair<string, vector<string>> new_rule (grammar_rules[i].first, vector<string>());
|
|
||||||
new_rule.second.push_back("$");
|
|
||||||
int rule_id = insert_rule(new_rule);
|
|
||||||
|
|
||||||
for (int k = 0; k < left_follow.size(); k++) {
|
|
||||||
symbol_predict[left_follow[k]] = rule_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
symbol_predict[right_first[j]] = i;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void LL1::print_LL1_predict()
|
|
||||||
{
|
|
||||||
cout << "[LL1_predict]:" << endl;
|
|
||||||
for (auto iter = LL1_predict.begin(); iter != LL1_predict.end(); ++iter) {
|
|
||||||
cout << (*iter).first << " ";
|
|
||||||
for (auto j = (*iter).second.begin(); j != (*iter).second.end(); ++j) {
|
|
||||||
cout << (*j).first << "," << (*j).second << " ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void LL1::build_LL1_grammar()
|
|
||||||
{
|
|
||||||
// 符号栈
|
|
||||||
stack<string> stack;
|
|
||||||
int token_cnt = 0;
|
|
||||||
|
|
||||||
// 起始符 入栈
|
|
||||||
stack.push(start);
|
|
||||||
|
|
||||||
while (!stack.empty())
|
|
||||||
{
|
|
||||||
LL1_grammar_log.push_back(string());
|
|
||||||
|
|
||||||
// 栈顶符号
|
|
||||||
// 判断栈顶是否为 空符号
|
|
||||||
if (stack.top() == "$") {
|
|
||||||
// 栈空 以 EOF 表示
|
|
||||||
LL1_grammar_log.back() += "EOF";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LL1_grammar_log.back() += stack.top();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加 # 分割
|
|
||||||
LL1_grammar_log.back() += "#";
|
|
||||||
|
|
||||||
// 面临输入的符号
|
|
||||||
string this_token;
|
|
||||||
if (token_cnt == token_strings.size()) {
|
|
||||||
// 栈空 以 EOF 表示
|
|
||||||
this_token = "$";
|
|
||||||
LL1_grammar_log.back() += "EOF";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this_token = token_strings[token_cnt];
|
|
||||||
LL1_grammar_log.back() += token_strings[token_cnt];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对栈顶元素与即将输入的符号进行比较
|
|
||||||
if (stack.top() == this_token) {
|
|
||||||
// 栈顶出栈 token 指向下一位
|
|
||||||
token_cnt++;
|
|
||||||
stack.pop();
|
|
||||||
|
|
||||||
if (this_token == "$") {
|
|
||||||
// 分析成功 结束分析
|
|
||||||
LL1_grammar_log.back() += "\taccept";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// 跳过
|
|
||||||
LL1_grammar_log.back() += "\tmove";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 若为终结符
|
|
||||||
else if (find(VTs.begin(), VTs.end(), stack.top()) != VTs.end()) {
|
|
||||||
if (stack.top() == "$") {
|
|
||||||
stack.pop();
|
|
||||||
LL1_grammar_log.pop_back();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
LL1_grammar_log.back() += "\terror";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto tab = LL1_predict[stack.top()];
|
|
||||||
|
|
||||||
if (tab.find(this_token) == tab.end()) {
|
|
||||||
LL1_grammar_log.back() += "\terror";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto this_rule = grammar_rules[tab[this_token]];
|
|
||||||
stack.pop();
|
|
||||||
for (int i = this_rule.second.size() - 1; i >= 0; i--) {
|
|
||||||
stack.push(this_rule.second[i]);
|
|
||||||
}
|
|
||||||
LL1_grammar_log.back() += "\treduction";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void LL1::print_LL1_grammar_log()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < LL1_grammar_log.size(); ++i) {
|
|
||||||
cout << LL1_grammar_log[i] << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void LL1::fileout_LL1_grammar_log(string file_name)
|
|
||||||
{
|
|
||||||
//打开结果输出文件
|
|
||||||
fstream outfile(file_name);
|
|
||||||
|
|
||||||
if (!outfile.is_open()) {
|
|
||||||
cout << "[FILEOUT] fail to open file" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < LL1_grammar_log.size(); ++i) {
|
|
||||||
outfile << LL1_grammar_log[i] << endl;
|
|
||||||
}
|
|
||||||
outfile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
int LL1::insert_rule(pair<string, vector<string>>& new_rule)
|
|
||||||
{
|
|
||||||
int cnt;
|
|
||||||
for (cnt = 0; cnt < grammar_rules.size(); cnt++) {
|
|
||||||
// 当 产生式规则 中存在这条产生式时 返回序号
|
|
||||||
if (grammar_rules[cnt].first == new_rule.first && grammar_rules[cnt].second == new_rule.second) {
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 若不存在 返回序号的同时加入
|
|
||||||
grammar_rules.push_back(new_rule);
|
|
||||||
return cnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,524 +0,0 @@
|
||||||
#include <deque>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
#include "grammar.h"
|
|
||||||
|
|
||||||
|
|
||||||
Grammar::Grammar()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Grammar::~Grammar()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Grammar::read_grammar() {
|
|
||||||
fstream infile;
|
|
||||||
infile.open(grammar_file,ios::in);
|
|
||||||
if (!infile.is_open())
|
|
||||||
{
|
|
||||||
cout << "[READ_GRAMMAR] fail to open file: "<< grammar_file << endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
string buf;
|
|
||||||
string arrow = "->";
|
|
||||||
string farrow;
|
|
||||||
bool start_flag = true;
|
|
||||||
string left;
|
|
||||||
string forms;
|
|
||||||
|
|
||||||
while (!infile.eof()) {
|
|
||||||
// 清理 string
|
|
||||||
buf.clear();
|
|
||||||
left.clear();
|
|
||||||
forms.clear();
|
|
||||||
farrow.clear();
|
|
||||||
|
|
||||||
|
|
||||||
grammar_rules.push_back(pair<string, vector<string>>());
|
|
||||||
getline(infile, buf);
|
|
||||||
|
|
||||||
stringstream ss(buf);
|
|
||||||
|
|
||||||
// 读取产生式左侧
|
|
||||||
ss >> left;
|
|
||||||
grammar_rules.back().first = left;
|
|
||||||
symbols.push_back(left);
|
|
||||||
VNs.push_back(left);
|
|
||||||
|
|
||||||
// 存储 start
|
|
||||||
if (start_flag) {
|
|
||||||
start = left;
|
|
||||||
start_flag = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取 -> 符号 并保证合法
|
|
||||||
ss >> farrow;
|
|
||||||
if (farrow != arrow) {
|
|
||||||
cout << "Grammar reading error" << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取产生式右侧
|
|
||||||
while (ss >> forms)
|
|
||||||
{
|
|
||||||
grammar_rules.back().second.push_back(forms);
|
|
||||||
symbols.push_back(forms);
|
|
||||||
forms.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 符号集 和 非终结符 去重
|
|
||||||
set<string> ssymbols(symbols.begin(), symbols.end());
|
|
||||||
symbols.clear();
|
|
||||||
symbols.resize(ssymbols.size());
|
|
||||||
symbols.assign(ssymbols.begin(), ssymbols.end());
|
|
||||||
|
|
||||||
set<string> sVNs(VNs.begin(), VNs.end());
|
|
||||||
VNs.clear();
|
|
||||||
VNs.resize(sVNs.size());
|
|
||||||
VNs.assign(sVNs.begin(), sVNs.end());
|
|
||||||
|
|
||||||
// 符号集 和 非终结符 排序 以保证差集的成功
|
|
||||||
sort(symbols.begin(), symbols.end());
|
|
||||||
sort(VNs.begin(), VNs.end());
|
|
||||||
|
|
||||||
// 取差集 得到终极符
|
|
||||||
set_difference(symbols.begin(), symbols.end(), VNs.begin(), VNs.end(), back_inserter(VTs));
|
|
||||||
|
|
||||||
infile.close();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::print_grammar()
|
|
||||||
{
|
|
||||||
cout << "[start]: " << endl << start << endl << endl;
|
|
||||||
|
|
||||||
cout << "[VTs]:" << endl;
|
|
||||||
for (int i = 0; i < VTs.size(); i++) {
|
|
||||||
cout << VTs[i] << " ";
|
|
||||||
if (((i + 1) % 5) == 0)
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
cout << "[VNs]:" << endl;
|
|
||||||
for (int i = 0; i < VNs.size(); i++) {
|
|
||||||
cout << VNs[i] << " ";
|
|
||||||
if (((i + 1) % 5) == 0)
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
cout << "[symbols]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << symbols[i] << " ";
|
|
||||||
if (((i + 1) % 5) == 0)
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
cout << "[grammar_rules]: " << grammar_rules.size() << endl;
|
|
||||||
for (int i = 0; i < grammar_rules.size(); ++i) {
|
|
||||||
cout << grammar_rules[i].first << " -> ";
|
|
||||||
for (int j = 0; j < grammar_rules[i].second.size(); ++j) {
|
|
||||||
cout << "\"" << grammar_rules[i].second[j] << "\" ";
|
|
||||||
}
|
|
||||||
cout << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::expand_grammar()
|
|
||||||
{
|
|
||||||
string new_start = start + "\'";
|
|
||||||
pair<string, vector<string>> new_rule = pair<string, vector<string>>(new_start, vector<string>());
|
|
||||||
new_rule.second.push_back(start);
|
|
||||||
|
|
||||||
VNs.push_back(new_start);
|
|
||||||
symbols.push_back(new_start);
|
|
||||||
grammar_rules.insert(grammar_rules.begin(), new_rule);
|
|
||||||
start = new_start;
|
|
||||||
|
|
||||||
// 符号集排序
|
|
||||||
sort(symbols.begin(), symbols.end());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::init_grammar_set()
|
|
||||||
{
|
|
||||||
string symbol;
|
|
||||||
|
|
||||||
//system("pause");
|
|
||||||
// 对符号集中各符号进行推导 是否可以到达 $ 空符号
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
symbol = symbols[i];
|
|
||||||
this->symbol_infer_empty(symbol);
|
|
||||||
symbol.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
//system("pause");
|
|
||||||
// 初始化符号在产生式的 出现 依赖 情况
|
|
||||||
init_appears_depend();
|
|
||||||
|
|
||||||
// 对符号集中各符号进行推导 FIRST 集
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
symbol = symbols[i];
|
|
||||||
this->symbol_infer_first(symbol);
|
|
||||||
symbol.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对符号集中各符号进行推导 FOLLOW 集
|
|
||||||
|
|
||||||
// 符号队列
|
|
||||||
deque<string> queue;
|
|
||||||
|
|
||||||
// 初次遍历所有符号 生成初始的 FOLLOW 集
|
|
||||||
|
|
||||||
|
|
||||||
// 构建 start 的 FOLLOW 集
|
|
||||||
follow[start] = this->symbol_infer_follow(start);
|
|
||||||
follow[start].push_back("$");
|
|
||||||
queue.push_back(start);
|
|
||||||
|
|
||||||
|
|
||||||
// 构建除 start 的 FOLLOW 集
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
symbol = symbols[i];
|
|
||||||
if (symbol == start) {
|
|
||||||
symbol.clear();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
follow[symbol] = this->symbol_infer_follow(symbol);
|
|
||||||
queue.push_back(symbol);
|
|
||||||
symbol.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对 符号队列 进行进一步生成
|
|
||||||
while (!queue.empty()) {
|
|
||||||
// 读取 符号队列 开头
|
|
||||||
symbol = queue.front();
|
|
||||||
queue.pop_front();
|
|
||||||
|
|
||||||
// 若 FOLLOW 集发生改变
|
|
||||||
vector<string> new_symbol_follow = this->symbol_infer_follow(symbol);
|
|
||||||
if (follow[symbol].size() < new_symbol_follow.size()) {
|
|
||||||
// 对依赖 该符号 的所有符号添加至 符号队列
|
|
||||||
vector<string> dep = depend[symbol];
|
|
||||||
for (int i = 0; i < dep.size(); i++) {
|
|
||||||
queue.push_back(dep[i]);
|
|
||||||
}
|
|
||||||
follow[symbol] = new_symbol_follow;
|
|
||||||
}
|
|
||||||
symbol.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::print_grammar_set()
|
|
||||||
{
|
|
||||||
// 打印符号在产生式的出现情况
|
|
||||||
cout << "[left_appears]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << "LEFT( " << symbols[i] << " ) = {";
|
|
||||||
for (int j = 0; j < left_appears[symbols[i]].size(); j++) {
|
|
||||||
cout << " " << left_appears[symbols[i]][j] << " ";
|
|
||||||
}
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
cout << "[right_appears]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << "RIGHT( " << symbols[i] << " ) = {";
|
|
||||||
for (int j = 0; j < right_appears[symbols[i]].size(); j++) {
|
|
||||||
cout << " " << right_appears[symbols[i]][j] << " ";
|
|
||||||
}
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
// 打印 FOLLOW 集的依赖关系
|
|
||||||
cout << "[depend]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << "DEPEND( " << symbols[i] << " ) = {";
|
|
||||||
for (int j = 0; j < depend[symbols[i]].size(); j++) {
|
|
||||||
cout << " " << depend[symbols[i]][j] << " ";
|
|
||||||
}
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
|
|
||||||
// 打印是否可以推导出 $ 空符号
|
|
||||||
cout << "[infer_empty]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << symbols[i]<<" -> " << infer_empty[symbols[i]] << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
// 打印 FIRST 集
|
|
||||||
cout << "[FIRST]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << "FIRST( " << symbols[i] << " ) = {";
|
|
||||||
for (int j = 0; j < first[symbols[i]].size(); j++) {
|
|
||||||
cout << " " << first[symbols[i]][j] << " ";
|
|
||||||
}
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
// 打印 FOLLOW 集
|
|
||||||
cout << "[FOLLOW]:" << endl;
|
|
||||||
for (int i = 0; i < symbols.size(); i++) {
|
|
||||||
cout << "FOLLOW( " << symbols[i] << " ) = {";
|
|
||||||
for (int j = 0; j < follow[symbols[i]].size(); j++) {
|
|
||||||
cout << " " << follow[symbols[i]][j] << " ";
|
|
||||||
}
|
|
||||||
cout << "}" << endl;
|
|
||||||
}
|
|
||||||
cout << endl << endl;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::get_token_strings(vector<string>& my_token_strings)
|
|
||||||
{
|
|
||||||
token_strings.resize(my_token_strings.size());
|
|
||||||
token_strings.assign(my_token_strings.begin(), my_token_strings.end());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::print_token_strings()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < token_strings.size(); i++) {
|
|
||||||
cout << token_strings[i] << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Grammar::init_appears_depend()
|
|
||||||
{
|
|
||||||
for (int k = 0; k < symbols.size(); k++) {
|
|
||||||
left_appears[symbols[k]] = vector<int>();
|
|
||||||
right_appears[symbols[k]] = vector<int>();
|
|
||||||
depend[symbols[k]] = vector<string>();
|
|
||||||
for (int i = 0; i < grammar_rules.size(); i++) {
|
|
||||||
if (grammar_rules[i].first == symbols[k]) {
|
|
||||||
// 产生式左侧相等 存入 left
|
|
||||||
left_appears[symbols[k]].push_back(i);
|
|
||||||
|
|
||||||
// 对该产生式构建依赖关系
|
|
||||||
for (int m = 0; m < grammar_rules[i].second.size(); m++) {
|
|
||||||
int n;
|
|
||||||
|
|
||||||
// 判断该产生式右侧符号是否可以推导至 $ 空符号
|
|
||||||
for (n = m + 1; n < grammar_rules[i].second.size(); n++) {
|
|
||||||
if (!infer_empty[grammar_rules[i].second[n]]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 若可以推导 按照入栈的方式依次加入
|
|
||||||
if (n == grammar_rules[i].second.size()) {
|
|
||||||
if (symbols[k] != grammar_rules[i].second[m]) {
|
|
||||||
depend[symbols[k]].push_back(grammar_rules[i].second[m]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (int j = 0; j < grammar_rules[i].second.size(); j++) {
|
|
||||||
// 产生式右侧相等 存入 left
|
|
||||||
if (grammar_rules[i].second[j] == symbols[k]) {
|
|
||||||
right_appears[symbols[k]].push_back(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Grammar::symbol_infer_empty(const string& symbol) {
|
|
||||||
|
|
||||||
// 已经进行推导过
|
|
||||||
if (infer_empty.find(symbol) != infer_empty.end()) {
|
|
||||||
return infer_empty[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当符号为终结符时,当且仅当为 $ 可以推导出 $
|
|
||||||
if (find(VTs.begin(), VTs.end(), symbol) != VTs.end()) {
|
|
||||||
infer_empty[symbol] = (symbol == "$") ;
|
|
||||||
return infer_empty[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当符号为非终结符时,通过产生式进行推导
|
|
||||||
for (int i = 0; i < grammar_rules.size(); i++) {
|
|
||||||
// 当该符号为产生式左侧时
|
|
||||||
if (grammar_rules[i].first == symbol) {
|
|
||||||
int j;
|
|
||||||
vector<string> rule_right = grammar_rules[i].second;
|
|
||||||
for (j = 0; j < rule_right.size(); j++) {
|
|
||||||
// 递归推导 产生式右侧无法推导至 $ 时
|
|
||||||
if (!(this->symbol_infer_empty(rule_right[j]))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当且仅当产生式右侧可以推导至 $ 时
|
|
||||||
if (j == rule_right.size()) {
|
|
||||||
infer_empty[symbol] = true;
|
|
||||||
return infer_empty[symbol];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当各产生式都无法推导至 $ 时,则无法推导
|
|
||||||
infer_empty[symbol] = false;
|
|
||||||
return infer_empty[symbol];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string> Grammar::symbol_infer_first(const string& symbol)
|
|
||||||
{
|
|
||||||
// 已经推导过 FIRST 集
|
|
||||||
if (first.find(symbol) != first.end()) {
|
|
||||||
return first[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string> symbol_first;
|
|
||||||
|
|
||||||
// 当符号为终结符时 FIRST 集为它本身
|
|
||||||
if (find(VTs.begin(), VTs.end(), symbol) != VTs.end()) {
|
|
||||||
symbol_first.push_back(symbol);
|
|
||||||
first[symbol] = symbol_first;
|
|
||||||
return first[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当符号为非终结符时,通过产生式进行推导
|
|
||||||
for (int i = 0; i < grammar_rules.size(); i++) {
|
|
||||||
// 当该符号为产生式左侧时
|
|
||||||
if (grammar_rules[i].first == symbol) {
|
|
||||||
int j;
|
|
||||||
for (j = 0; j < grammar_rules[i].second.size(); j++) {
|
|
||||||
|
|
||||||
// 依次添加所有产生式右侧的
|
|
||||||
vector<string> firsts = symbol_infer_first(grammar_rules[i].second[j]);
|
|
||||||
for (int k = 0; k < firsts.size(); k++) {
|
|
||||||
symbol_first.push_back(firsts[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若产生式右侧无法推导至 $ 空字符时 中断
|
|
||||||
if (!infer_empty[grammar_rules[i].second[j]]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当且仅当产生式右侧可以推导至 $ 时 将 $ 加入到 FIRST 集中
|
|
||||||
if (j == grammar_rules[i].second.size()) {
|
|
||||||
symbol_first.push_back("$");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 对当前 FIRST 集进行 去重 与 排序
|
|
||||||
set<string> ssymbol_first(symbol_first.begin(), symbol_first.end());
|
|
||||||
symbol_first.clear();
|
|
||||||
symbol_first.resize(ssymbol_first.size());
|
|
||||||
symbol_first.assign(ssymbol_first.begin(), ssymbol_first.end());
|
|
||||||
|
|
||||||
sort(symbol_first.begin(), symbol_first.end());
|
|
||||||
|
|
||||||
// 返回非终结符的 FIRST 集
|
|
||||||
first[symbol] = symbol_first;
|
|
||||||
return first[symbol];
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<string> Grammar::symbol_infer_follow(const string& symbol)
|
|
||||||
{
|
|
||||||
vector<string> symbol_follow;
|
|
||||||
|
|
||||||
// 获取该符号出现在哪些产生式右侧
|
|
||||||
vector<int> right_appear = right_appears[symbol];
|
|
||||||
for (int i = 0; i < right_appear.size(); i++) {
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
// 获取该产生式右侧的符号
|
|
||||||
vector<string> rule_right = grammar_rules[right_appear[i]].second;
|
|
||||||
|
|
||||||
// 依次遍历 该产生式右侧 至 该符号 后一位
|
|
||||||
for (cnt = 0; cnt < rule_right.size(); cnt++) {
|
|
||||||
if (rule_right[cnt] == symbol) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cnt++;
|
|
||||||
|
|
||||||
// 遍历 剩余产生式右侧
|
|
||||||
for (; cnt < rule_right.size(); cnt++) {
|
|
||||||
|
|
||||||
// 依次获取 后置元素 的 FIRST 集
|
|
||||||
vector<string> symbol_first = first[rule_right[cnt]];
|
|
||||||
|
|
||||||
// 将 该 FIRST 集 循环添加至 symbol_follow 中
|
|
||||||
for (int j = 0; j < symbol_first.size(); j++) {
|
|
||||||
symbol_follow.push_back(symbol_first[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 若不可达 $ 中断遍历
|
|
||||||
if (!infer_empty[rule_right[cnt]]) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 当剩余产生式右侧均可到达 $ 时
|
|
||||||
if (cnt == rule_right.size()) {
|
|
||||||
if (follow.find(grammar_rules[right_appear[i]].first) != follow.end()) {
|
|
||||||
|
|
||||||
// 将产生式左侧的 FOLLOW 集 加入到 当前符号的 FOLLOW 集中
|
|
||||||
vector<string> first_follow = follow[grammar_rules[right_appear[i]].first];
|
|
||||||
for (int j = 0; j < first_follow.size(); j++) {
|
|
||||||
symbol_follow.push_back(first_follow[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除不需要的 $ 空字符
|
|
||||||
auto it = remove(symbol_follow.begin(), symbol_follow.end(), "$");
|
|
||||||
auto it1 = symbol_follow.erase(it, symbol_follow.end());
|
|
||||||
|
|
||||||
|
|
||||||
// 对当前 FOLLOW 集 进行去重排序
|
|
||||||
set<string> ssymbol_follow(symbol_follow.begin(), symbol_follow.end());
|
|
||||||
symbol_follow.clear();
|
|
||||||
symbol_follow.resize(ssymbol_follow.size());
|
|
||||||
symbol_follow.assign(ssymbol_follow.begin(), ssymbol_follow.end());
|
|
||||||
|
|
||||||
sort(symbol_follow.begin(), symbol_follow.end());
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return symbol_follow;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
#include <iostream>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "grammar.h"
|
|
||||||
#include "LL1.h"
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
string inputs[] = {
|
|
||||||
"tests/00.txt",
|
|
||||||
"tests/20.txt"
|
|
||||||
};
|
|
||||||
|
|
||||||
string outputs_lexical[] = {
|
|
||||||
"tests/00_my_lexical.txt",
|
|
||||||
"tests/20_my_lexical.txt"
|
|
||||||
};
|
|
||||||
|
|
||||||
string outputs_grammar[] = {
|
|
||||||
"tests/00_my_grammar.txt",
|
|
||||||
"tests/20_my_grammar.txt",
|
|
||||||
};
|
|
||||||
|
|
||||||
// 读取文件
|
|
||||||
string readfile(const string& filename)
|
|
||||||
{
|
|
||||||
ifstream file(filename);
|
|
||||||
string content((istreambuf_iterator<char>(file)),istreambuf_iterator<char>());
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
|
|
||||||
try{
|
|
||||||
int i=0;
|
|
||||||
for (auto input : inputs) {
|
|
||||||
LL1 ll;
|
|
||||||
//ll.print_grammar_set();
|
|
||||||
|
|
||||||
string content = readfile(input);
|
|
||||||
vector<string> token_strings = recognize(minimizedDFA, content,outputs_lexical[i]);
|
|
||||||
|
|
||||||
bool flag = ll.IsLL1();
|
|
||||||
ll.build_LL1_predict();
|
|
||||||
|
|
||||||
|
|
||||||
//ll.print_LL1_predict();
|
|
||||||
ll.get_token_strings(token_strings);
|
|
||||||
|
|
||||||
|
|
||||||
ll.print_token_strings();
|
|
||||||
ll.build_LL1_grammar();
|
|
||||||
|
|
||||||
|
|
||||||
ll.fileout_LL1_grammar_log(outputs_grammar[i]);
|
|
||||||
|
|
||||||
|
|
||||||
//ll.print_LL1_grammar_log();
|
|
||||||
cout << endl;
|
|
||||||
cout<<outputs_grammar[i]<<endl;
|
|
||||||
cout<<"end"<<endl;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
cout<<"LL1 FINISH"<<endl;
|
|
||||||
}
|
|
||||||
catch(...){
|
|
||||||
cout<<"ERROR"<<endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
cout<<"SYSTEM END"<<endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(main)
|
||||||
|
|
||||||
|
file(GLOB SOURCES "*.cpp")
|
||||||
|
|
||||||
|
add_executable(main ${SOURCES})
|
||||||
|
|
||||||
|
# 链接静态库
|
||||||
|
target_link_libraries(main PRIVATE ${CMAKE_BINARY_DIR}/../../bin/LL.lib)
|
||||||
|
target_link_libraries(main PRIVATE ${CMAKE_BINARY_DIR}/../../bin/nfa.lib)
|
||||||
|
|
||||||
|
|
||||||
|
# 添加头文件目录
|
||||||
|
# target_include_directories(main PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
114
main/main.cpp
114
main/main.cpp
|
|
@ -7,80 +7,74 @@
|
||||||
#include "LL1.h"
|
#include "LL1.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
string inputs[] = {
|
|
||||||
"tests/00/00.txt",
|
|
||||||
"tests/01/01.txt",
|
|
||||||
"tests/02/02.txt",
|
|
||||||
"tests/07/07.txt",
|
|
||||||
"tests/08_err/08.txt",
|
|
||||||
"tests/10_err/10.txt",
|
|
||||||
"tests/20/20.txt"
|
|
||||||
};
|
|
||||||
|
|
||||||
string outputs_lexical[] = {
|
|
||||||
"tests/00/00_my_lexical.txt",
|
|
||||||
"tests/01/01_my_lexical.txt",
|
|
||||||
"tests/02/02_my_lexical.txt",
|
|
||||||
"tests/07/07_my_lexical.txt",
|
|
||||||
"tests/08_err/08_my_lexical.txt",
|
|
||||||
"tests/10_err/10_my_lexical.txt",
|
|
||||||
"tests/20/20_my_lexical.txt"
|
|
||||||
};
|
|
||||||
|
|
||||||
string outputs_grammar[] = {
|
|
||||||
"tests/00/00_my_grammar.txt",
|
|
||||||
"tests/01/01_my_grammar.txt",
|
|
||||||
"tests/02/02_my_grammar.txt",
|
|
||||||
"tests/07/07_my_grammar.txt",
|
|
||||||
"tests/08_err/08_my_grammar.txt",
|
|
||||||
"tests/10_err/10_my_grammar.txt",
|
|
||||||
"tests/20/20_my_grammar.txt",
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
|
NFA nfa = RexToNFA();
|
||||||
|
//printNFA(nfa);
|
||||||
|
|
||||||
NFA nfa = RexToNFA();
|
DFA dfa = nfaToDFA(nfa);
|
||||||
//printNFA(nfa);
|
//printDFA(dfa);
|
||||||
|
DFA minimizedDFA = minimizeDFA(minimizeDFA(dfa));
|
||||||
|
removeUnreachableStates(minimizedDFA);
|
||||||
|
//printDFA(minimizedDFA);
|
||||||
|
|
||||||
DFA dfa = nfaToDFA(nfa);
|
string inputs[6] = {
|
||||||
//printDFA(dfa);
|
"tests/00/00.txt",
|
||||||
DFA minimizedDFA = minimizeDFA(minimizeDFA(dfa));
|
"tests/01/01.txt",
|
||||||
removeUnreachableStates(minimizedDFA);
|
"tests/02/02.txt",
|
||||||
printDFA(minimizedDFA);
|
"tests/07/07.txt",
|
||||||
|
"tests/08_err/08.txt",
|
||||||
|
"tests/10_err/10.txt"
|
||||||
|
};
|
||||||
|
|
||||||
cout<<"DFA FINISH"<<endl;
|
string outputs_lexical[6] = {
|
||||||
int i = 0;
|
"tests/00/00_my_lexical.txt",
|
||||||
cout<<"LL1 START"<<endl;
|
"tests/01/01_my_lexical.txt",
|
||||||
for (auto input : inputs) {
|
"tests/02/02_my_lexical.txt",
|
||||||
cout<<outputs_grammar[i]<<endl;
|
"tests/07/07_my_lexical.txt",
|
||||||
LL1 ll;
|
"tests/08_err/08_my_lexical.txt",
|
||||||
//ll.print_grammar_set();
|
"tests/10_err/10_my_lexical.txt"
|
||||||
|
};
|
||||||
|
|
||||||
string content = readfile(input);
|
string outputs_grammar[6] = {
|
||||||
vector<string> token_strings = recognize(minimizedDFA, content,outputs_lexical[i]);
|
"tests/00/00_my_grammar.txt",
|
||||||
|
"tests/01/01_my_grammar.txt",
|
||||||
bool flag = ll.IsLL1();
|
"tests/02/02_my_grammar.txt",
|
||||||
ll.build_LL1_predict();
|
"tests/07/07_my_grammar.txt",
|
||||||
|
"tests/08_err/08_my_grammar.txt",
|
||||||
|
"tests/10_err/10_my_grammar.txt"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//ll.print_LL1_predict();噢
|
int i = 0;
|
||||||
ll.get_token_strings(token_strings);
|
for (auto input : inputs) {
|
||||||
|
LL1 ll;
|
||||||
|
//ll.print_grammar_set();
|
||||||
|
|
||||||
|
string content = readfile(input);
|
||||||
|
vector<string> token_strings = recognize(minimizedDFA, content,outputs_lexical[i]);
|
||||||
|
|
||||||
|
bool flag = ll.IsLL1();
|
||||||
|
ll.build_LL1_predict();
|
||||||
|
|
||||||
|
|
||||||
ll.print_token_strings();
|
//ll.print_LL1_predict();
|
||||||
ll.build_LL1_grammar();
|
ll.get_token_strings(token_strings);
|
||||||
|
|
||||||
|
|
||||||
ll.fileout_LL1_grammar_log(outputs_grammar[i]);
|
ll.print_token_strings();
|
||||||
|
ll.build_LL1_grammar();
|
||||||
|
|
||||||
|
|
||||||
//ll.print_LL1_grammar_log();
|
ll.fileout_LL1_grammar_log(outputs_grammar[i]);
|
||||||
cout << endl;
|
|
||||||
i++;
|
|
||||||
}
|
//ll.print_LL1_grammar_log();
|
||||||
cout<<"LL1 FINISH"<<endl;
|
cout << endl;
|
||||||
|
cout<<"end"<<endl;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
#pragma once
|
||||||
|
#ifndef __NFA__H__
|
||||||
|
#define __NFA__H__
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <deque>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stack>
|
||||||
|
#include <queue>
|
||||||
|
#include <algorithm>
|
||||||
|
using namespace std;
|
||||||
|
//单词符号的类型,返回<待测代码中的单词符号,WordType>
|
||||||
|
typedef enum WordType {
|
||||||
|
//当识别成标识符后,先判断是不是保留字,让后再判断IDN
|
||||||
|
KW_INT = 0, // int
|
||||||
|
KW_VOID, // void
|
||||||
|
KW_RETURN, // return
|
||||||
|
KW_CONST, // const
|
||||||
|
KW_MAIN, //main
|
||||||
|
|
||||||
|
OP_ADD, // +
|
||||||
|
OP_SUB, // -
|
||||||
|
OP_MUL, // *
|
||||||
|
OP_DIV, // /
|
||||||
|
OP_MOD, // %
|
||||||
|
OP_ASSIGN, // =
|
||||||
|
OP_GT, // >
|
||||||
|
OP_LT, // <
|
||||||
|
OP_EQ, // ==
|
||||||
|
OP_LE, // <=
|
||||||
|
OP_GE, // >=
|
||||||
|
OP_NE, // !=
|
||||||
|
OP_AND, // &&
|
||||||
|
OP_OR, // ||
|
||||||
|
|
||||||
|
SE_LBRAC, // ( left backet
|
||||||
|
SE_RBRAC, // ) right bracket
|
||||||
|
SE_LCBRAC, // { left curly bracket
|
||||||
|
SE_RCBRAC, // } right curly bracket
|
||||||
|
SE_COMMA, // ,
|
||||||
|
SE_SEMI, // ;
|
||||||
|
|
||||||
|
IDN, // [a-zA-Z][a-zA-Z_0-9]*
|
||||||
|
INT_VAL, // -*[0-9]+
|
||||||
|
UNKOWN
|
||||||
|
}WordType;
|
||||||
|
string getWordTypeName(WordType type);
|
||||||
|
//定义输入的字符类别
|
||||||
|
typedef enum InputCharType {
|
||||||
|
LETTER = 0, // 字母 0
|
||||||
|
UNDERLINE, // _ 1
|
||||||
|
DIGIT, // 数字 2 当识别成功一个数字时,为了避免出现数字01的情况,返回前先进行一个判断,对GCC,01可以识别并等于1的
|
||||||
|
//OP
|
||||||
|
ADD, // + 3
|
||||||
|
SUB, // - 4
|
||||||
|
MUL, // * 5
|
||||||
|
DIV, // / 6
|
||||||
|
MOD, // % 7
|
||||||
|
EQ, // = 8
|
||||||
|
GT, // > 9
|
||||||
|
LT, // < 10
|
||||||
|
NOT, // ! 11
|
||||||
|
AND, // & 12
|
||||||
|
OR, // | 13
|
||||||
|
//SE
|
||||||
|
LBRACKET, // ( 14
|
||||||
|
RBRACKET, // ) 15
|
||||||
|
LCBRAC, // { 16
|
||||||
|
RCBRAC, // } 17
|
||||||
|
COMMA, // , 18
|
||||||
|
SEMI, // ; 19
|
||||||
|
|
||||||
|
EPSILON, // 空字符 20
|
||||||
|
}InputCharType;
|
||||||
|
string getInputChartypeName(InputCharType type);
|
||||||
|
enum class TokenType {
|
||||||
|
KW = 0,
|
||||||
|
OP,
|
||||||
|
SE,
|
||||||
|
IDN,
|
||||||
|
INT,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
TokenType getTokenType(WordType wordType,string buffer);
|
||||||
|
typedef struct Token {
|
||||||
|
string value;
|
||||||
|
TokenType type;
|
||||||
|
} Token;
|
||||||
|
|
||||||
|
//定义函数判断输入的字符类别
|
||||||
|
InputCharType getInputCharType(char c);
|
||||||
|
string getWordTypeName(WordType type,string buffer);
|
||||||
|
string getWordAttribute(WordType type,string buffer);
|
||||||
|
|
||||||
|
//定义状态类
|
||||||
|
class State {
|
||||||
|
public:
|
||||||
|
int id; // 状态编号
|
||||||
|
map<InputCharType, set<State*>> transitions; // 转移函数映射表,记录每个输入字符类型对应的目标状态集合
|
||||||
|
bool isFinalState; // 是否为最终状态
|
||||||
|
WordType wordType; // 到达该状态时应该返回的词法单元类型
|
||||||
|
State(int id) : id(id), isFinalState(false), wordType(UNKOWN) {}
|
||||||
|
void addTransition(InputCharType input, State* targetState) {
|
||||||
|
transitions[input].insert(targetState);
|
||||||
|
}
|
||||||
|
void setFinalState(bool isFinal, WordType type) {
|
||||||
|
isFinalState = isFinal;
|
||||||
|
wordType = type;
|
||||||
|
}
|
||||||
|
bool operator<(const State& other) const {
|
||||||
|
return id < other.id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//为了是set内部有序,定义排序结构体StatePtrCompare
|
||||||
|
struct StatePtrCompare {
|
||||||
|
bool operator()(const State* lhs, const State* rhs) const {
|
||||||
|
return lhs->id < rhs->id;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//定义NFA类
|
||||||
|
class NFA {
|
||||||
|
public:
|
||||||
|
State* startState; // 起始状态
|
||||||
|
set<State*, StatePtrCompare> endStates; // 终止状态集合
|
||||||
|
set<State*, StatePtrCompare> states; // 状态集合
|
||||||
|
NFA(State* startState, set<State*, StatePtrCompare> endStates, set<State*, StatePtrCompare> states) :
|
||||||
|
startState(startState), endStates(endStates), states(states) {}
|
||||||
|
// void printNFA();
|
||||||
|
};
|
||||||
|
NFA RexToNFA();
|
||||||
|
void printNFA(const NFA& nfa);
|
||||||
|
NFA buildNFA(string filename);
|
||||||
|
NFA RexToNFA();
|
||||||
|
set<State*, StatePtrCompare> move(const set<State*, StatePtrCompare>& states, InputCharType input);
|
||||||
|
set<State*, StatePtrCompare> epsilonClosure(const set<State*, StatePtrCompare>& states);
|
||||||
|
|
||||||
|
class DFA {
|
||||||
|
public:
|
||||||
|
State* startState; // 起始状态
|
||||||
|
set<State*, StatePtrCompare> endStates; // 终止状态集合
|
||||||
|
set<State*, StatePtrCompare> states; // 状态集合
|
||||||
|
DFA(State* startState, set<State*, StatePtrCompare> endStates, set<State*, StatePtrCompare> states) :
|
||||||
|
startState(startState), endStates(endStates), states(states) {}
|
||||||
|
};
|
||||||
|
void removeUnreachableStates(DFA& dfa);
|
||||||
|
void printDFA(const DFA& dfa);
|
||||||
|
DFA nfaToDFA(const NFA& nfa);
|
||||||
|
void printDFA(const DFA& dfa);
|
||||||
|
struct SetComparator {
|
||||||
|
bool operator()(const set<State*, StatePtrCompare>& a, const set<State*, StatePtrCompare>& b) const {
|
||||||
|
if (a.size() != b.size()) {
|
||||||
|
return a.size() < b.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
vector<State*> vecA(a.begin(), a.end());
|
||||||
|
vector<State*> vecB(b.begin(), b.end());
|
||||||
|
|
||||||
|
sort(vecA.begin(), vecA.end(), [](const State* a, const State* b) { return a->id < b->id; });
|
||||||
|
sort(vecB.begin(), vecB.end(), [](const State* a, const State* b) { return a->id < b->id; });
|
||||||
|
|
||||||
|
return vecA < vecB;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
string getGrammarName(WordType type, string buffer);
|
||||||
|
DFA minimizeDFA(const DFA& dfa);
|
||||||
|
vector<string> recognize(const DFA& dfa, const string& input, const string& output);
|
||||||
|
string readfile(const string& filename);
|
||||||
|
#endif
|
||||||
|
|
@ -2,14 +2,19 @@ cmake_minimum_required(VERSION 3.10)
|
||||||
project(nfa)
|
project(nfa)
|
||||||
|
|
||||||
# 收集所有的cpp源文件
|
# 收集所有的cpp源文件
|
||||||
file(GLOB SOURCES "src/*.cpp")
|
file(GLOB SOURCES dfa.cpp nfa.cpp tool.cpp test_main.cpp)
|
||||||
|
|
||||||
|
# 设置输出目录为 bin
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
# 创建静态链接库
|
# 创建静态链接库
|
||||||
add_library(nfa STATIC ${SOURCES})
|
add_library(nfa STATIC ${SOURCES})
|
||||||
|
|
||||||
# Test:添加可执行文件并链接目标库
|
|
||||||
add_executable(test_nfa test/test_main.cpp)
|
|
||||||
target_link_libraries(test_nfa nfa)
|
|
||||||
|
|
||||||
# 添加头文件目录
|
# 添加头文件目录
|
||||||
target_include_directories(nfa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
target_include_directories(nfa PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
# 添加可执行文件
|
||||||
|
add_executable(test_nfa test_main.cpp nfa)
|
||||||
|
|
||||||
|
# 链接目标库
|
||||||
|
target_link_libraries(test_nfa nfa)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -84,7 +84,7 @@ DFA minimizeDFA(const DFA& dfa) {
|
||||||
size_t oldSize;//分割集初始大小
|
size_t oldSize;//分割集初始大小
|
||||||
do {
|
do {
|
||||||
oldSize = partitions.size();
|
oldSize = partitions.size();
|
||||||
for (InputCharType input = static_cast<InputCharType>(0); input < InputCharType::EPSILON; input = static_cast<InputCharType>(static_cast<int>(input) + 1)) {//类似于求Ia,Ib等
|
for (InputCharType input = static_cast<InputCharType>(0); input < EPSILON; input = static_cast<InputCharType>(input + 1)) {//类似于求Ia,Ib等
|
||||||
for (Partition* partition : set<Partition*>(partitions)) {//遍历现存分割的每一个割集,看是否可再分割
|
for (Partition* partition : set<Partition*>(partitions)) {//遍历现存分割的每一个割集,看是否可再分割
|
||||||
if (partition->states.size() > 1) {//为1的集合不可再分割
|
if (partition->states.size() > 1) {//为1的集合不可再分割
|
||||||
split(partition->states, input, partitions);//核心分割函数
|
split(partition->states, input, partitions);//核心分割函数
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
// 将正则表达式转换为非确定性有限自动机
|
// 将正则表达式转换为非确定性有限自动机
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include "nfa.h"
|
#include "nfa.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7,32 +11,12 @@
|
||||||
NFA RexToNFA() {
|
NFA RexToNFA() {
|
||||||
//由于里面存在||,所以不同正则间使用空格分隔代表| l代表letter,_代表下划线,0代表数字(也可以是d,但是为了使用已经有的函数),
|
//由于里面存在||,所以不同正则间使用空格分隔代表| l代表letter,_代表下划线,0代表数字(也可以是d,但是为了使用已经有的函数),
|
||||||
//[lu]代表l|u
|
//[lu]代表l|u
|
||||||
std::string rex = "+ - * / % = > < == <= >= != && || ( ) { } , ; [l_][l_0]* -?00*";
|
string rex = "+ - * / % = > < == <= >= != && || ( ) { } , ; [l_][l_0]* -?00* -?[0-9]+\\.[0-9]+";
|
||||||
|
|
||||||
//正则对应的输出(终态)
|
//下面给出正则对应的输出(终态)
|
||||||
vector<WordType> finalState = {
|
vector<WordType> finalState = {
|
||||||
WordType::OP_ADD,
|
OP_ADD, OP_SUB,OP_MUL,OP_DIV,OP_MOD,OP_ASSIGN,OP_GT,OP_LT, OP_EQ,OP_LE,OP_GE,OP_NE, OP_AND, OP_OR,SE_LBRAC, SE_RBRAC,
|
||||||
WordType::OP_SUB,
|
SE_LCBRAC,SE_RCBRAC,SE_COMMA,SE_SEMI,IDN,INT_VAL,FLOAT_CONST
|
||||||
WordType::OP_MUL,
|
|
||||||
WordType::OP_DIV,
|
|
||||||
WordType::OP_MOD,
|
|
||||||
WordType::OP_ASSIGN,
|
|
||||||
WordType::OP_GT,
|
|
||||||
WordType::OP_LT,
|
|
||||||
WordType::OP_EQ,
|
|
||||||
WordType::OP_LE,
|
|
||||||
WordType::OP_GE,
|
|
||||||
WordType::OP_NE,
|
|
||||||
WordType::OP_AND,
|
|
||||||
WordType::OP_OR,
|
|
||||||
WordType::SE_LBRAC,
|
|
||||||
WordType::SE_RBRAC,
|
|
||||||
WordType::SE_LCBRAC,
|
|
||||||
WordType::SE_RCBRAC,
|
|
||||||
WordType::SE_COMMA,
|
|
||||||
WordType::SE_SEMI,
|
|
||||||
WordType::IDN,
|
|
||||||
WordType::INT_VAL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
stringstream ss(rex);
|
stringstream ss(rex);
|
||||||
|
|
@ -50,6 +34,21 @@ NFA RexToNFA() {
|
||||||
//如获得[l_][l_0]*
|
//如获得[l_][l_0]*
|
||||||
State* currentState = startState;
|
State* currentState = startState;
|
||||||
|
|
||||||
|
cout<<target<<endl;
|
||||||
|
if (target == "-?[0-9]+\\.[0-9]+") {
|
||||||
|
// 处理浮点数
|
||||||
|
for (size_t i = 0; i < target.length(); i++) {
|
||||||
|
State* newState = new State(stateIndex++);
|
||||||
|
allStates.insert(newState);
|
||||||
|
InputCharType input = getInputCharType(target[i]);
|
||||||
|
currentState->addTransition(input, newState);
|
||||||
|
currentState = newState;
|
||||||
|
}
|
||||||
|
currentState->setFinalState(true, finalState[endStates.size()]);
|
||||||
|
endStates.insert(currentState);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < target.length();i++) {
|
for (size_t i = 0; i < target.length();i++) {
|
||||||
//创建一个新状态,startState通过输入InputCharType到达该状态
|
//创建一个新状态,startState通过输入InputCharType到达该状态
|
||||||
State* newState = new State(stateIndex++);
|
State* newState = new State(stateIndex++);
|
||||||
|
|
@ -59,7 +58,7 @@ NFA RexToNFA() {
|
||||||
//[...]构成一种输入,查看]后面是否有?或者*,来判断当前状态的构成
|
//[...]构成一种输入,查看]后面是否有?或者*,来判断当前状态的构成
|
||||||
for (i=i+1; i < target.length() && target[i] != ']'; i++) {
|
for (i=i+1; i < target.length() && target[i] != ']'; i++) {
|
||||||
InputCharType input = getInputCharType(target[i]);
|
InputCharType input = getInputCharType(target[i]);
|
||||||
if (input != InputCharType::EPSILON) {
|
if (input != EPSILON) {
|
||||||
// 添加转移函数,从当前状态向新状态转移
|
// 添加转移函数,从当前状态向新状态转移
|
||||||
currentState->addTransition(input, newState);
|
currentState->addTransition(input, newState);
|
||||||
}
|
}
|
||||||
|
|
@ -74,8 +73,8 @@ NFA RexToNFA() {
|
||||||
//创建EPSILON转移状态
|
//创建EPSILON转移状态
|
||||||
State* epsState = new State(stateIndex++);
|
State* epsState = new State(stateIndex++);
|
||||||
allStates.insert(epsState);
|
allStates.insert(epsState);
|
||||||
currentState->addTransition(InputCharType::EPSILON, epsState);
|
currentState->addTransition(EPSILON, epsState);
|
||||||
newState->addTransition(InputCharType::EPSILON, epsState);
|
newState->addTransition(EPSILON, epsState);
|
||||||
currentState = epsState;
|
currentState = epsState;
|
||||||
// 跳过'?'字符
|
// 跳过'?'字符
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -83,9 +82,9 @@ NFA RexToNFA() {
|
||||||
else if (i + 1 < target.length() && target[i + 1] == '*') {
|
else if (i + 1 < target.length() && target[i + 1] == '*') {
|
||||||
State* epsState = new State(stateIndex++);
|
State* epsState = new State(stateIndex++);
|
||||||
allStates.insert(epsState);
|
allStates.insert(epsState);
|
||||||
currentState->addTransition(InputCharType::EPSILON, epsState);
|
currentState->addTransition(EPSILON, epsState);
|
||||||
newState->addTransition(InputCharType::EPSILON, epsState);
|
newState->addTransition(EPSILON, epsState);
|
||||||
epsState->addTransition(InputCharType::EPSILON, currentState);
|
epsState->addTransition(EPSILON, currentState);
|
||||||
currentState = epsState;
|
currentState = epsState;
|
||||||
// 跳过'*'字符
|
// 跳过'*'字符
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -102,9 +101,11 @@ NFA RexToNFA() {
|
||||||
}//for
|
}//for
|
||||||
}
|
}
|
||||||
// 返回字符集合对应的NFA
|
// 返回字符集合对应的NFA
|
||||||
|
cout<<"ok"<<endl;
|
||||||
return NFA(startState, endStates, allStates);
|
return NFA(startState, endStates, allStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void printNFA(const NFA& nfa) {
|
void printNFA(const NFA& nfa) {
|
||||||
cout << "Start state: " << nfa.startState->id << endl;
|
cout << "Start state: " << nfa.startState->id << endl;
|
||||||
cout << "End states: "<<endl;
|
cout << "End states: "<<endl;
|
||||||
|
|
@ -151,7 +152,7 @@ set<State*, StatePtrCompare> epsilonClosure(const set<State*, StatePtrCompare>&
|
||||||
while (!stateStack.empty()) {
|
while (!stateStack.empty()) {
|
||||||
State* currentState = stateStack.top();
|
State* currentState = stateStack.top();
|
||||||
stateStack.pop();
|
stateStack.pop();
|
||||||
auto it = currentState->transitions.find(InputCharType::EPSILON);
|
auto it = currentState->transitions.find(EPSILON);
|
||||||
if (it != currentState->transitions.end()) {
|
if (it != currentState->transitions.end()) {
|
||||||
for (State* nextState : it->second) {
|
for (State* nextState : it->second) {
|
||||||
if (closure.find(nextState) == closure.end()) {//防止同一状态多次进栈,set自带去重
|
if (closure.find(nextState) == closure.end()) {//防止同一状态多次进栈,set自带去重
|
||||||
|
|
@ -194,7 +195,7 @@ DFA nfaToDFA(const NFA& nfa) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 遍历所有输入字符类型
|
// 遍历所有输入字符类型
|
||||||
for (int i = 0; i < static_cast<int>(InputCharType::EPSILON); i++) {
|
for (int i = 0; i < static_cast<int>(EPSILON); i++) {
|
||||||
InputCharType inputCharType = static_cast<InputCharType>(i);
|
InputCharType inputCharType = static_cast<InputCharType>(i);
|
||||||
set<State*, StatePtrCompare> nextNFAStates = epsilonClosure(move(currentNFAStates, inputCharType));
|
set<State*, StatePtrCompare> nextNFAStates = epsilonClosure(move(currentNFAStates, inputCharType));
|
||||||
if (nextNFAStates.empty()) {
|
if (nextNFAStates.empty()) {
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#ifndef __NFA__H__
|
||||||
|
#define __NFA__H__
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
@ -11,29 +14,22 @@
|
||||||
#include <stack>
|
#include <stack>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//单词符号的类型,返回<待测代码中的单词符号,WordType>
|
//单词符号的类型,返回<待测代码中的单词符号,WordType>
|
||||||
//当识别成标识符后,先判断是不是保留字,让后再判断IDN
|
// 保留关键字
|
||||||
|
typedef enum WordType {
|
||||||
// Token 类型定义
|
//当识别成标识符后,先判断是不是保留字,让后再判断IDN
|
||||||
enum class WordType {
|
|
||||||
|
|
||||||
//关键字
|
|
||||||
KW_INT = 0, // int
|
KW_INT = 0, // int
|
||||||
KW_VOID, // void
|
KW_VOID, // void
|
||||||
KW_RETURN, // return
|
KW_RETURN, // return
|
||||||
KW_CONST, // const
|
KW_CONST, // const
|
||||||
KW_MAIN, // main
|
KW_MAIN, //main
|
||||||
KW_IF, // if
|
KW_IF,
|
||||||
KW_ELSE, // else
|
KW_ELSE,
|
||||||
KW_FLOAT, // float
|
KW_FLOAT,
|
||||||
|
|
||||||
//操作符
|
|
||||||
OP_ADD, // +
|
OP_ADD, // +
|
||||||
OP_SUB, // -
|
OP_SUB, // -
|
||||||
OP_MUL, // *
|
OP_MUL, // *
|
||||||
|
|
@ -49,8 +45,6 @@ enum class WordType {
|
||||||
OP_AND, // &&
|
OP_AND, // &&
|
||||||
OP_OR, // ||
|
OP_OR, // ||
|
||||||
|
|
||||||
|
|
||||||
//界符
|
|
||||||
SE_LBRAC, // ( left backet
|
SE_LBRAC, // ( left backet
|
||||||
SE_RBRAC, // ) right bracket
|
SE_RBRAC, // ) right bracket
|
||||||
SE_LCBRAC, // { left curly bracket
|
SE_LCBRAC, // { left curly bracket
|
||||||
|
|
@ -60,13 +54,15 @@ enum class WordType {
|
||||||
|
|
||||||
IDN, // [a-zA-Z][a-zA-Z_0-9]*
|
IDN, // [a-zA-Z][a-zA-Z_0-9]*
|
||||||
INT_VAL, // -*[0-9]+
|
INT_VAL, // -*[0-9]+
|
||||||
FLOAT_VAL, // -?[0-9]+\\.[0-9]+
|
FLOAT_CONST, //[0-9]+'.'[0-9]+
|
||||||
|
|
||||||
UNKOWN
|
UNKOWN
|
||||||
};
|
}WordType;
|
||||||
|
string getWordTypeName(WordType type);
|
||||||
|
|
||||||
// 定义输入的字符类别
|
// 定义输入的字符类别
|
||||||
enum class InputCharType {
|
// 输入与实际不完全匹配
|
||||||
|
// 注意:此处定义的;和,顺序与实验指导书中不同
|
||||||
|
typedef enum InputCharType {
|
||||||
LETTER = 0, // 字母 0
|
LETTER = 0, // 字母 0
|
||||||
UNDERLINE, // _ 1
|
UNDERLINE, // _ 1
|
||||||
DIGIT, // 数字 2 当识别成功一个数字时,为了避免出现数字01的情况,返回前先进行一个判断,对GCC,01可以识别并等于1的
|
DIGIT, // 数字 2 当识别成功一个数字时,为了避免出现数字01的情况,返回前先进行一个判断,对GCC,01可以识别并等于1的
|
||||||
|
|
@ -89,10 +85,12 @@ enum class InputCharType {
|
||||||
RCBRAC, // } 17
|
RCBRAC, // } 17
|
||||||
COMMA, // , 18
|
COMMA, // , 18
|
||||||
SEMI, // ; 19
|
SEMI, // ; 19
|
||||||
POINT, // . 20 如果浮点按整数缓存判断,则将小数点作为数字类型加载,最后在缓冲区内判断
|
POINT, // .
|
||||||
|
|
||||||
|
EPSILON, // 空字符 20
|
||||||
|
}InputCharType;
|
||||||
|
string getInputChartypeName(InputCharType type);
|
||||||
|
|
||||||
EPSILON, // 空字符 21
|
|
||||||
};
|
|
||||||
|
|
||||||
// 定义 token类型
|
// 定义 token类型
|
||||||
enum class TokenType {
|
enum class TokenType {
|
||||||
|
|
@ -101,22 +99,15 @@ enum class TokenType {
|
||||||
SE,
|
SE,
|
||||||
IDN,
|
IDN,
|
||||||
INT,
|
INT,
|
||||||
FLOAT,
|
|
||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
|
TokenType getTokenType(WordType wordType,string buffer);
|
||||||
|
|
||||||
// 定义最终返回/输出的token的组成类型,包含值和类型两部分
|
// 定义最终返回的token的组成类型,包含值和类型两部分
|
||||||
class Token {
|
typedef struct Token {
|
||||||
string value;
|
string value;
|
||||||
TokenType type;
|
TokenType type;
|
||||||
};
|
} Token;
|
||||||
|
|
||||||
// 定义与名称映射
|
|
||||||
extern std::unordered_map<InputCharType, std::string> CharTypeNames;
|
|
||||||
extern std::unordered_map<WordType, std::string> WordTypeNames;
|
|
||||||
|
|
||||||
string getWordTypeName(WordType type);
|
|
||||||
string getInputChartypeName(InputCharType type);
|
|
||||||
|
|
||||||
// 定义函数判断输入的字符类别
|
// 定义函数判断输入的字符类别
|
||||||
InputCharType getInputCharType(char c);
|
InputCharType getInputCharType(char c);
|
||||||
|
|
@ -129,11 +120,10 @@ public:
|
||||||
int id; // 状态编号
|
int id; // 状态编号
|
||||||
bool isFinalState; // 是否为最终状态
|
bool isFinalState; // 是否为最终状态
|
||||||
WordType wordType; // 到达该状态时应该返回的词法单元类型
|
WordType wordType; // 到达该状态时应该返回的词法单元类型
|
||||||
|
|
||||||
map<InputCharType, set<State*>> transitions; // 转移函数映射表,记录每个输入字符类型对应的目标状态集合
|
map<InputCharType, set<State*>> transitions; // 转移函数映射表,记录每个输入字符类型对应的目标状态集合
|
||||||
|
|
||||||
// 构造函数
|
// 构造函数
|
||||||
State(int id) : id(id), isFinalState(false), wordType(WordType::UNKOWN) {}
|
State(int id) : id(id), isFinalState(false), wordType(UNKOWN) {}
|
||||||
|
|
||||||
// 添加状态转移映射
|
// 添加状态转移映射
|
||||||
void addTransition(InputCharType input, State* targetState) {
|
void addTransition(InputCharType input, State* targetState) {
|
||||||
|
|
@ -190,8 +180,6 @@ void removeUnreachableStates(DFA& dfa);
|
||||||
void printDFA(const DFA& dfa);
|
void printDFA(const DFA& dfa);
|
||||||
DFA nfaToDFA(const NFA& nfa);
|
DFA nfaToDFA(const NFA& nfa);
|
||||||
void printDFA(const DFA& dfa);
|
void printDFA(const DFA& dfa);
|
||||||
|
|
||||||
|
|
||||||
struct SetComparator {
|
struct SetComparator {
|
||||||
bool operator()(const set<State*, StatePtrCompare>& a, const set<State*, StatePtrCompare>& b) const {
|
bool operator()(const set<State*, StatePtrCompare>& a, const set<State*, StatePtrCompare>& b) const {
|
||||||
if (a.size() != b.size()) {
|
if (a.size() != b.size()) {
|
||||||
|
|
@ -211,4 +199,4 @@ string getGrammarName(WordType type, string buffer);
|
||||||
DFA minimizeDFA(const DFA& dfa);
|
DFA minimizeDFA(const DFA& dfa);
|
||||||
vector<string> recognize(const DFA& dfa, const string& input, const string& output);
|
vector<string> recognize(const DFA& dfa, const string& input, const string& output);
|
||||||
string readfile(const string& filename);
|
string readfile(const string& filename);
|
||||||
|
#endif
|
||||||
309
nfa/src/tool.cpp
309
nfa/src/tool.cpp
|
|
@ -1,309 +0,0 @@
|
||||||
#include "nfa.h"
|
|
||||||
|
|
||||||
std::unordered_map<InputCharType, std::string> CharTypeNames = {
|
|
||||||
{InputCharType::UNDERLINE, "_"},
|
|
||||||
{InputCharType::ADD, "+"},
|
|
||||||
{InputCharType::SUB, "-"},
|
|
||||||
{InputCharType::MUL, "*"},
|
|
||||||
{InputCharType::DIV, "/"},
|
|
||||||
{InputCharType::MOD, "%"},
|
|
||||||
{InputCharType::EQ, "="},
|
|
||||||
{InputCharType::GT, ">"},
|
|
||||||
{InputCharType::LT, "<"},
|
|
||||||
{InputCharType::NOT, "!"},
|
|
||||||
{InputCharType::AND, "&"},
|
|
||||||
{InputCharType::OR, "|"},
|
|
||||||
{InputCharType::LBRACKET, "("},
|
|
||||||
{InputCharType::RBRACKET, ")"},
|
|
||||||
{InputCharType::LCBRAC, "{"},
|
|
||||||
{InputCharType::RCBRAC, "}"},
|
|
||||||
{InputCharType::COMMA, ","},
|
|
||||||
{InputCharType::SEMI, ";"},
|
|
||||||
{InputCharType::POINT, "."} // 小数点
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
std::unordered_map<WordType, std::string> WordTypeNames = {
|
|
||||||
{WordType::KW_INT, "INT"}, {WordType::KW_VOID, "VOID"}, {WordType::KW_RETURN, "RETURN"},
|
|
||||||
{WordType::KW_CONST, "CONST"}, {WordType::KW_MAIN, "MAIN"}, {WordType::KW_IF, "IF"},
|
|
||||||
{WordType::KW_ELSE, "ELSE"}, {WordType::KW_FLOAT, "FLOAT"}, {WordType::OP_ADD, "+"},
|
|
||||||
{WordType::OP_SUB, "-"}, {WordType::OP_MUL, "*"}, {WordType::OP_DIV, "/"},
|
|
||||||
{WordType::OP_MOD, "%"}, {WordType::OP_ASSIGN, "="}, {WordType::OP_GT, ">"},
|
|
||||||
{WordType::OP_LT, "<"}, {WordType::OP_EQ, "=="}, {WordType::OP_LE, "<="},
|
|
||||||
{WordType::OP_GE, ">="}, {WordType::OP_NE, "!="}, {WordType::OP_AND, "&&"},
|
|
||||||
{WordType::OP_OR, "||"}, {WordType::SE_LBRAC, "("}, {WordType::SE_RBRAC, ")"},
|
|
||||||
{WordType::SE_LCBRAC, "{"}, {WordType::SE_RCBRAC, "}"}, {WordType::SE_COMMA, ","},
|
|
||||||
{WordType::SE_SEMI, ";"}, {WordType::IDN, "IDENTIFIER"}, {WordType::INT_VAL, "INTEGER"},
|
|
||||||
{WordType::FLOAT_VAL, "FLOAT"}, {WordType::UNKOWN, "UNKNOWN"}
|
|
||||||
};
|
|
||||||
//扫描,以字符的格式读入
|
|
||||||
//对于界符和部分运算符,是单个组成,即可以单独代表一个状态
|
|
||||||
InputCharType getInputCharType(char c) {
|
|
||||||
switch (c) {
|
|
||||||
case '_': return InputCharType::UNDERLINE;
|
|
||||||
case '+': return InputCharType::ADD;
|
|
||||||
case '-': return InputCharType::SUB;
|
|
||||||
case '*': return InputCharType::MUL;
|
|
||||||
case '/': return InputCharType::DIV;
|
|
||||||
case '%': return InputCharType::MOD;
|
|
||||||
case '=': return InputCharType::EQ;
|
|
||||||
case '>': return InputCharType::GT;
|
|
||||||
case '<': return InputCharType::LT;
|
|
||||||
case '!': return InputCharType::NOT;
|
|
||||||
case '&': return InputCharType::AND;
|
|
||||||
case '|': return InputCharType::OR;
|
|
||||||
case '(': return InputCharType::LBRACKET;
|
|
||||||
case ')': return InputCharType::RBRACKET;
|
|
||||||
case '{': return InputCharType::LCBRAC;
|
|
||||||
case '}': return InputCharType::RCBRAC;
|
|
||||||
case ',': return InputCharType::COMMA;
|
|
||||||
case ';': return InputCharType::SEMI;
|
|
||||||
|
|
||||||
//小数点作为数字读入
|
|
||||||
case '.': return InputCharType::DIGIT;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
|
|
||||||
return InputCharType::LETTER;
|
|
||||||
}
|
|
||||||
else if (c >= '0' && c <= '9') {
|
|
||||||
return InputCharType::DIGIT;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return InputCharType::EPSILON;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据状态获取名称
|
|
||||||
std::string getInputChartypeName(InputCharType type) {
|
|
||||||
auto it = CharTypeNames.find(type);
|
|
||||||
if (it != CharTypeNames.end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
string judeFloat(string buffer){
|
|
||||||
size_t firstDot = buffer.find('.');
|
|
||||||
size_t lastDot = buffer.rfind('.');
|
|
||||||
if (firstDot == lastDot && firstDot != std::string::npos) {
|
|
||||||
return "FLOAT";
|
|
||||||
}
|
|
||||||
else if (firstDot == std::string::npos)
|
|
||||||
{
|
|
||||||
return "INT";
|
|
||||||
}
|
|
||||||
else return "UNKNOWN";
|
|
||||||
}
|
|
||||||
|
|
||||||
//根据关键字类型获取其所属的种别
|
|
||||||
string getWordTypeName(WordType type, string buffer) {
|
|
||||||
switch (type) {
|
|
||||||
// 运算符
|
|
||||||
case WordType::OP_ADD:
|
|
||||||
case WordType::OP_SUB:
|
|
||||||
case WordType::OP_MUL:
|
|
||||||
case WordType::OP_DIV:
|
|
||||||
case WordType::OP_MOD:
|
|
||||||
case WordType::OP_ASSIGN:
|
|
||||||
case WordType::OP_GT:
|
|
||||||
case WordType::OP_LT:
|
|
||||||
case WordType::OP_EQ:
|
|
||||||
case WordType::OP_LE:
|
|
||||||
case WordType::OP_GE:
|
|
||||||
case WordType::OP_NE:
|
|
||||||
case WordType::OP_AND:
|
|
||||||
case WordType::OP_OR:
|
|
||||||
return "OP";
|
|
||||||
|
|
||||||
// 界符
|
|
||||||
case WordType::SE_LBRAC:
|
|
||||||
case WordType::SE_RBRAC:
|
|
||||||
case WordType::SE_LCBRAC:
|
|
||||||
case WordType::SE_RCBRAC:
|
|
||||||
case WordType::SE_COMMA:
|
|
||||||
case WordType::SE_SEMI:
|
|
||||||
return "SE";
|
|
||||||
|
|
||||||
// 标识符和关键字
|
|
||||||
case WordType::IDN:
|
|
||||||
if (!buffer.compare("int") ||
|
|
||||||
!buffer.compare("void") ||
|
|
||||||
!buffer.compare("const") ||
|
|
||||||
!buffer.compare("return")||
|
|
||||||
!buffer.compare("if") ||
|
|
||||||
!buffer.compare("else") ||
|
|
||||||
!buffer.compare("float")
|
|
||||||
){
|
|
||||||
return "KW";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "IDN";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 整数(添加了浮点判断)
|
|
||||||
case WordType::INT_VAL:
|
|
||||||
return judeFloat(buffer);
|
|
||||||
|
|
||||||
//浮点
|
|
||||||
// case FLOAT_VAL:
|
|
||||||
// return "FLOAT";
|
|
||||||
|
|
||||||
//default
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//根据关键字属性
|
|
||||||
string getWordAttribute(WordType type, string buffer) {
|
|
||||||
switch (type) {
|
|
||||||
// 运算符
|
|
||||||
case WordType::OP_ADD: return "6";
|
|
||||||
case WordType::OP_SUB: return "7";
|
|
||||||
case WordType::OP_MUL: return "8";
|
|
||||||
case WordType::OP_DIV: return "9";
|
|
||||||
case WordType::OP_MOD: return "10";
|
|
||||||
case WordType::OP_ASSIGN: return "11";
|
|
||||||
case WordType::OP_GT: return "12";
|
|
||||||
case WordType::OP_LT: return "13";
|
|
||||||
case WordType::OP_EQ: return "14";
|
|
||||||
case WordType::OP_LE: return "15";
|
|
||||||
case WordType::OP_GE: return "16";
|
|
||||||
case WordType::OP_NE: return "17";
|
|
||||||
case WordType::OP_AND:return "18";
|
|
||||||
case WordType::OP_OR: return "19";
|
|
||||||
|
|
||||||
// 界符
|
|
||||||
case WordType::SE_LBRAC: return "20";
|
|
||||||
case WordType::SE_RBRAC: return "21";
|
|
||||||
case WordType::SE_LCBRAC: return "22";
|
|
||||||
case WordType::SE_RCBRAC: return "23";
|
|
||||||
case WordType::SE_COMMA: return "25";
|
|
||||||
case WordType::SE_SEMI: return "24";
|
|
||||||
|
|
||||||
|
|
||||||
// 标识符和关键字
|
|
||||||
case WordType::IDN:
|
|
||||||
if (!buffer.compare("int")){
|
|
||||||
return "1";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("void")){
|
|
||||||
return "2";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("return")){
|
|
||||||
return "3";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("const")){
|
|
||||||
return "4";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("main")){
|
|
||||||
return "5";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("if")){
|
|
||||||
return "6";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("else")){
|
|
||||||
return "7";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("float")){
|
|
||||||
return "8";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 整数
|
|
||||||
case WordType::INT_VAL:
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
//浮点类型,理论不使用
|
|
||||||
case WordType::FLOAT_VAL:
|
|
||||||
return buffer;
|
|
||||||
|
|
||||||
//default
|
|
||||||
default:
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取文件
|
|
||||||
string readfile(const string& filename)
|
|
||||||
{
|
|
||||||
// 打开文件流并读取文件内容
|
|
||||||
ifstream file(filename);
|
|
||||||
|
|
||||||
// 使用istreambuf_iterator类逐字符从file中读取到content中
|
|
||||||
string content((istreambuf_iterator<char>(file)),istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
// 去掉换行符
|
|
||||||
//remove函数的作用是将字符串中的某个字符移动到字符串的末尾,并返回一个指向该字符后面位置的指针。
|
|
||||||
//erase 函数的作用是删除字符串中指定区间内的所有字符,返回修改后的字符串
|
|
||||||
//content.erase(remove(content.begin(), content.end(), '\n'), content.end());
|
|
||||||
|
|
||||||
return content;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// 获取token名称
|
|
||||||
string getWordTypeName(WordType type) {
|
|
||||||
auto it = WordTypeNames.find(type);
|
|
||||||
if (it != WordTypeNames.end()) {
|
|
||||||
return it->second;
|
|
||||||
} else {
|
|
||||||
return "UNKNOWN";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取语法名称
|
|
||||||
string getGrammarName(WordType type, string buffer) {
|
|
||||||
switch (type) {
|
|
||||||
|
|
||||||
case WordType::OP_ADD: return "+";
|
|
||||||
case WordType::OP_SUB: return "-";
|
|
||||||
case WordType::OP_MUL: return "*";
|
|
||||||
case WordType::OP_DIV: return "/";
|
|
||||||
case WordType::OP_MOD: return "%";
|
|
||||||
case WordType::OP_ASSIGN: return "=";
|
|
||||||
case WordType::OP_GT: return ">";
|
|
||||||
case WordType::OP_LT: return "<";
|
|
||||||
case WordType::OP_EQ: return "==";
|
|
||||||
case WordType::OP_LE: return "<=";
|
|
||||||
case WordType::OP_GE: return ">=";
|
|
||||||
case WordType::OP_NE: return "!=";
|
|
||||||
case WordType::OP_AND: return "&&";
|
|
||||||
case WordType::OP_OR: return "||";
|
|
||||||
|
|
||||||
case WordType::SE_LBRAC: return "(";
|
|
||||||
case WordType::SE_RBRAC: return ")";
|
|
||||||
case WordType::SE_LCBRAC: return "{";
|
|
||||||
case WordType::SE_RCBRAC: return "}";
|
|
||||||
case WordType::SE_COMMA: return ",";
|
|
||||||
case WordType::SE_SEMI: return ";";
|
|
||||||
|
|
||||||
case WordType::IDN:
|
|
||||||
if (!buffer.compare("int")) {
|
|
||||||
return "int";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("void")) {
|
|
||||||
return "void";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("return")) {
|
|
||||||
return "return";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("const")) {
|
|
||||||
return "const";
|
|
||||||
}
|
|
||||||
else if (!buffer.compare("main")) {
|
|
||||||
return "main";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return "IDN";
|
|
||||||
}
|
|
||||||
case WordType::INT_VAL: return "INT";
|
|
||||||
case WordType::FLOAT_VAL: return "FLOAT";
|
|
||||||
default: cerr << "Token Error: "<< WordTypeNames.find(type)->second << endl; exit(-1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -8,18 +8,14 @@ using namespace std;
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
|
|
||||||
NFA nfa = RexToNFA();
|
NFA nfa = RexToNFA();
|
||||||
printNFA(nfa);
|
//printNFA(nfa);
|
||||||
//cout<<"OK1"<<endl;
|
cout<<"OK1";
|
||||||
|
|
||||||
DFA dfa = nfaToDFA(nfa);
|
DFA dfa = nfaToDFA(nfa);
|
||||||
printDFA(dfa);
|
cout<<"OK2";
|
||||||
//cout<<"OK2"<<endl;
|
//printDFA(dfa);
|
||||||
|
|
||||||
system("pause");
|
|
||||||
DFA minimizedDFA = minimizeDFA(minimizeDFA(dfa));
|
DFA minimizedDFA = minimizeDFA(minimizeDFA(dfa));
|
||||||
removeUnreachableStates(minimizedDFA);
|
removeUnreachableStates(minimizedDFA);
|
||||||
printDFA(minimizedDFA);
|
//printDFA(minimizedDFA);
|
||||||
//cout<<"OK3"<<endl;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,383 @@
|
||||||
|
#include "nfa.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
扫描读入-->以字符的格式读入
|
||||||
|
对于界符和部分运算符,显然是单个组成,即可以单独代表一个状态
|
||||||
|
|
||||||
|
|
||||||
|
注意:
|
||||||
|
1.字母需要区分大小写
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 获取输入串的类型
|
||||||
|
// 单独一位的读入-->下一步标识终态
|
||||||
|
InputCharType getInputCharType(char c) {
|
||||||
|
switch (c) {
|
||||||
|
case '_': return UNDERLINE;
|
||||||
|
case '+': return ADD;
|
||||||
|
case '-': return SUB;
|
||||||
|
case '*': return MUL;
|
||||||
|
case '/': return DIV;
|
||||||
|
case '%': return MOD;
|
||||||
|
case '=': return EQ;
|
||||||
|
case '>': return GT;
|
||||||
|
case '<': return LT;
|
||||||
|
case '!': return NOT;
|
||||||
|
case '&': return AND;
|
||||||
|
case '|': return OR;
|
||||||
|
case '(': return LBRACKET;
|
||||||
|
case ')': return RBRACKET;
|
||||||
|
case '{': return LCBRAC;
|
||||||
|
case '}': return RCBRAC;
|
||||||
|
case ',': return COMMA;
|
||||||
|
case ';': return SEMI;
|
||||||
|
case '.': return POINT;
|
||||||
|
default:
|
||||||
|
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
|
||||||
|
return LETTER;
|
||||||
|
}
|
||||||
|
else if (c >= '0' && c <= '9') {
|
||||||
|
return DIGIT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return EPSILON;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据状态获取名称
|
||||||
|
string getInputChartypeName(InputCharType type) {
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case LETTER:
|
||||||
|
return "LETTER";
|
||||||
|
case UNDERLINE:
|
||||||
|
return "UNDERLINE";
|
||||||
|
case DIGIT:
|
||||||
|
return "DIGIT";
|
||||||
|
case ADD:
|
||||||
|
return "+";
|
||||||
|
case SUB:
|
||||||
|
return "-";
|
||||||
|
case MUL:
|
||||||
|
return "*";
|
||||||
|
case DIV:
|
||||||
|
return "/";
|
||||||
|
case MOD:
|
||||||
|
return "%";
|
||||||
|
case EQ:
|
||||||
|
return "=";
|
||||||
|
case GT:
|
||||||
|
return ">";
|
||||||
|
case LT:
|
||||||
|
return "<";
|
||||||
|
case NOT:
|
||||||
|
return "!";
|
||||||
|
case AND:
|
||||||
|
return "&";
|
||||||
|
case OR:
|
||||||
|
return "|";
|
||||||
|
case LBRACKET:
|
||||||
|
return "(";
|
||||||
|
case RBRACKET:
|
||||||
|
return ")";
|
||||||
|
case LCBRAC:
|
||||||
|
return "{";
|
||||||
|
case RCBRAC:
|
||||||
|
return "}";
|
||||||
|
case COMMA:
|
||||||
|
return ",";
|
||||||
|
case SEMI:
|
||||||
|
return ";";
|
||||||
|
case POINT:
|
||||||
|
return ".";
|
||||||
|
case EPSILON:
|
||||||
|
return "EPSILON";
|
||||||
|
default:
|
||||||
|
return "UNKOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据关键字类型获取其所属的种别
|
||||||
|
string getWordTypeName(WordType type, string buffer) {
|
||||||
|
switch (type) {
|
||||||
|
// 运算符
|
||||||
|
case OP_ADD:
|
||||||
|
case OP_SUB:
|
||||||
|
case OP_MUL:
|
||||||
|
case OP_DIV:
|
||||||
|
case OP_MOD:
|
||||||
|
case OP_ASSIGN:
|
||||||
|
case OP_GT:
|
||||||
|
case OP_LT:
|
||||||
|
case OP_EQ:
|
||||||
|
case OP_LE:
|
||||||
|
case OP_GE:
|
||||||
|
case OP_NE:
|
||||||
|
case OP_AND:
|
||||||
|
case OP_OR:
|
||||||
|
return "OP";
|
||||||
|
|
||||||
|
// 界符
|
||||||
|
case SE_LBRAC:
|
||||||
|
case SE_RBRAC:
|
||||||
|
case SE_LCBRAC:
|
||||||
|
case SE_RCBRAC:
|
||||||
|
case SE_COMMA:
|
||||||
|
case SE_SEMI:
|
||||||
|
return "SE";
|
||||||
|
|
||||||
|
// 标识符和关键字
|
||||||
|
case IDN:
|
||||||
|
if (!buffer.compare("int") || !buffer.compare("void") || !buffer.compare("const") || !buffer.compare("return")||!buffer.compare("main")){
|
||||||
|
return "KW";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "IDN";
|
||||||
|
}
|
||||||
|
|
||||||
|
// 整数
|
||||||
|
case INT_VAL:
|
||||||
|
return "INT";
|
||||||
|
case FLOAT_CONST:
|
||||||
|
return "FLOAT";
|
||||||
|
|
||||||
|
//default
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//根据关键字属性
|
||||||
|
string getWordAttribute(WordType type, string buffer) {
|
||||||
|
switch (type) {
|
||||||
|
// 运算符
|
||||||
|
case OP_ADD: return "6";
|
||||||
|
case OP_SUB: return "7";
|
||||||
|
case OP_MUL: return "8";
|
||||||
|
case OP_DIV: return "9";
|
||||||
|
case OP_MOD: return "10";
|
||||||
|
case OP_ASSIGN: return "11";
|
||||||
|
case OP_GT: return "12";
|
||||||
|
case OP_LT: return "13";
|
||||||
|
case OP_EQ: return "14";
|
||||||
|
case OP_LE: return "15";
|
||||||
|
case OP_GE: return "16";
|
||||||
|
case OP_NE: return "17";
|
||||||
|
case OP_AND:return "18";
|
||||||
|
case OP_OR: return "19";
|
||||||
|
|
||||||
|
// 界符
|
||||||
|
case SE_LBRAC: return "20";
|
||||||
|
case SE_RBRAC: return "21";
|
||||||
|
case SE_LCBRAC: return "22";
|
||||||
|
case SE_RCBRAC: return "23";
|
||||||
|
case SE_COMMA: return "25";
|
||||||
|
case SE_SEMI: return "24";
|
||||||
|
|
||||||
|
|
||||||
|
// 标识符和关键字
|
||||||
|
case IDN:
|
||||||
|
if (!buffer.compare("int")){
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("void")){
|
||||||
|
return "2";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("return")){
|
||||||
|
return "3";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("const")){
|
||||||
|
return "4";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("main")){
|
||||||
|
return "5";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 整数
|
||||||
|
case INT_VAL:
|
||||||
|
return buffer;
|
||||||
|
|
||||||
|
//default
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 读取文件
|
||||||
|
string readfile(const string& filename)
|
||||||
|
{
|
||||||
|
// 打开文件流并读取文件内容
|
||||||
|
ifstream file(filename);
|
||||||
|
|
||||||
|
// 使用istreambuf_iterator类逐字符从file中读取到content中
|
||||||
|
string content((istreambuf_iterator<char>(file)),istreambuf_iterator<char>());
|
||||||
|
|
||||||
|
// 去掉换行符
|
||||||
|
//remove函数的作用是将字符串中的某个字符移动到字符串的末尾,并返回一个指向该字符后面位置的指针。
|
||||||
|
//erase 函数的作用是删除字符串中指定区间内的所有字符,返回修改后的字符串
|
||||||
|
//content.erase(remove(content.begin(), content.end(), '\n'), content.end());
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取关键字的Token种类
|
||||||
|
TokenType getTokenType(WordType type,string buffer) {
|
||||||
|
switch (type) {
|
||||||
|
case OP_ADD:
|
||||||
|
case OP_SUB:
|
||||||
|
case OP_MUL:
|
||||||
|
case OP_DIV:
|
||||||
|
case OP_MOD:
|
||||||
|
case OP_ASSIGN:
|
||||||
|
case OP_GT:
|
||||||
|
case OP_LT:
|
||||||
|
case OP_EQ:
|
||||||
|
case OP_LE:
|
||||||
|
case OP_GE:
|
||||||
|
case OP_NE:
|
||||||
|
case OP_AND:
|
||||||
|
case OP_OR:
|
||||||
|
return TokenType::OP;
|
||||||
|
|
||||||
|
case SE_LBRAC:
|
||||||
|
case SE_RBRAC:
|
||||||
|
case SE_LCBRAC:
|
||||||
|
case SE_RCBRAC:
|
||||||
|
case SE_COMMA:
|
||||||
|
case SE_SEMI:
|
||||||
|
return TokenType::SE;
|
||||||
|
|
||||||
|
case IDN:
|
||||||
|
if (!buffer.compare("int") || !buffer.compare("void") || !buffer.compare("const") || !buffer.compare("return")|| !buffer.compare("main")) {
|
||||||
|
return TokenType::KW;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return TokenType::IDN;
|
||||||
|
}
|
||||||
|
|
||||||
|
case INT_VAL:
|
||||||
|
return TokenType::INT;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return TokenType::UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取token名称
|
||||||
|
string getWordTypeName(WordType type) {
|
||||||
|
switch (type) {
|
||||||
|
case KW_INT:
|
||||||
|
return "KW_INT";
|
||||||
|
case KW_VOID:
|
||||||
|
return "KW_VOID";
|
||||||
|
case KW_RETURN:
|
||||||
|
return "KW_RETURN";
|
||||||
|
case KW_CONST:
|
||||||
|
return "KW_CONST";
|
||||||
|
case KW_MAIN:
|
||||||
|
return "KW_MAIN";
|
||||||
|
case OP_ADD:
|
||||||
|
return "OP_ADD";
|
||||||
|
case OP_SUB:
|
||||||
|
return "OP_SUB";
|
||||||
|
case OP_MUL:
|
||||||
|
return "OP_MUL";
|
||||||
|
case OP_DIV:
|
||||||
|
return "OP_DIV";
|
||||||
|
case OP_MOD:
|
||||||
|
return "OP_MOD";
|
||||||
|
case OP_ASSIGN:
|
||||||
|
return "OP_ASSIGN";
|
||||||
|
case OP_GT:
|
||||||
|
return "OP_GT";
|
||||||
|
case OP_LT:
|
||||||
|
return "OP_LT";
|
||||||
|
case OP_EQ:
|
||||||
|
return "OP_EQ";
|
||||||
|
case OP_LE:
|
||||||
|
return "OP_LE";
|
||||||
|
case OP_GE:
|
||||||
|
return "OP_GE";
|
||||||
|
case OP_NE:
|
||||||
|
return "OP_NE";
|
||||||
|
case OP_AND:
|
||||||
|
return "OP_AND";
|
||||||
|
case OP_OR:
|
||||||
|
return "OP_OR";
|
||||||
|
case SE_LBRAC:
|
||||||
|
return "SE_LBRAC";
|
||||||
|
case SE_RBRAC:
|
||||||
|
return "SE_RBRAC";
|
||||||
|
case SE_LCBRAC:
|
||||||
|
return "SE_LCBRAC";
|
||||||
|
case SE_RCBRAC:
|
||||||
|
return "SE_RCBRAC";
|
||||||
|
case SE_COMMA:
|
||||||
|
return "SE_COMMA";
|
||||||
|
case SE_SEMI:
|
||||||
|
return "SE_SEMI";
|
||||||
|
case IDN:
|
||||||
|
return "IDN";
|
||||||
|
case INT_VAL:
|
||||||
|
return "INT_VAL";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取语法名称
|
||||||
|
string getGrammarName(WordType type, string buffer) {
|
||||||
|
switch (type) {
|
||||||
|
|
||||||
|
case OP_ADD: return "+";
|
||||||
|
case OP_SUB: return "-";
|
||||||
|
case OP_MUL: return "*";
|
||||||
|
case OP_DIV: return "/";
|
||||||
|
case OP_MOD: return "%";
|
||||||
|
case OP_ASSIGN: return "=";
|
||||||
|
case OP_GT: return ">";
|
||||||
|
case OP_LT: return "<";
|
||||||
|
case OP_EQ: return "==";
|
||||||
|
case OP_LE: return "<=";
|
||||||
|
case OP_GE: return ">=";
|
||||||
|
case OP_NE: return "!=";
|
||||||
|
case OP_AND: return "&&";
|
||||||
|
case OP_OR: return "||";
|
||||||
|
|
||||||
|
case SE_LBRAC: return "(";
|
||||||
|
case SE_RBRAC: return ")";
|
||||||
|
case SE_LCBRAC: return "{";
|
||||||
|
case SE_RCBRAC: return "}";
|
||||||
|
case SE_COMMA: return ",";
|
||||||
|
case SE_SEMI: return ";";
|
||||||
|
|
||||||
|
case IDN:
|
||||||
|
if (!buffer.compare("int")) {
|
||||||
|
return "int";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("void")) {
|
||||||
|
return "void";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("return")) {
|
||||||
|
return "return";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("const")) {
|
||||||
|
return "const";
|
||||||
|
}
|
||||||
|
else if (!buffer.compare("main")) {
|
||||||
|
return "main";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "IDN";
|
||||||
|
}
|
||||||
|
case INT_VAL: return "INT";
|
||||||
|
default: cerr << "Token Error: "<< type << endl; exit(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue