/***************************************
*** 语法分析(算符优先文法)-头文件 *****
*** 输入文法格式-非终结符:其产生式 *****
*** 每个文法子句间用空格分隔 *****
*** 非终结符采用A--Z中字母 *****
*** 例E:E+T|T T:T*F|F F:P-F|P ... *****
***************************************/
#include<iostream>
#include<string>
#include<vector>
using namespace std;
/
/// 语法分析(算符优先文法)类
class wpanalyse
{
public:
wpanalyse(string s, string s1);// 构造函数
~wpanalyse(){}// 析构函数
void firstvt(string s);// firstvt函数
void lastvt(string s);// lastvt函数
void analyse();// 语法分析函数
private:
vector<string> vs;// 保存文法
vector<char> fs[26];// 保存对应firstvt--由于vc6.0中string没有push_back()函数所以采用vector
vector<char> ls[26];// 保存对应lastvt
char vt[20];// 终结符集
string st;// 输入句子
bool iserror;// 是否出错记录变量
int nvt;// 优先表大小
};
// 构造函数--实现算符文法判断、记录终结符集和产生式集并调用其他函数
wpanalyse :: wpanalyse(string s, string s1) : nvt(0),iserror(0)// 输入文法和判断是否是算符优先文法
{ // 并调用相关处理函数
int i, j, k;
bool f, flag, symbol;// 判断标志
char tmp[20];// 文法中产生式中间变量
string::iterator h;// 句子的迭代器--用于检测句子中的字符是否均是文法中的终结符
vector<string>::iterator it;// 产生式集的迭代器
st = s1;// 记录句子
for(i=0; s[i]!='/0';)
{
j = 0;
flag = 0;
while(s[i]!=' '&&s[i]!='/0')// 将文法中产生式分离并保存在vs产生式集中
{
f = 0;
tmp[j] = s[i];
if(s[i]>='A'&&s[i]<='Z'&&
s[i+1]>='A'&&s[i+1]<='Z')// 判断是否是算符文法
{
flag = 1;
break;
}
if(!(tmp[j]>='A'&&tmp[j]<='Z')&&tmp[j]!=':'&&tmp[j]!='|')// 判断是否是终结符
{
for(k=0; k<nvt; ++k)// 检索该终结符是否已在终结符集合中
{
if(vt[k]==tmp[j])
{
f = 1;
}
}
if(!f)// 由标志判断是否加入终结符集
{
vt[nvt] = tmp[j];
++nvt;
}
}
++i;
++j;
}
if(flag)
{
cout<<"This isn't a operational word!"<<endl;
break;
}
else// 将该产生式存入产生式集
{
tmp[j] = '/0';
vs.push_back(tmp);
}
if(s[i]==' ')// 进入下个产生式的首位
{
++i;
}
}
for(h=s1.begin(); h!=s1.end(); ++h)// 检测句子中的字符是否均是文法中的终结符
{
symbol = 0;
for(i=0, j=0; i<nvt; ++i)
{
if(*h==vt[i])
{
symbol= 1;
}
}
if(!symbol)
{
break;
}
}
if(symbol)
{
for(it=vs.begin(); it!=vs.end(); ++it)// 分析每个非终结符的firstvt和lastvt
{
firstvt(*it);
lastvt(*it);
}
analyse();// 分析句子
if(iserror)// 根据前面分析函数给出的标志判断句子是否正确
{
cout<<"The sentence is wrong!"<<endl;
}
else
{
cout<<"The sentence is right!"<<endl;
}
}
else
{
cout<<"The sentence is wrong!"<<endl;
}
}
// firstvt函数--分析每个非终结符的firstvt并保存在fs中
void wpanalyse :: firstvt(string s)
{
int i=2;
bool flag;// 终结符是否压入fs的标志
vector<string>::iterator j;// 产生式集的迭代器
vector<char>::iterator h;// fs集的迭代器
vector<char>::iterator k;// fs集的迭代器
string p;
while(s[i]!='/0')// 判断产生式是否结束
{
flag = 0;
if(!(s[i]>='A'&&s[i]<='Z'))// 产生式右部首位是终结符时
{
for(h=fs[s[0]-'A'].begin(); h!=fs[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
{
if(s[i]==*h)
{
flag = 1;
}
}
if(!flag)// 终结符不在ls集则加入
{
fs[s[0]-'A'].push_back(s[i]);
}
}
else if(s[i]>='A'&&s[i]<='Z'&&s[i]!=s[0])// 产生式右部首位是非终结符时
{
for(j=vs.begin(); j!=vs.end(); ++j)
{
p = *j;
if(p[0]==s[i])// 判断产生式的首位(产生式左部)是否是此非终结符
{
firstvt(p);// 分析此非终结符的firstvt集
for(k=fs[s[i]-'A'].begin(); k!=fs[s[i]-'A'].end(); ++k)
{
for(h=fs[s[0]-'A'].begin(); h!=fs[s[0]-'A'].end(); ++h)// 检索终结符是否已经在fs集中
{
if(*k==*h)
{
flag = 1;
}
}
if(!flag)// 终结符不在fs集则加入
{
fs[s[0]-'A'].push_back(*k);
}
}
}
}
}
while(s[i]!='|'&&s[i]!='/0')
{
++i;
}
if(s[i]=='|')
{
++i;
}
}
}
// lastvt函数--分析每个非终结符的lastvt并保存在ls中
void wpanalyse :: lastvt(string s)
{
int i=2;
bool flag;// 终结符是否压入ls的标志
vector<char>::iterator h;// ls集的迭代器
vector<char>::iterator k;// ls集的迭代器
vector<string>::iterator j;// 产生式集的迭代器
string p;// 辅助变量
while(s[i]!='/0')// 判断产生式是否结束
{
flag = 0;
while(s[i]!='|'&&s[i]!='/0')// 找到产生式末尾
{
++i;
}
--i;
if(!(s[i]>='A'&&s[i]<='Z'))// 最后字符是终结符时
{
for(h=ls[s[0]-'A'].begin(); h!=ls[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
{
if(s[i]==*h)
{
flag = 1;
}
}
if(!flag)// 终结符不在ls集则加入
{
ls[s[0]-'A'].push_back(s[i]);
}
}
else // 找非终结符的lastvt集
{
for(j=vs.begin(); j!=vs.end(); ++j)
{
p = *j;// 记录产生式
if(p[0]==s[i])// 判断产生式的首位(产生式左部)是否是此非终结符
{
lastvt(p);// 分析此非终结符的lastvt集
for(k=ls[s[i]-'A'].begin(); k!=ls[s[i]-'A'].end(); ++k)
{
for(h=ls[s[0]-'A'].begin(); h!=ls[s[0]-'A'].end(); ++h)// 检索终结符是否已经在ls集中
{
if(*k==*h)
{
flag = 1;
}
}
if(!flag)// 终结符不在ls集则加入
{
ls[s[0]-'A'].push_back(*k);
}
}
}
}
}
++i;
if(s[i]=='|')
{
++i;
}
}
}
// 语法分析函数--构建优先表和分析句子
void wpanalyse :: analyse()
{
int i, x, y, k, pre;
char r[20];
string p;
vector<char>::iterator z;
vector<string>::iterator j;
char **table = new char*[nvt];
for(i=0; i<nvt; ++i)
{
table[i] = new char[nvt];
}
// 构建优先表
for(j=vs.begin(); j!=vs.end(); ++j)
{
p = *j;
for(i=2; p[i]!='/0'; ++i)
{
if(p[i+1]!='/0'&&p[i]!='|'&&p[i+1]!='|'&&
!(p[i]>='A'&&p[i]<='Z')&&
!(p[i+1]>='A'&&p[i+1]<='Z'))// 两终结符相邻时
{
for(x=0; vt[x]!=p[i]; ++x);// 找到table中的行位置
for(y=0; vt[y]!=p[i+1]; ++y);// 找到table中的列位置
if(table[x][y]!='>'&&
table[x][y]!='<')// table[x][y]原无其他状态时
{
table[x][y] = '=';
}
else
{
iserror = 1;
}
}
if(p[i+2]!='/0'&&p[i]!='|'&&p[i+2]!='|'&&
!(p[i]>='A'&&p[i]<='Z')&&
p[i+1]>='A'&&p[i+1]<='Z'&&
!(p[i+2]>='A'&&p[i+2]<='Z'))// 两终结符间隔一个非终结符时
{
for(x=0; vt[x]!=p[i]; ++x);// 找到table中的行位置
for(y=0; vt[y]!=p[i+2]; ++y);// 找到table中的列位置
if(table[x][y]!='>'&&
table[x][y]!='<')// table[x][y]原无其他状态时
{
table[x][y] = '=';
}
else
{
iserror = 1;
}
}
if(!(p[i]>='A'&&p[i]<='Z')&&p[i+1]!='/0'&&
p[i+1]>='A'&&p[i+1]<='Z')// 终结符和其后非终结符时
{
for(x=0; vt[x]!=p[i]; ++x);// 找到行位置
for(z=fs[p[i+1]-'A'].begin(); z!=fs[p[i+1]-'A'].end(); ++z)
{
for(y=0; vt[y]!=*z; ++y);// 找到列位置
if(table[x][y]!='>'&&
table[x][y]!='=')// table[x][y]原无其他状态时
{
table[x][y] = '<';
}
else
{
iserror = 1;
}
}
}
if(p[i]>='A'&&p[i]<='Z'&&p[i+1]!='|'&&p[i+1]!='/0'&&
!(p[i+1]>='A'&&p[i+1]<='Z'))// 非终结符和其后终结符时
{
for(y=0; vt[y]!=p[i+1]; ++y);// 找到列位置
for(z=fs[p[i]-'A'].begin(); z!=fs[p[i]-'A'].end(); ++z)
{
for(x=0; vt[x]!=*z; ++x);// 找到行位置
if(table[x][y]!='='&&
table[x][y]!='<')// table[x][y]原无其他状态时
{
table[x][y] = '>';
}
else
{
iserror = 1;
}
}
}
}
}
// 分析句子
for(x=0; vt[x]!=st[0]; ++x);
for(i=1; st[i]!='/0'; ++i)// 根据table对句子两两关系判断并记录
{
for(y=0; vt[y]!=st[i]; ++y);
r[i] = table[x][y];
x = y;
}
r[i] = '/0';
pre = -1;
i = 0;
while(r[i]!='/0')
{
for(i=1; r[i]!='>'&&r[i]!='/0'; ++i)// 找到最左素短语 // bug:a?dbcde=>S:aAcBe A:Bb|b B:d
{
if(r[i]=='<')
{
pre = i;
}
if(pre==-1&&r[i+1]=='>')
{
++i;
}
}
for(j=vs.begin(); pre!=-1&&j!=vs.end(); ++j)// 检索该最左素短语能否归约--若能则归约否则报错
{
k = 2;
p = *j;
x = pre;
while(p[k]!='/0')// 判断产生式是否结束
{
while(p[k]==st[x]&&p[k]!='/0')// 产生式与最左素短语比较
{
++x;
++k;
}
if(x==i)// 判断最左素短语是否与某产生式一一对应
{
if(r[i]=='/0')
{
--x;
}
r[x] = '=';// 消除原大于或小于关系-即去除当前最左素短语
for(y=x+1; r[y]!='/0'&&r[y]!='<'&&r[y]!='>'; ++y);// 检索下一个非'='关系--当关系为'>'时
// 说明可继续归约不能去除原归约项左边'<'关系
if(r[y]=='>')// 可进一步归约时-对归约后的st和r进行相应处理
{
if(x-pre==1)// 归约项为一位时仅改变一位st
{
st[pre] = p[0];
}
else// 归约项为多位时归约一位后空余归约位补上后面字符并对r进行相同处理(同步对应)
{
st[pre] = p[0];
for(y=pre+1; st[y]!='/0'; ++y)
{
st[y] = st[y+x-pre-1];
r[y] = r[y+x-pre-1];
}
}
}
else// 不可进一步归约则去除原归约项左边'<'关系
{
r[pre] = '=';
}
pre = -1;
break;
}
else
{
while(p[k]!='|'&&p[k]!='/0')// 移到下条产生式
{
++k;
}
if(p[k]=='|')
{
++k;
}
}
}
}
if(pre!=-1)
{
iserror = 1;
break;
}
}
for(i=1; r[i]!='/0'; ++i)// 判断是否全部归约
{
if(r[i]=='<'||r[i]=='>')
{
iserror = 1;
break;
}
}
for(i=0; i<nvt; ++i)// 释放申请空间
{
delete[] table[i];
}
delete[] table;
}
#include "prioranalyse_h.h"
int main()
{
string s, s1;
cin>>s;
cin.clear();// 清除缓冲流
cin.ignore();
getline(cin, s1);//第三参数默认为'/n'
//s = "adbcde";
//s1 = "S:aAcBe A:Bb|b B:d";
wpanalyse a(s1, s);
return 0;
}