java 消除文法左递归,[原创]【编译原理】文法解析算法以及左递归消除算法

CFG.h

#pragma once

#include

#include

#include

#include

#include

namespace CFG {

enum SYMBOLIC_TYPE

{

SYMBOLIC_TYPE_TERMINAL = 0, // 终结符号

SYMBOLIC_TYPE_N_TERMINAL, // 非终结符号

SYMBOLIC_TYPE_UNKNOW // 未知类型

};

// 文法符号

class GrammarSymbolic

{

public:

GrammarSymbolic(const std::string &name, SYMBOLIC_TYPE type) : name_(name), type_(type) { }

public:

std::string Name()

{

return name_;

}

SYMBOLIC_TYPE Type()

{

return type_;

}

private:

std::string name_; // 符号名称

SYMBOLIC_TYPE type_; // 符号类型

};

// 产生式体

typedef std::vector ProductionBody;

// 产生式类

class Production

{

public:

Production(std::string header) : header_(header) {}

public:

std::string Header() const

{

return header_;

}

std::vector &Body() {

return bodys_;

}

public:

void AppendBody(ProductionBody body);

Production &operator +=(const Production &rhs)

{

// 产生式头部相同才可以合并

if (header_ != rhs.header_)

{

return *this;

}

for (auto body : rhs.bodys_)

{

this->bodys_.push_back(body);

}

return *this;

}

private:

std::string header_; // 产生式头

std::vector bodys_; // 产生式体

};

// 文法类

class CFG

{

friend std::ostream &operator <

public:

CFG(const std::set<:string> n_terminal_set, // 非终结符的集合

const std::set<:string> terminal_set, // 终结符的集合

const std::string &productions, // 产生式列表

const std::string start // 文法的开始符号

);

~CFG();

public:

/// 是否是终结符号

bool IsTerminal(const std::string &symbolic);

/// 是否是非终结符号

bool IsNTerminal(const std::string &symbolic);

/// 是否是文法符号

bool IsCFGSymbolic(const std::string &symbolic);

/// 获取文法符号类型

SYMBOLIC_TYPE GetSymbolicType(const std::string &symbolic);

public:

/// 移除左递归

CFG &RemoveRecursive();

/// 提取左公因子

CFG &TakeLeft();

private:

void AppendProduct(std::shared_ptr product);

private:

std::set<:string> n_terminal_set_; // 非中介符号集合

std::set<:string> terminal_set_; // 终结符号集合

std::string start_; // 文法开始符号

std::vector<:shared_ptr>> productions_;// 产生式列表

};

}

CFG.cpp

#include "CFG.h"

#include

#include

#include

#include

using std::stringstream;

CFG::CFG::CFG(const std::set<:string> n_terminal_set,

const std::set<:string> terminal_set,

const std::string &productions,

const std::string start) : n_terminal_set_(n_terminal_set), terminal_set_(terminal_set)

