这是一个基于 LL(1) 文法的语法分析器,可以对输入的字符串进行语法分析,判断其是否符合该文法。

该程序使用了一个向量 v 来存储分析过程中的每一步推导式以及分析栈的状态,使用一个模拟栈 stackStr 来模拟语法分析器中的分析栈,使用一个字符串 ch 来存储每一步分析的字符。具体实现过程如下:

  1. 定义了一个基于 LL(1) 文法的语法分析器,该文法包含以下产生式:
E-->TG
G-->+TG | ε
T-->FS
S-->*FS | ε
F-->(E) | i

其中,E、G、T、S、F 均为非终结符,+、*、(、)、i 均为终结符。

  1. 运行程序后,用户可以输入要进行语法分析的字符串,以 # 号结束。

  2. 对于输入的每一个字符串,程序首先将向量 v、模拟栈 stackStr、当前分析字符 ch 进行初始化。

  3. 然后程序从文法的开始符号 E 开始进行语法分析,调用 E() 函数。在 E() 函数中,首先将 'E-->TG' 作为推导式存入向量 v 中,然后调用 T() 函数进行下一步分析。

  4. T() 函数中,首先将 'T-->FS' 作为推导式存入向量 v 中,然后调用 F() 函数进行下一步分析。

  5. F() 函数中,如果当前分析字符为左括号 '(',则将 '(E)' 作为推导式存入向量 v 中,然后调用 E() 函数进行下一步分析;如果当前分析字符为终结符 'i',则将 'i' 作为推导式存入向量 v 中,否则提示错误信息。

  6. S() 函数中,如果当前分析字符为 '*',则将 'FS' 作为推导式存入向量 v 中,然后调用 F() 函数进行下一步分析;如果当前分析字符不为 '',则将 'ε' 作为推导式存入向量 v 中。

  7. G() 函数中,如果当前分析字符为 '+',则将 '+TG' 作为推导式存入向量 v 中,然后调用 T() 函数进行下一步分析;如果当前分析字符不为 '+',则将 'ε' 作为推导式存入向量 v 中。

  8. 在每一步分析中,程序都会将推导式和当前分析栈的状态存入向量 v 中,并将当前分析字符存入字符串 ch 中。

  9. 最后,程序通过检查是否已经到达输入串的末尾或输入串是否以 # 号结束来判断输入串是否符合该文法。如果符合,则输出分析过程中向量 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;
}
LL(1) 文法语法分析器:原理与实现解析

原文地址: https://www.cveoy.top/t/topic/oaln 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录