#include <sstream>
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <set>
#include <algorithm>
#include <bitset>
using namespace std;
struct Grammar {
vector<string> productions;
bool hasN;
};
struct N {
set<char> names;
};
struct T {
set<char> names;
};
N non_terminals;
T terminals;
char start_symbol;
map<char, Grammar> grammars;
void hasN_() {
bool changes = true;
while (changes) {
changes = false;
for (auto& it : grammars) {
if (it.second.hasN)
continue;
for (string& prod : it.second.productions) {
bool onlyN = true;
for (char c : prod) {
if (grammars.count(c) == 0 || !grammars[c].hasN) {
onlyN = false;
break;
}
}
if (onlyN) {
it.second.hasN = true;
changes = true;
break;
}
}
}
}
Grammar start_grammar = grammars[start_symbol];
if (start_grammar.hasN) {
start_symbol = 'T';
vector<string> newproductions;
newproductions.push_back("S");
Grammar new_grammar;
new_grammar.hasN = 1;
new_grammar.productions = newproductions;
grammars[start_symbol] = new_grammar;
non_terminals.names.insert('T');
}
}
void cleanseN() {
hasN_();
map<char, Grammar> newGrammars;
for (auto& it : grammars) {
if (it.second.hasN)
newGrammars.insert(it);
}
for (auto& it : grammars) {
vector<string> newproductions;
for (auto& p : it.second.productions) {
int a = 0;
for (char c : p) {
if (newGrammars.count(c) > 0) {
a = (a << 1) | 1;
}
else {
a = a << 1;
}
}
for (int i = a; i ; i = (i - 1) & a) {
string transformedProduction;
for (size_t j = 0; j < p.size(); ++j) {
if ((i >> (p.size() - j - 1)) == 0) {
transformedProduction += p[j];
}
}
if (transformedProduction.size() > 0) {
newproductions.push_back(transformedProduction);
}
}
}
for (const string& newProduction : newproductions) {
it.second.productions.push_back(newProduction);
}
}
}
void removeUselessSymbols() {
set<char> generating, reachable = {start_symbol};
bool changes;
do {
changes = false;
for (const auto& it : grammars) {
for (const string& prod : it.second.productions) {
bool canGenerate = true;
for (char c : prod) {
if (grammars.count(c) > 0 && !generating.count(c)) {
canGenerate = false;
break;
}
}
if (canGenerate && generating.insert(it.first).second)
changes = true;
}
}
} while (changes);
do {
changes = false;
for (char symbol : reachable) {
if (grammars.count(symbol) > 0) {
for (const string& prod : grammars[symbol].productions) {
for (char c : prod) {
if (grammars.count(c) > 0 && reachable.insert(c).second)
changes = true;
}
}
}
}
} while (changes);
for (auto it = grammars.begin(); it != grammars.end();) {
if (!generating.count(it->first) || !reachable.count(it->first)) {
non_terminals.names.erase(it->first); // 同步删除 non_terminals 中的非终结符
it = grammars.erase(it);
}
else
++it;
}
for (auto it = terminals.names.begin(); it != terminals.names.end();) {
bool found = false;
for (const auto& grammar : grammars) {
for (const auto& prod : grammar.second.productions) {
if (prod.find(*it) != string::npos) {
found = true;
break;
}
}
if (found) break;
}
if (!found) {
it = terminals.names.erase(it);
}
else {
++it;
}
}
}
void cleanseSingleProds() {
map<char, set<char>> singleProds;
for (const auto& it : grammars) {
char nonTerminal = it.first;
for (const string& prod : it.second.productions) {
if (prod.size() == 1 && grammars.count(prod[0]) > 0) {
singleProds[nonTerminal].insert(prod[0]);
}
}
}
bool changes = true;
while (changes) {
changes = false;
for (auto& it : singleProds) {
size_t oldSize = it.second.size();
vector<char> addToSet;
for (char c : it.second) {
if (singleProds.count(c) > 0) {
for (char c2 : singleProds[c]) {
addToSet.push_back(c2);
}
}
}
it.second.insert(addToSet.begin(), addToSet.end());
if (it.second.size() > oldSize) {
changes = true;
}
}
}
for (auto& it : grammars) {
vector<string> newProds;
for (const string& prod : it.second.productions) {
if (!(prod.size() == 1 && grammars.count(prod[0]) > 0)) {
newProds.push_back(prod);
}
}
if (singleProds.count(it.first) > 0) {
for (char c : singleProds[it.first]) {
for (const string& prod : grammars[c].productions) {
if (!(prod.size() == 1 && grammars.count(prod[0]) > 0)) {
newProds.push_back(prod);
}
}
}
}
sort(newProds.begin(), newProds.end());
newProds.erase(unique(newProds.begin(), newProds.end()), newProds.end());
it.second.productions = newProds;
}
}
void readinput(){
int flag;
char c;
//read N
getchar();
getchar();
getchar();
flag = 1;
while (flag) {
char A, ch;
A = getchar();
ch = getchar();
non_terminals.names.insert(A);
if (ch == '}') {
flag = 0;
}
}
//read T
for (c = getchar(); c!='{'; c = getchar());
c = getchar();
flag = 1;
while (flag) {
char ch;
ch = getchar();
terminals.names.insert(c);
if (ch == '}') {
flag = 0;
}
else {
c = getchar();
}
}
//read P & S
string str;
cin >> str;
while (1) {
cin >> str;
//if (str.compare("S=S") == 0) {
// break;
//}
if (str[0] == 'S' && str[1] == '=') {
start_symbol = str[2];
break;
}
char S = str[0];
int length = str.length();
for (int i = 4, j = 4; i < length; i = ++j) {
while (str[j] != '|' && j < length) {
j++;
}
if (j - i == 1 && str[i] == 'N') {
grammars[S].hasN = 1;
}
else {
string str1 = str.substr(i, j - i);
grammars[S].productions.push_back(str1);
}
}
}
}
void printOutput() {
for (auto& it : grammars) {
sort(it
北京邮电大学形式语言第二次上机作业(c++)
需积分: 0 97 浏览量
更新于2023-06-07
收藏 2KB RAR 举报
**形式语言与自动机理论**
形式语言是计算机科学的一个重要分支,主要研究具有特定规则的符号序列,这些规则通常由正规表达式、上下文无关文法或上下文敏感文法来描述。在计算机科学中,形式语言理论为编译器设计、正则表达式、自动机理论等提供了理论基础。
**C++ 编程语言**
C++ 是一种强大的、面向对象的编程语言,由Bjarne Stroustrup于1983年在C语言的基础上发展而来。它支持类、模板、异常处理、命名空间等高级特性,并且具有高效性能和灵活性。在形式语言的实现中,C++ 提供了丰富的数据结构和算法库,使得编写复杂的语法分析和解析程序变得可能。
**上机作业内容推测**
这个“北京邮电大学形式语言第二次上机作业”很可能涉及以下几个方面:
1. **正规表达式与有限状态自动机(FSA)**:学生可能需要实现一个C++程序,能够根据给定的正规表达式构造和操作有限状态自动机。这可能包括构建NFA(非确定性有限状态自动机)和DFA(确定性有限状态自动机),以及进行正规集的并、交、差等操作。
2. **正则表达式匹配**:作业可能要求编写一个函数,该函数接收字符串和正规表达式作为输入,然后判断该字符串是否符合给定的正规表达式。这通常涉及到KMP算法或者后缀自动机等技术。
3. **上下文无关文法(CFG)**:学生可能需要理解和实现上下文无关文法的解析,比如LL(1)解析或LR(0)解析,用于分析和生成符合文法规则的程序代码。
4. **编译器基础**:作业可能涵盖词法分析和语法分析的基本概念,要求学生编写词法分析器和语法分析器的部分或全部功能。词法分析器将源代码转换为标记流,而语法分析器则将标记流解析成抽象语法树(AST)。
5. **测试用例**:形式语言的上机作业通常会包含一系列测试用例,用于检查程序的正确性和效率。学生需要确保他们的程序能正确处理各种复杂情况,包括边界条件和错误输入。
在提供的文件“形式语言第二次上机.cpp”中,可以预期包含上述提到的实现代码。为了完成作业,学生应该熟悉C++的基础语法,了解如何定义和操作自定义数据结构,以及如何编写和使用函数。此外,理解形式语言的基本理论和自动机的概念至关重要。完成这样的作业可以帮助学生深入理解形式语言的理论,并提高他们的编程技能。
komorebi1233214
- 粉丝: 0
- 资源: 2
最新资源
- 基于Springboot+Vue的疗养院管理系统的设计与实现-毕业源码案例设计(源码+项目说明+演示视频).zip
- 基于Springboot+Vue的旅游推荐系统设计与实现-毕业源码案例设计(高分毕业设计).zip
- 11种概率分布的拟合与ks检验,可用于概率分析,可靠度计算等领域 案例中提供11种概率分布,具体包括:gev、logistic、gaussian、tLocationScale、Rayleigh、Log
- 基于Springboot+Vue的贸易行业crm系统-毕业源码案例设计(95分以上).zip
- 基于Springboot+Vue的秒杀系统设计与实现-毕业源码案例设计(高分项目).zip
- 西门子1200和三菱FXU通讯程序
- 基于Springboot+Vue的名城小区物业管理系统-毕业源码案例设计(高分毕业设计).zip
- 欧美风格, 节日主题模板
- 基于Springboot+Vue的民族婚纱预定系统的设计与实现-毕业源码案例设计(高分毕业设计).zip
- 基于Springboot+Vue的农商订单跟踪售后交流对接系统-毕业源码案例设计(源码+数据库).zip
- 海面目标检测跟踪数据集.zip
- 基于Springboot+vue的人力资源管理系统-毕业源码案例设计(高分毕业设计).zip
- 基于Springboot+Vue的商业辅助决策系统的设计与实现-毕业源码案例设计(95分以上).zip
- 基于Springboot+Vue的企业资产管理系统-毕业源码案例设计(源码+论文).zip
- 准Z源光伏并网系统MATLAB仿真模型,采用了三次谐波注入法SPWM调制,具有更高的电压利用效率 并网部分采用了电压外环电流内环 电池部分采用了扰动观察法,PO Z源并网和逆变器研究方向的同学可
- 基于Springboot+Vue的实习管理系统-毕业源码案例设计(高分项目).zip