{

// 检查开始符号是否在终结符号中

auto iter = std::find(n_terminal_set.begin(), n_terminal_set.end(), start);

if (iter == n_terminal_set.end())

{

throw std::runtime_error("开始符号不在非终结符集中!");

}

enum

{

PARSE_CFG_STATUS_HEADER = 0, // 解析产生式头状态

PARSE_CFG_STATUS_BODY // 解析产生式体状态

};

int parse_status = PARSE_CFG_STATUS_HEADER;

std::string cfg_symbolic_head, // 产生式头文法符号

cfg_symbolic_body; // 产生式体文法符号

ProductionBody product_body; // 产生式体

std::shared_ptr product; // 产生式

for (size_t i = 0; i < productions.length(); i++)

{

switch (parse_status)

{

case PARSE_CFG_STATUS_HEADER:

{

// 过滤空格

if (' ' == productions[i])

{

break;

}

// 检查产生式头部结束

if ('-' == productions[i] &&

i + 1 < productions.length() &&

'>' == productions[i + 1])

{

++i; // 过滤 ">"

parse_status = PARSE_CFG_STATUS_BODY;

if (cfg_symbolic_head.empty())

{

throw std::runtime_error("产生式头部不能为空!");

}

product = std::shared_ptr(new Production(cfg_symbolic_head));

assert(product);

if (NULL == product)

{

throw std::runtime_error("分配内存失败!");

}

cfg_symbolic_head = "";

break;

}

cfg_symbolic_head += productions[i];

// 查找产生式头部符号 是否在非终结符内, 不在的话则报错

if (false == IsNTerminal(cfg_symbolic_head))

{

stringstream ss;

ss << "产生式头部符号" << cfg_symbolic_head << "不在非终结符号集合中!";

throw std::runtime_error(ss.str().c_str());

}

break;

}

case PARSE_CFG_STATUS_BODY:

{

// 过滤空格

if (' ' == productions[i])

{

break;

}

switch (productions[i])

{

case '\n':

case '|':

{

if (cfg_symbolic_body != "")

{

stringstream ss;

ss << "未知的文法符号: " << cfg_symbolic_body;

throw std::runtime_error(ss.str().c_str());

}

if (product_body.empty())

{

stringstream ss;

ss << "未知的文法符号: " << cfg_symbolic_body;

throw std::runtime_error(ss.str().c_str());

}

product->AppendBody(product_body);

product_body.clear();

if ('\n' == productions[i])

{

AppendProduct(product); // 添加产生式

parse_status = PARSE_CFG_STATUS_HEADER; // 切换分析状态

}

break;

}

case '\r':

{

break;

}

default:

{

cfg_symbolic_body += productions[i];

if (IsCFGSymbolic(cfg_symbolic_body))

{

product_body.push_back(new GrammarSymbolic(cfg_symbolic_body, GetSymbolicType(cfg_symbolic_body)));

cfg_symbolic_body = "";

}

break;

}

}

if (i + 1 == productions.length())

{

if (cfg_symbolic_body != "")

{

stringstream ss;

ss << "未知的文法符号: " << cfg_symbolic_body;

throw std::runtime_error(ss.str().c_str());

}

if (product_body.empty())

{

stringstream ss;

ss << "未知的文法符号: " << cfg_symbolic_body;

throw std::runtime_error(ss.str().c_str());

}

product->AppendBody(product_body);

product_body.clear();

AppendProduct(product); // 添加产生式

parse_status = PARSE_CFG_STATUS_HEADER; // 切换分析状态

}

break;

}

}

}

}

CFG::CFG::~CFG()

{

}

/// 移除左递归

CFG::CFG &CFG::CFG::RemoveRecursive()

{

size_t size = productions_.size();

for (size_t i = 0; i < size; i++)

{

// 将外层非直接左递归 转换为直接左递归

for (size_t j = 0; j < i; j++)

{

size_t k = 0;

while (k < productions_[i]->Body().size())

{

auto body = productions_[i]->Body();

if (body[k][0]->Name() == productions_[j]->Header())

{

body.erase(body.begin() + k); // 删除原先的元素

// 替换第一个符号

for (size_t t = 0; t < productions_[j]->Body().size(); t++)

{

// 添加新的产生式体

ProductionBody pb;

pb.insert(pb.end(), productions_[j]->Body()[t].begin(), productions_[j]->Body()[t].end());

pb.insert(pb.end(), body[0].begin() + 1, body[0].end());

body.push_back(pb);

}

// erase insert push_back 会使迭代器失效, 此处把k设置为0

k = 0;

}

else

{

k++; // 获取下一个产生式

}

}

}

消除立即左递归

// 消除产生式i的立即左递归

// E -> E + E | num

// 消除左递归之后变成了

// E -> numE`

// E` -> +EE` | ε

// 是否立即左递归

bool isLeftRecursive = false;

for (size_t k = 0; k < productions_[i]->Body().size(); k++)

{

if (productions_[i]->Header() == productions_[i]->Body()[k][0]->Name())

{

isLeftRecursive = true;

break;

}

}

if (false == isLeftRecursive)

{

continue;

}

for (size_t k = 0; k < productions_[i]->Body().size(); )

{

std::string product_header = productions_[i]->Header() + "`";

// 左递归产生式 E -> E + E 转换为 E` -> +EE`

if (productions_[i]->Header() == productions_[i]->Body()[k][0]->Name())

{

assert(productions_[i]->Body()[k].size() > 1); // 断言至少有两个符号

ProductionBody pb; // 新的产生式体

// 获取 +E

pb.insert(pb.end(), productions_[i]->Body()[k].begin() + 1, productions_[i]->Body()[k].end());

pb.push_back(new GrammarSymbolic(product_header, SYMBOLIC_TYPE_N_TERMINAL));

// 设置新的产生式

auto new_product = std::shared_ptr(new Production(product_header));

new_product->AppendBody(pb);

this->AppendProduct(new_product); // 添加新的产生式

// 删除原先的产生式

auto iter = productions_[i]->Body().erase(productions_[i]->Body().begin() + k);

k = iter - productions_[i]->Body().begin();

n_terminal_set_.insert(product_header);

continue;

}

else // 非递归产生式

{

if (productions_[i]->Body()[k][0]->Name() == "ε") // 如果是空的话

{

ProductionBody pb; // 新的产生式体

pb.push_back(new GrammarSymbolic(product_header, SYMBOLIC_TYPE_N_TERMINAL));

}

else

{

productions_[i]->Body()[k].push_back(new GrammarSymbolic(product_header, SYMBOLIC_TYPE_N_TERMINAL));

}

}

// 设置新的产生式

auto new_product = std::shared_ptr(new Production(product_header));

ProductionBody pb; // 新的产生式体

pb.push_back(new GrammarSymbolic("ε", SYMBOLIC_TYPE_TERMINAL));

new_product->AppendBody(pb);

this->AppendProduct(new_product); // 添加新的产生式

k++;

}

}

return *this;

}

