本文将介绍一个基于C++语言实现的文法分析器,该文法分析器是一份编译原理实验作业的成果。通过本文的阅读,您将会了解到如何使用C++语言来实现一个基本的文法分析器,并且了解文法分析器的基本原理和实现方法。
该程序的主要思路是将输入的产生式转换为文法,然后通过判断文法的特征来确定其是否为0-3型文法,并输出对应信息。最后,将文法转换为四元组形式输出。
具体实现中,通过自定义结构体Production
保存每个产生式,并使用vector
保存所有产生式。采用isType0
、isType1
、isType2
和isType3
函数来判断文法类型,其中isType3
由于比较复杂,需要分别判断右部符号的数量和类型。最后,通过printGrammar
函数将文法转换为四元组形式输出。
代码是按照老师给的判定要求来写的,如果规则不一样,可以自己修改一下。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct Production {
string left; // 产生式左部非终结符
vector<string> right; // 产生式右部,可能包含多个右部
bool operator < (const Production& p) const { // 因为要作为set的类型,所以不仅要定义==,还要定义<
if (left == p.left) {
if (right.size() == p.right.size()) {
for (int i = 0; i < right.size(); i++) {
if (right[i] != p.right[i]) {
return right[i] < p.right[i];
}
}
return false;
}
else {
return right.size() < p.right.size();
}
}
else {
return left < p.left;
}
}
} Production;
// split: 分割字符串
vector<string> split(string s, char delimiter) {
vector<string> res;
size_t start = 0, end = 0;
while ((end = s.find(delimiter, start)) != string::npos) {
if (end > start) {
res.push_back(s.substr(start, end - start));
}
start = end + 1;
}
if (start < s.size()) {
res.push_back(s.substr(start));
}
return res;
}
// isType0: 判断是否为0型文法
bool isType0(vector<Production> grammar) {
for (auto p : grammar) {
int symbol_count = 0;
for (char c : p.left) { // 统计非终结符数量
if (isupper(c)) {
symbol_count++;
}
}
if (symbol_count == 0) { // 左部没有非终结符
return false;
}
}
return true;
}
// isType1: 判断是否为1型文法
bool isType1(vector<Production> grammar) {
for (auto p : grammar) {
for (auto right : p.right) {
if (p.left.size() > right.size()) {
return false;
}
}
}
return true;
}
// isType2: 判断是否为2型文法
bool isType2(vector<Production> grammar) {
for (auto p : grammar) {
int symbol_count = 0;
for (char c : p.left) { // 统计非终结符数量
if (isupper(c)) {
symbol_count++;
}
}
if (symbol_count != 1) { // 左部不是一个非终结符
return false;
}
}
return true;
}
// isType3: 判断是否为3型文法
bool isType3(vector<Production> grammar) {
for (auto p : grammar) {
for (auto right : p.right) {
if (right.size() > 2) {
return false;
}
if (right.size() == 2) {
if ((isupper(right[0]) && isupper(right[1])) || (islower(right[0]) && islower(right[1])) || (isdigit(right[0]) && islower(right[1])) || (isdigit(right[0]) && islower(right[1])) || (islower(right[0]) && isdigit(right[1]))) {
return false;
}
}
if (right.size() == 1) {
if (!islower(right[0]) && !isdigit(right[0])) {
return false;
}
}
}
}
return true;
}
// printGrammar: 输出文法的四元组形式
void printGrammar(vector<Production> grammar, string start) {
vector<string> non_terms; // 非终结符
vector<string> terms; // 终结符
for (auto p : grammar) {
for (char c : p.left) {
if (isupper(c)) {
if (find(non_terms.begin(), non_terms.end(), string(1, c)) == non_terms.end()) {
non_terms.push_back(string(1, c));
}
}
}
for (auto right : p.right) { // 遍历每个产生式的右部
for (char c : right) {
if (islower(c) || isdigit(c)) {
if (find(terms.begin(), terms.end(), string(1, c)) == terms.end()) {
terms.push_back(string(1, c));
}
}
}
}
}
sort(non_terms.begin(), non_terms.end());
sort(terms.begin(), terms.end());
cout << "文法G定义:四元组(VN,VT,P,S)" << endl;
cout << "其中VN为非终结符集:{";
for (int i = 0; i < non_terms.size(); i++) {
cout << non_terms[i];
if (i != non_terms.size() - 1) {
cout << ", ";
}
}
cout << "}" << endl;
cout << "其中VT为终结符集:{";
for (int i = 0; i < terms.size(); i++) {
cout << terms[i];
if (i != terms.size() - 1) {
cout << ", ";
}
}
cout << "}" << endl;
cout << "其中P为产生式的集合:" << endl;
for (auto p : grammar) {
cout << " " << p.left << "->";
for (int i = 0; i < p.right.size(); i++) { // 遍历每个产生式的右部
cout << p.right[i];
if (i != p.right.size() - 1) {
cout << "|";
}
}
cout << endl;
}
cout << "S为开始符,它是一个非终结符,至少要在一条产生式的左部出现。" << endl;
cout << "开始符号: " << start << endl;
}
int main() {
while (true) { // 循环输入文法
vector<Production> grammar;
string start;
cout << "欢迎使用文法分析器!请输入产生式,以“@”结束,或输入“exit”退出:" << endl;
while (true) { // 输入产生式
string s;
getline(cin, s);
if (s == "@") {
break;
}
if (s == "exit") { // 用户输入退出指令时退出程序
return 0;
}
size_t pos = s.find("->"); // 找到"->"的位置
if (pos != string::npos) { // 找到"->",说明这是一条产生式
string left = s.substr(0, pos);
string right_str = s.substr(pos + 2);
vector<string> right = split(right_str, '|'); // 将右部按 '|' 分割
grammar.push_back({ left, right }); // 将产生式加入文法中
if (start.empty()) { // 第一次输入产生式时,将左部非终结符作为开始符号
start = left;
}
}
}
if (grammar.empty()) { // 如果输入为空,则重新输入
cout << "文法为空!" << endl;
continue;
}
cout << endl << "输入完成,您所输入的文法为:" << endl;
for (auto p : grammar) {
cout << " " << p.left << "->";
for (int i = 0; i < p.right.size(); i++) {
cout << p.right[i];
if (i != p.right.size() - 1) {
cout << "|";
}
}
cout << endl;
}
cout << endl << "该文法的四型文法类型为:" << endl;
if (isType0(grammar)) {
cout << " 0型文法" << endl;
}
if (isType1(grammar)) {
cout << " 1型文法" << endl;
}
if (isType2(grammar)) {
cout << " 2型文法" << endl;
}
if (isType3(grammar)) {
cout << " 3型文法" << endl;
}
if (!isType0(grammar) && !isType1(grammar) && !isType2(grammar) && !isType3(grammar)) {
cout << " 该文法不属于0-3型文法" << endl;
}
cout << endl << "该文法的四元组形式为:" << endl;
cout << endl << "======================================================" << endl << endl;
printGrammar(grammar, start);
cout << endl << "======================================================" << endl << endl;
}
return 0;
}