时隔这么久,我又回来更新博客了。
编译原理这里本人就是做多少更新多少了,不定期更新,因为时间有时候比较紧,所以就不能按时更新了。
今天看了一下语法分析,要是有需要词法分析的小伙伴们可以在等一等,很快也会更新过来。文章中不免有用词不当的地方,谢谢指正。
今天我们学习一下语法分析的LL(1)文法,LL(1)文法不是二义性的,也不是左递归的,我们要做确定的自顶向下语法分析,那么当给定一个文法,如下,本着学习并且要体验创造乐趣的我们,干脆自己写一个文法了,我就不直接用书上的例子了,我们要判定一个加,乘,括号和数字的式子是否符合我们的文法,文法如下。
这个文法粗糙了点,一看就不是LL(1)文法,我们要将其整理成符合LL(1)文法规则的文法,为了不让文章篇幅过大,这里不会展开整理的过程(相关知识会在别的文章里更新出),我直接写出结果。
整理完之后我也吓一跳,和书上的完全不同,可能是因为我对加,乘,括号之间没定义优先级的原因,不过这个文法还是符合LL(1)文法的。暂时不知道有什么弊端,我觉得可能会导致递归树过深。
#include<iostream>
using namespace std;
char code[128];//字符串
int i = 0;//字符串下标
bool isError = false;//当有一个位置出错了,则不会显示第二个位置的错误
void GrammarE();
void GrammarF();
/*获取下一个字符*/
char nextSymbol()
{
return code[++i];
}
/*访问当前的字符*/
char nowSymbol()
{
return code[i];
}
/*语法E*/
void GrammarE()
{
switch (nowSymbol())
{
case '(':
nextSymbol();
GrammarE();
switch (nowSymbol())
{
case ')':
nextSymbol();
GrammarF();
break;
default:
if (!isError)
{
cout << "error: at col " << i+1 << endl;
cout << endl;
isError = true;
}
break;
}
break;
case 'a':
nextSymbol();
GrammarF();
break;
default:
if (!isError)
{
cout << "error: at col " << i+1 << endl;
cout << endl;
isError = true;
}
break;
}
}
/*语法F*/
void GrammarF()
{
switch (nowSymbol())
{
case '+':
case '*':
nextSymbol();
GrammarE();
GrammarF();
break;
default:
break;
}
}
int main()
{
while (1)
{
cin >> code;
GrammarE();
//当分析结束后,测试中途中断说明有错误
if (strlen(code) != i)
{
if (!isError)
{
cout << "error: at col " << i+1 << endl;
cout << endl;
isError = true;
}
isError = true;
}
//没有错误,显示成功
if (!isError)
{
cout << "succeed" << endl;
cout << endl;
}
isError = false;
i = 0;
}
return 0;
}
/*
测试数据集:
a
(a)
a+a
(a+a)*a
a+a)
a)
()
aaa
a*a
a+(a+a)*a*(a+a*(a+a))
((((a))))
(((a)))+(((a+a)))*(a+a+(((a))))
a+a+b
a++
a+a++
a+(a+)
a*(a+(+))
)))
(((
((a)
(a))
*/
如果想把减法和除法也加进来,可以修改一下语法F
之后修改代码如下。
/*语法F*/
void GrammarF()
{
switch (nowSymbol())
{
case '+':
case '*':
case '-':
case '/':
nextSymbol();
GrammarE();
GrammarF();
break;
default:
break;
}
}
/*
a-a
a/a-a
a-a*a
a/(a+a-(a+a)/a)
a//
a++
a--
a/*-+
*/
这样也能识别减法和除法了。
给出一个运行图片。
我们最后要把零碎的东西组合在一起,会有意想不到的惊喜。
ARTELE