/// 提取左公因子

CFG::CFG &CFG::CFG::TakeLeft()

{

return *this;

}

bool CFG::CFG::IsTerminal(const std::string &symbolic)

{

auto iter = std::find(terminal_set_.begin(), terminal_set_.end(), symbolic);

return !(iter == terminal_set_.end());

}

bool CFG::CFG::IsNTerminal(const std::string &symbolic)

{

auto iter = std::find(n_terminal_set_.begin(), n_terminal_set_.end(), symbolic);

return !(iter == n_terminal_set_.end());

}

bool CFG::CFG::IsCFGSymbolic(const std::string &symbolic)

{

return IsTerminal(symbolic) || IsNTerminal(symbolic);

}

void CFG::CFG::AppendProduct(std::shared_ptr product)

{

for (auto &_product : productions_)

{

if (_product->Header() == product->Header())

{

*_product += *product;

return;

}

}

productions_.push_back(product);

}

CFG::SYMBOLIC_TYPE CFG::CFG::GetSymbolicType(const std::string & symbolic)

{

if (IsTerminal(symbolic))

{

return SYMBOLIC_TYPE_TERMINAL;

}

if (IsNTerminal(symbolic))

{

return SYMBOLIC_TYPE_N_TERMINAL;

}

return SYMBOLIC_TYPE_UNKNOW;

}

void CFG::Production::AppendBody(ProductionBody body)

{

this->bodys_.push_back(body);

}

std::ostream & CFG::operator<

{

// TODO: 在此处插入 return 语句

for (auto &product : cfg.productions_)

{

out << product->Header() << " -> ";

for (auto &body : product->Body())

{

for (auto &symbolic : body)

{

out << symbolic->Name();

}

out << " | ";

}

out << std::endl;

}

return out;

}

main.cpp

#include

#include "CFG.h"

#include

using std::cin;

using std::cout;

void TestParse()

{

// 产生式列表

const char *products = "S -> E\n"

"E -> E + T | E - T | T\n"

"T -> T * F | T / F | F\n"

"F -> (E) | num";

// 非终结符号集合

std::set<:string> n_terminal_set = { "S", "E", "T", "F" };

// 终结符号集合

std::set<:string> terminal_set = { "num", "+", "-", "*", "/", "(", ")" };

try

{

CFG::CFG cfg(n_terminal_set, terminal_set, products, "S");

std::cout << "消除左递归之前: " << std::endl << cfg << std::endl;

std::cout << "消除左递归后: " << std::endl << cfg.RemoveRecursive();

}

catch (const std::exception &exp)

{

std::cout << exp.what() << std::endl;

}

}

void TestFirst()

{

}

int main()

{

TestParse();

system("pause");

return 0;

}

效果如下

310e5cd41ab32568678599cfe1d5d594.png

最后于 2018-12-24 12:00

被菜鸟级X编辑

,原因:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值