转载请注明出处:https://blog.csdn.net/hhhhhhhhhhkkkkkkkkkk
嗯,先上代码,后面慢慢写注释,我好像太鸡智(贼)了,哈哈
生成项目集簇
基本符号的定义与相关操作
using t_sym = int;//符号
using t_vv = t_sym;//终结符+虚拟终结符
using t_vt = t_vv;//终结符
using t_vc = t_vv;//虚拟终结符
using t_vn = t_sym;//非终结符
#define is_vv(x) ((x)>=0)
#define is_vt(x) (((x)>=0)&&((x)<=0xffff))
#define is_vc(x) ((x)>0xffff)
#define is_vn(x) ((x)<0)
语法
产生式
class t_analyzer;
using t_sematic = void(*)(t_analyzer*ana);
using t_syms = std::vector<t_sym>;//符号串
struct t_sen//产生式
{
t_vn left;
t_syms rights;
t_sematic sematic;
t_vv pri_sym;//优先级虚拟符号
};
语法与相关函数
enum e_ass
{
e_ass_none,
e_ass_left,
e_ass_right,
};
using t_vv_pri_ass_map = std::map<t_vv, std::pair<int, e_ass>>;//虚拟符号的优先级与结合性
using t_sens = std::vector<t_sen>;//文法
struct t_grammar//语法
{
t_sens sens;
t_vv_pri_ass_map vv_pri_ass_map;
t_sematic other_sens;
};
void grammar_make_pri_ass(t_grammar&g)
{
//插入默认优先级的处理
g.vv_pri_ass_map.insert({ 0,{ 0,e_ass_none } });
//开始设置语句对应的终结符
for (auto&sen : g.sens)
{
if (sen.pri_sym == 0)//未手动指定优先级和结合性符号
{
//找到右边起第一个终结符
for (auto rit = sen.rights.rbegin(); rit != sen.rights.rend(); rit++)
{
if (is_vt(*rit))
{
sen.pri_sym = *rit;
break;
}
}
//可能会没有终结符,这时候就设置不了产生式的优先级
}
}
}
项目集簇
first集与相关函数
using t_first = std::set<t_vt>;//first集
t_first&operator+=(t_first&dst, const t_first&src)
{
for (auto vt : src)
dst.insert(vt);
return dst;
}
项目与相关操作
struct t_item//项目
{
size_t senid;//产生式id
size_t pos;//项目符位置
t_first first;//first集
};
bool operator==(const t_item&item1, const t_item&item2)
{
if (item1.senid != item2.senid)
return false;
if (item1.pos != item2.pos)
return false;
if (item1.first.size() != item2.first.size())
return false;
auto it1 = item1.first.begin();
auto it2 = item2.first.begin();
for (; it1 != item1.first.end(); it1++, it2++)
if (*it1 != *it2)
return false;
return true;
}
bool operator!=(const t_item&item1, const t_item&item2)
{
return !(item1 == item2);
}
using t_items = std::vector<t_item>;//项目集合
bool operator==(const t_items&items1, const t_items&items2)
{
if (items1.size() != items2.size())
return false;
for (size_t i = 0; i < items1.size(); i++)
{
if (items1.at(i) != items2.at(i))
return false;
}
return true;
}
t_items&operator+=(t_items&items, const t_item&item)
{
for (size_t i = 0; i < items.size(); i++)
if (items.at(i) == item)
return items;
items.push_back(item);
return items;
}
项目集
using t_action_map = std::map<t_sym, int>;//动作表(符号->>=0移进,==-1接受,<-1归约)
enum e_action//动作类型
{
e_error,
e_shift,
e_reduce,
e_access,
};
using t_collision_map = std::map<t_vt, std::map<e_action, std::vector<int>>>;//冲突表
struct t_set//项目集
{
t_items items;
t_action_map action_map;
t_collision_map collision_map;
};
构造项目集簇
生成空推导与非终结符的first集
using t_vn_senids_map = std::map<t_vn, std::vector<size_t>>;//以非终结符为索引的语句id集合
using t_vn_empty_map = std::map<t_vn, int>;//非终结符的空推导表-1-无法推出空 0-未知 1可推出空
using t_vn_first_map = std::map<t_vn, t_first>;//非终结符的first集表
t_vn_senids_map build_vn_senids_map(const t_sens&sens)
{
t_vn_senids_map vn_senids_map;
for (size_t i = 0; i < sens.size(); i++)
{
const auto&sen = sens.at(i);
vn_senids_map[sen.left].push_back(i);
}
return vn_senids_map;
}
t_vn_empty_map build_vn_empty_map(const t_sens&sens)
{
t_vn_empty_map vn_empty_map;
//生成语法的左部(非终结符)索引,方便操作
std::map<t_vn, std::vector<std::pair<int, int>>> vn_senid_poss_map;
for (int i = 0; i < (int)sens.size(); i++)
{
vn_senid_poss_map[sens.at(i).left].push_back({ i,0 });
}
//设置为未定
vn_empty_map.clear();
for (const auto&vn : vn_senid_poss_map)
{
vn_empty_map[vn.first] = 0;
}
//对每个非终结符,直接设置
for (auto it0 = vn_senid_poss_map.begin(); it0 != vn_senid_poss_map.end();)
{
auto&vn_senid_poss = *it0;
bool _is_deleted = false;
//对每个产生式
for (auto it = vn_senid_poss.second.begin(); it != vn_senid_poss.second.end(); )
{
const auto&sen = sens.at(it->first);
if (sen.rights.size() > 0)//如果不是空产生式
{
auto sym = sen.rights.at(0);
if (is_vt(sym))//如果第一个符号是终结符,删掉该产生式
it = vn_senid_poss.second.erase(it);
else
it++;
}
else//有空产生式
{
//置为‘是’
vn_empty_map.at(vn_senid_poss.first) = 1;
//删掉该非终结符的所有产生式
it0 = vn_senid_poss_map.erase(it0);
_is_deleted = true;
break;
}
}
//如果未删
if (!_is_deleted)
{
//如果该非终结符的所有产生式都被删去
if (vn_senid_poss.second.size() <= 0)
{
//置为‘否’
vn_empty_map.at(vn_senid_poss.first) = -1;
it0 = vn_senid_poss_map.erase(it0);//既然都没产生式了,他也没必要存在了
}
else//自增
it0++;
}
}
while (true)
{
bool is_changed = false;
//间接设置
for (auto it0 = vn_senid_poss_map.begin(); it0 != vn_senid_poss_map.end();)
{
auto&vn_senid_poss = *it0;
bool _is_deleted = false;
//对每个产生式
for (auto it = vn_senid_poss.second.begin(); it != vn_senid_poss.second.end(); )
{
const auto&sen = sens.at(it->first);
auto non = sen.rights.at(it->second);
if (vn_empty_map.find(non) == vn_empty_map.end())
printf("warn: %d undefined\n", non);
if (vn_empty_map[non] == 1)//如果该非终结符在数组中为‘是’
{
//删去该终结符
it->second++;
is_changed = true;
//若这使右部为空
if (it->second >= (int)sen.rights.size())
{
//置该非终结符号为‘是’
vn_empty_map.at(vn_senid_poss.first) = 1;
//删掉所有该非终结符的产生式
it0 = vn_senid_poss_map.erase(it0);
_is_deleted = true;
break;
}
it++;
}
else if (vn_empty_map.at(non) = -1)//若为‘否’
{
//删去该产生式
it = vn_senid_poss.second.erase(it);
}
else
{
it++;
}
}
//如果未删
if (!_is_deleted)
{
//如果该非终结符的所有产生式都被删去
if (vn_senid_poss.second.size() <= 0)
{
//置为‘否’
vn_empty_map.at(vn_senid_poss.first) = -1;
is_changed = true;
it0 = vn_senid_poss_map.erase(it0);//既然都没产生式了,他也没必要存在了
}
else//自增
it0++;
}
}
if (!is_changed)
break;
}
return vn_empty_map;
}
t_vn_first_map build_vn_first_map(const t_sens&sens, const t_vn_empty_map&vn_empty_map)
{
t_vn_first_map vn_first_map;
//构造非终结符的索引,并直接设置
t_vn_senids_map vn_senids_map;
for (size_t i = 0; i < sens.size(); i++)
{
const auto&sen = sens.at(i);
if (sen.rights.size() > 0)
{
if (is_vt(sen.rights.at(0)))
vn_first_map[sen.left].insert(sen.rights.at(0));
else
vn_senids_map[sen.left].push_back({ i });
}
}
//间接设置
int old_size = 0;
while (true)
{
for (auto it0 = vn_senids_map.begin(); it0 != vn_senids_map.end(); it0++)
{
for (auto it = it0->second.begin(); it != it0->second.end(); it++)
{
const auto&sen = sens.at(*it);
for (size_t i = 0; i < sen.rights.size(); i++)
{
auto sym = sen.rights.at(i);
if (is_vn(sym))
{
for (auto ter : vn_first_map[sym])
vn_first_map[it0->first].insert(ter);
if (vn_empty_map.at(it0->first) != 1)
break;
}
else
{
vn_first_map[it0->first].insert(sym);
break;
}
}
}
}
int size = 0;
for (const auto&first_vn : vn_first_map)
{
size += (int)first_vn.second.size();
}
if (size != old_size)
old_size = size;
else
break;
}
return vn_first_map;
}
t_first calc_last_first(const t_item&item, const t_sens&sens, const t_vn_empty_map&vn_empty_map, const t_vn_first_map&vn_first_map)
{
t_first first;
const auto&rights = sens.at(item.senid).rights;
int i;
for (i = item.pos + 1; i < (int)rights.size(); i++)
{
auto v = rights.at(i);
if (is_vn(v))//非终结符
{
//将该vn对应的first并入
first += vn_first_map.at(v);
//如果该vn推导不出空,则结束
if (vn_empty_map.at(v) <= 0)
break;
}
else//终结符,直接结束
{
first.insert(v);
break;
}
}
//如果推导到了产生式末尾,则把项目的first并入
if (i >= (int)rights.size())
first += item.first;
return first;
}
生成项目集簇
//展开项目集合
void expand_items(t_items&items, const t_sens&sens, const t_vn_senids_map&vn_senids_map,const t_vn_empty_map&vn_empty_map, const t_vn_first_map&vn_first_map)
{
//展开
for (size_t i = 0; i < items.size(); i++)
{
const auto&item = items.at(i);
const auto&sen = sens.at(item.senid);
if (item.pos < sen.rights.size())
{
auto sym = sen.rights.at(item.pos);
if (is_vn(sym))
{
const auto&senids = vn_senids_map.at(sym);
auto first = calc_last_first(item, sens, vn_empty_map, vn_first_map);
for (auto senid : senids)
{
items += {senid, 0, first};
}
}
}
}
//合并仅first集不同的项
for (size_t i = 0; i < items.size(); i++)
{
for (size_t j = i + 1; j < items.size(); )
{
auto&item1 = items.at(i);
auto&item2 = items.at(j);
if ((item1.senid == item2.senid) && (item1.pos == item2.pos))
{
item1.first += item2.first;
items.erase(items.begin() + j);
}
else
j++;
}
}
}
std::pair<int, e_ass>get_ass(const t_vv_pri_ass_map&vv_pri_ass_map, int vv)
{
auto it = vv_pri_ass_map.find(vv);
if (it != vv_pri_ass_map.end())
{
return it->second;
}
return { 0,e_ass::e_ass_right };
}
t_cluster cluster_build(const t_grammar&g, t_vt end_vt)
{
//生成vn_senids_map
auto vn_senids_map = build_vn_senids_map(g.sens);
//生成vn_empty_map
auto vn_empty_map = build_vn_empty_map(g.sens);
//生成vn_first_map
auto vn_first_map = build_vn_first_map(g.sens, vn_empty_map);
//开始构造
//添加初始项目集
t_cluster cluster = { { { { 0,0,{ end_vt } } } } };
//对项目集簇中的每个项目集
for (size_t i = 0; i < cluster.size(); i++)
{
auto&set = cluster.at(i);
//展开当前项目集
expand_items(set.items, g.sens, vn_senids_map, vn_empty_map, vn_first_map);
std::map<t_sym, t_items>sym_items_map;
//对项目集合中的每个项目
for (size_t j = 0; j < set.items.size(); j++)
{
const auto&item = set.items.at(j);
const auto&sen = g.sens.at(item.senid);
//如果不是归约项目,则按项目符号添加到对应的项目集合,同时项目符号后移一位
if (item.pos < sen.rights.size())
{
sym_items_map[sen.rights.at(item.pos)].push_back({ item.senid,item.pos + 1,item.first });
}
}
//对每个符号,生成移进表
for (auto&pr : sym_items_map)
{
auto&new_items = pr.second;
//展开上面生成的项目集合
expand_items(new_items, g.sens, vn_senids_map, vn_empty_map, vn_first_map);
//在项目集簇中查找这个项目集合
auto id = cluster_find(cluster, new_items);
//若未找到,把这个项目集合构成项目集并添加到项目集簇的末尾
if (id >= cluster.size())
{
cluster.push_back({ new_items });
}
//生成该符号的移进表
cluster.at(i).action_map[pr.first] = int(id);
//添加冲突
cluster.at(i).collision_map[pr.first][e_shift].push_back(int(id));
}
//生成归约表(包括接受表)
auto&new_set = cluster.at(i);
//对当前项目集合的每个项目
for (const auto&item : new_set.items)
{
const auto&sen = g.sens.at(item.senid);
//如果是归约项目
if (item.pos >= sen.rights.size())
{
//对项目的每个first集符号
for (auto vt : item.first)
{
new_set.collision_map[vt][e_reduce].push_back(int(item.senid));
}
}
}
//处理冲突
/*
默认:
1 移进-归约->移进
2 归约-归约->senid小的归约
指定:
1 采用优先级大的
2 优先先级相同的按本符号的结合性处理
*/
for (const auto&pr : new_set.collision_map)
{
auto it = pr.second.find(e_reduce);
//有归约项
if (it != pr.second.end())
{
auto it1 = pr.second.find(e_shift);
//有移进项
size_t j = 0;
if (it1 != pr.second.end())
{
//比较归约项与移进项的优先级大小
auto pri_shift = get_ass(g.vv_pri_ass_map, pr.first);
for (; j < it->second.size(); j++)
{
auto pri_reduce = get_ass(g.vv_pri_ass_map, g.sens.at(it->second.at(j)).pri_sym);
//如果有优先级大于移进项的,就跳到无移进项的处理,否则结束(采用移进项)
if (pri_shift.first < pri_reduce.first)
break;
else if (pri_shift.first == pri_reduce.first)
{
if (pri_reduce.second == e_ass_left)//采用归约,所以跳出
break;
}
}
}
if (j < it->second.size())//无移进项,或移进项优先级小
{
auto pri_cur = get_ass(g.vv_pri_ass_map, g.sens.at(it->second.at(j)).pri_sym);
auto cur_senid = it->second.at(j);
for (j++; j < it->second.size(); j++)
{
auto pri_next = get_ass(g.vv_pri_ass_map, g.sens.at(it->second.at(j)).pri_sym);
if (pri_next.first < pri_cur.first)
continue;
if (pri_next.first == pri_cur.first)
{
if (cur_senid >= it->second.at(j))
continue;
}
pri_cur = pri_next;
cur_senid = it->second.at(j);
}
new_set.action_map[pr.first] = -cur_senid - 1;
}
}
//如果没有归约项,就不用管了
}
}
return cluster;
}