LL(1) 文法语法分析器:原理与实现解析
这是一个基于 LL(1) 文法的语法分析器,可以对输入的字符串进行语法分析,判断其是否符合该文法。
该程序使用了一个向量 v 来存储分析过程中的每一步推导式以及分析栈的状态,使用一个模拟栈 stackStr 来模拟语法分析器中的分析栈,使用一个字符串 ch 来存储每一步分析的字符。具体实现过程如下:
- 定义了一个基于 LL(1) 文法的语法分析器,该文法包含以下产生式:
E-->TG
G-->+TG | ε
T-->FS
S-->*FS | ε
F-->(E) | i
其中,E、G、T、S、F 均为非终结符,+、*、(、)、i 均为终结符。
-
运行程序后,用户可以输入要进行语法分析的字符串,以 # 号结束。
-
对于输入的每一个字符串,程序首先将向量
v、模拟栈stackStr、当前分析字符ch进行初始化。 -
然后程序从文法的开始符号 E 开始进行语法分析,调用
E()函数。在E()函数中,首先将 'E-->TG' 作为推导式存入向量v中,然后调用T()函数进行下一步分析。 -
在
T()函数中,首先将 'T-->FS' 作为推导式存入向量v中,然后调用F()函数进行下一步分析。 -
在
F()函数中,如果当前分析字符为左括号 '(',则将 '(E)' 作为推导式存入向量v中,然后调用E()函数进行下一步分析;如果当前分析字符为终结符 'i',则将 'i' 作为推导式存入向量v中,否则提示错误信息。 -
在
S()函数中,如果当前分析字符为 '*',则将 'FS' 作为推导式存入向量v中,然后调用F()函数进行下一步分析;如果当前分析字符不为 '',则将 'ε' 作为推导式存入向量v中。 -
在
G()函数中,如果当前分析字符为 '+',则将 '+TG' 作为推导式存入向量v中,然后调用T()函数进行下一步分析;如果当前分析字符不为 '+',则将 'ε' 作为推导式存入向量v中。 -
在每一步分析中,程序都会将推导式和当前分析栈的状态存入向量
v中,并将当前分析字符存入字符串ch中。 -
最后,程序通过检查是否已经到达输入串的末尾或输入串是否以 # 号结束来判断输入串是否符合该文法。如果符合,则输出分析过程中向量
v中存储的推导式和分析栈的状态;如果不符合,则输出错误信息。
代码示例
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
using namespace std;
//变量定义
string s, str, stackStr;//s:输入串、str:中间变量、stackStr : 模拟栈
int i;
string ch;//当前分析字符
vector<string> v;//字符串类型的向量(文法+分析栈)
//函数声明
void E(); //E-->TG
void G(); //G-->+TG|ε
void T(); //T-->FS
void S(); //S-->*FS|ε
void F(); //F-->(E)|i
void err(); //提示错误信息
int check();//验证是否已经到栈底
void push(string pre, string value);//将字符串存入输出栈
/**
* 函数功能:提示错误信息
*/
void err()
{
cout << 'ERROR' << endl;
exit(0);
}
/**
* 函数功能:将字符串存入输出栈
*/
void push(string pre, string value)
{
ch += s[i];
int idx = stackStr.find_first_of(pre[0], 0);//从头开始找到pre开始的位置
if (value != 'ε')//不是空字时
{
string value1;
value1 = value;
if (value[0] == '+')value1 = 'TG';
if (value[0] == '*')value1 = 'FS';
if (value[0] == '(')value1 = 'E';
if (value[0] == 'i')value1 = '';
stackStr.replace(idx, 1, value1);//将第一个pre的位置替换为value
}
else
{
stackStr.erase(idx, 1);//删除从该位置开始的1个字符
}
v.push_back((pre + value + ',' + stackStr));//将对应的表达式和栈的内容存加入在向量v尾部
}
/**
* 函数功能:验证是否已经到栈底
*/
int check()
{
if (i >= s.size()) {
return 1;
}
else if (s[i] == '#')
{
ch += '#';
return 1;
}
return 0;
}
/**
* 函数功能:E-->TG
*/
void E()
{
push('E-->', 'TG');
T();
G();
}
/**
* 函数功能:G-->+TG|ε
*/
void G() {
if (s[i] == '+')
{
str = s[i];
str += 'TG';
i++;
push('G-->', str);
T();
G();
}
else
{
push('G-->', 'ε');
}
}
/**
* 函数功能:T-->FS
*/
void T()
{
push('T-->', 'FS');
F();
S();
}
/**
* 函数功能:S-->*FS|ε
*/
void S() {
if (s[i] == '*')
{
str = s[i];
str += 'FS';
i++;
push('S-->', str);
F();
S();
}
else
{
push('S-->', 'ε');
}
}
/**
* 函数功能:F-->(E)|i
*/
void F() {
if (s[i] == '(')
{
i++;
push('F-->', '(E)');
E();
if (s[i] == ')')
{
i++;
}
else
{
err();
}
}
else if (s[i] == 'i')
{
i++;
push('F-->', 'i');
}
else
{
err();
}
}
/**
* 函数功能:主函数
*/
int main() {
cout << '请输入字符串 (以#号结束) ' << endl;
while (cin >> s) //输入要分析的字符串
{
v.clear();
i = 0;
stackStr = 'E#';//初始化栈
E();
if (check())
{
cout << ' 输入串分析正确! ' << endl;
cout << '推导过程如下: ' << endl;
cout << '文法 分析栈 当前分析字符
';
cout << 'E E# ' << s[0] << endl;//初始栈的内容
int i;
for (i = 0; i < v.size(); i++)
{
cout << v[i].substr(0, v[i].find_first_of(',', 0)) << ' ';
cout << setiosflags(ios::right) << setw(10) << v[i].substr(v[i].find_first_of(',', 0) + 1) << ' ';
cout << ch[i] << endl;
}
cout << ' 请继续输入字符串 (以#号结束) ' << endl;
}
else
cout << ' 输入串不符合该文法 ' << endl;
}
return 0;
}
原文地址: https://www.cveoy.top/t/topic/oaln 著作权归作者所有。请勿转载和采集!