给定一个EBNF,用LL(1)算法打印分析过程,C++实现

给定以下的EBNF:

lexp --> atom | list

atom --> number | identifier

list --> (lexp - seq)

lexp-seq --> lexp lexp-seq'

lexp-seq' --> lexp lexp-seq'| ε

打印出编译器分析栈的选择判断过程,look ahead为1。

运行结果截图

实现代码

/* A sample parser for grammar 4.8,C++11 environment is needed.
*  After eliminating the left recursion,the following EBNF is obtained.
*  lexp --> atom | list
*  atom --> number | identifier
*  list --> (lexp - seq)
*  lexp-seq --> lexp lexp-seq'
*  lexp-seq' --> lexp lexp-seq'| ε
*/
#include <iostream>
#include <vector>
#include <cstdlib>
#include <initializer_list>
using namespace std;

typedef vector<string> StackType;
typedef vector<vector<string>> RecordType;

const string ParseStr = "(a(b(2))(c))$";
const int StrLen = ParseStr.size();
int offset = 0;
char LookAhead;

StackType   ParseStack = {"$","lexp"};
StackType   Actions;
RecordType  recorder = {ParseStack};

//Five nonterminals in all
void lexp();
void atom();
void list();
void lexp_seq();
void lexp_seq_1();

void error()
{
    fprintf(stderr,"Error!\n");
    exit(1);
}

void match(const string &target)
{
    int len = target.size();
    if(ParseStr.substr(offset,len) == target)
    {
        offset += len;
//        cout<<"match "<<target<<endl;
    }
    else
        error();
}

//Add a step of derivation decision to the ParseStack
void AddRecord(const initializer_list<string>& r)
{
    for(auto &r_:r)
    {
        ParseStack.push_back(r_);
    }
    recorder.push_back(ParseStack);
}

//Record the derivation dicision
void AddAction(const string &a)
{
    Actions.push_back(a);
}

void lexp()
{
    LookAhead = ParseStr[offset];
    //Pop self
    ParseStack.pop_back();
    if(LookAhead == '(')
    {
        AddRecord({"list"});
        AddAction("lexp --> list");
        list();
    }
    else if(isdigit(LookAhead) || isalpha(LookAhead))
    {
        AddRecord({"atom"});
        AddAction("lexp --> atom");
        atom();
    }
    else error();
}

void list()
{
    //Pop self
    ParseStack.pop_back();
    AddRecord({")","lexp-seq","("});
    AddAction("list --> (lexp-seq)");
    match("(");
    AddAction("match (");
    //Pop '('
    ParseStack.pop_back();
    recorder.push_back(ParseStack);
    lexp_seq();
}

void atom()
{
    LookAhead = ParseStr[offset];
    //Pop self
    ParseStack.pop_back();
    if(isalpha(LookAhead))
    {
        AddRecord({"identifier"});
        AddAction("atom --> identifier");
        while (isalpha(ParseStr[offset])||isdigit(ParseStr[offset]))
        {
            string s = ParseStr.substr(offset,1);
            match(s);
        }
        AddAction("match id");
    }
    else if(isdigit(LookAhead))
    {
        AddRecord({"number"});
        AddAction("atom --> number");
        while (isdigit(ParseStr[offset]))
        {
            string s = ParseStr.substr(offset,1);
            match(s);
        }
        AddAction("match num");
        //Don't allow the format like '1xx'
        if(isalpha(ParseStr[offset]))
            error();
    }
    else
        error();
    ParseStack.pop_back();
    recorder.push_back(ParseStack);
}

void lexp_seq()
{
    //Pop self
    ParseStack.pop_back();
    AddRecord({"lexp-seq'","lexp"});
    AddAction("lexp-seq --> lexp lexp-seq'");
    lexp();
    lexp_seq_1();
}

void lexp_seq_1()
{
    //Pop self
    ParseStack.pop_back();
    LookAhead = ParseStr[offset];
    //lexp-seq'--> ε
    if(LookAhead == ')')
    {
        recorder.push_back(ParseStack);
        AddAction("lexp-seq'--> ε");
        match(")");
        AddAction("match )");
        ParseStack.pop_back();
        recorder.push_back(ParseStack);
    }
    else
    {
        AddRecord({"lexp-seq'","lexp"});
        AddAction("lexp-seq'--> lexp lexp-seq'");
        lexp();
        lexp_seq_1();
    }
}

int main()
{
    int lineno = 0;
    lexp();
    match("$");
    if (offset == StrLen)
        cout<<"Success!"<<endl;
    else
        error();
    AddAction("Accept");
    for(auto &s : recorder)
    {
        for(auto & i : s)
        {
            cout<<i<<" ";
        }
        cout<<"\t\t\t\t\t\t\t\t\t\t"<<Actions[lineno]<<endl;
        ++lineno;
    }
    return 0;
}

posted @ 2021-02-26 22:19  LWenH  阅读(114)  评论(0编辑  收藏  举报