LL(1)语法分析之first、follow的实现

来源:互联网 发布:录制脚本的软件 编辑:程序博客网 时间:2024/06/06 00:12


#include <cassert>
#include <functional>
#include <iostream>
#include <map>
#include <tr1/memory>
#include <set>
#include <vector>

class non_copy_constructor {
public:
    non_copy_constructor();

private:
    non_copy_constructor(const non_copy_constructor &);

};

class has_virtual_destructor {
public:
    virtual ~has_virtual_destructor();

};

class grammar_symbol:public non_copy_constructor, public has_virtual_destructor {
    class _compare_type;

protected:
    grammar_symbol();

public:
    typedef std::tr1::shared_ptr<const grammar_symbol> handle_type;
    typedef std::set<handle_type, _compare_type> set_type;

    virtual const set_type first() const=0;
    virtual const set_type follow() const=0;

};

class symbol_factor;

class end_symbol:public grammar_symbol {
    friend class symbol_factor;

public:
    const set_type first() const;
    const set_type follow() const;

};

class empty_symbol:public grammar_symbol {
    friend class symbol_factor;

public:
    const set_type first() const;
    const set_type follow() const;

};

class named_symbol:public grammar_symbol {
protected:
    named_symbol(char);

public:
    char name() const;

private:
    const char _name_m;

};

class termination_symbol:public named_symbol {
    friend class symbol_factor;

protected:
    termination_symbol(char);

public:
    const set_type first() const;
    const set_type follow() const;

};

class nonterminal_symbol:public named_symbol {
    friend class symbol_factor;

protected:
    nonterminal_symbol(char, const std::vector<std::vector<handle_type> > &);

public:
    const set_type first() const;
    const set_type follow() const;

private:
    void _production_first(set_type &, const std::vector<handle_type> &) const;

    void _import_nonempty_symbol(set_type &, handle_type) const;

    void _import_other_symbol(set_type &, const std::vector<handle_type> &) const;

    bool _have_empty_symbol(handle_type) const;

    void _productions_follow(set_type &, const nonterminal_symbol *) const;

    void _production_follow(set_type &, const nonterminal_symbol *, const std::vector<handle_type> &) const;

    void _include_this_follow(set_type &, const nonterminal_symbol *) const;

    const std::vector<std::vector<handle_type> > _productions_m;

};

class symbol_factor {
    friend class nonterminal_symbol;

    static grammar_symbol::handle_type get_end_symbol();

public:
    typedef std::map<int, grammar_symbol::handle_type> map_type;

    static grammar_symbol::handle_type get_empty_symbol();

    static grammar_symbol::handle_type get_termination_symbol(char);

    static grammar_symbol::handle_type get_nonterminal_symbol(char);

    static void set_nonterminal_symbol(char, const std::vector<std::vector<grammar_symbol::handle_type> > &);

    static void set_start_symbol(char);

private:
    static map_type _symbols_s;
    static char _start_s;

};

class grammar_symbol::_compare_type:public std::binary_function<grammar_symbol::handle_type, grammar_symbol::handle_type, bool> {
public:
    result_type operator()(first_argument_type, second_argument_type);

};

non_copy_constructor::non_copy_constructor() {}

has_virtual_destructor::~has_virtual_destructor() {}

grammar_symbol::grammar_symbol() {}

const grammar_symbol::set_type end_symbol::first() const {assert(false);}

const grammar_symbol::set_type end_symbol::follow() const {assert(false);}

const grammar_symbol::set_type empty_symbol::first() const {
    set_type _result;
    _result.insert(symbol_factor::get_empty_symbol());
    return _result;
}

const grammar_symbol::set_type empty_symbol::follow() const {assert(false);}

named_symbol::named_symbol(char _name):_name_m(_name) {}

char named_symbol::name() const {return _name_m;}

termination_symbol::termination_symbol(char _name):named_symbol(_name) {}

const grammar_symbol::set_type termination_symbol::first() const {
    set_type _result;
    _result.insert(symbol_factor::get_termination_symbol(name()));
    return _result;
}

const grammar_symbol::set_type termination_symbol::follow() const {assert(false);}

nonterminal_symbol::nonterminal_symbol(char _name, const std::vector<std::vector<handle_type> > &_productions):named_symbol(_name), _productions_m(_productions) {}

const grammar_symbol::set_type nonterminal_symbol::first() const {
    set_type _result;
    for(std::vector<std::vector<handle_type> >::const_iterator _i=_productions_m.begin(); _i!=_productions_m.end(); ++_i)
    _production_first(_result, *_i);
    return _result;
}

const grammar_symbol::set_type nonterminal_symbol::follow() const {
    set_type _result;
    if(name()==symbol_factor::_start_s)
    _result.insert(symbol_factor::get_end_symbol());
    for(symbol_factor::map_type::const_iterator _i=symbol_factor::_symbols_s.begin(); _i!=symbol_factor::_symbols_s.end(); ++_i) {
    const nonterminal_symbol *_p=dynamic_cast<const nonterminal_symbol *>(_i->second.get());
    if(_p&&_p->name()!=name()) _productions_follow(_result, _p);
    }
    return _result;
}

void nonterminal_symbol::_production_first(set_type &_result, const std::vector<handle_type> &_curr) const {
    _import_nonempty_symbol(_result, _curr.front());
    _import_other_symbol(_result, _curr);
}

void nonterminal_symbol::_import_nonempty_symbol(set_type &_result, handle_type _curr) const {
    const set_type _curr_first=_curr->first();
    for(set_type::const_iterator _i=_curr_first.begin(); _i!=_curr_first.end(); ++_i)
    if(!dynamic_cast<const empty_symbol *>(_i->get()))
        _result.insert(*_i);
}

void nonterminal_symbol::_import_other_symbol(set_type &_result, const std::vector<handle_type> &_curr) const {
    for(std::vector<handle_type>::const_iterator _i=_curr.begin(); _i!=_curr.end(); ++_i) {
    if(!_have_empty_symbol(*_i)) return;
    if(_i+1!=_curr.end())
        _import_nonempty_symbol(_result, *(_i+1));
    }
    _result.insert(symbol_factor::get_empty_symbol());
}

bool nonterminal_symbol::_have_empty_symbol(handle_type _curr) const {
    const set_type &_curr_first=_curr->first();
    for(set_type::const_iterator _i=_curr_first.begin(); _i!=_curr_first.end(); ++_i)
    if(dynamic_cast<const empty_symbol *>(_i->get()))
        return true;
    return false;
}

void nonterminal_symbol::_productions_follow(set_type &_result, const nonterminal_symbol *_ptr) const {
    for(std::vector<std::vector<handle_type> >::const_iterator _i=_ptr->_productions_m.begin(); _i!=_ptr->_productions_m.end(); ++_i)
    _production_follow(_result, _ptr, *_i);
}

void nonterminal_symbol::_production_follow(set_type &_result, const nonterminal_symbol *_ptr, const std::vector<handle_type> &_production) const {
    for(std::vector<handle_type>::const_iterator _i=_production.begin(); _i!=_production.end(); ++_i) {
    const nonterminal_symbol *_p=dynamic_cast<const nonterminal_symbol *>(_i->get());
    if(_p&&_p->name()==name()) {
        if(_i+1!=_production.end())
        _import_nonempty_symbol(_result, *(_i+1));
        if(_i+1==_production.end()||_have_empty_symbol(*(_i+1)))
        _include_this_follow(_result, _ptr);
    }
    }
}

void nonterminal_symbol::_include_this_follow(set_type &_result, const nonterminal_symbol *_ptr) const {
    const set_type _curr_follow=_ptr->follow();
    _result.insert(_curr_follow.begin(), _curr_follow.end());
}

grammar_symbol::_compare_type::result_type grammar_symbol::_compare_type::operator()(first_argument_type _x, second_argument_type _y) {
    if(!dynamic_cast<const empty_symbol *>(_x.get())) return true;
    if(!dynamic_cast<const empty_symbol *>(_y.get())) return false;
    return dynamic_cast<const named_symbol *>(_x.get())->name()<dynamic_cast<const named_symbol *>(_y.get())->name();
}

grammar_symbol::handle_type symbol_factor::get_end_symbol() {
    return _symbols_s[-1].get()?_symbols_s[-1]:_symbols_s[-1]=grammar_symbol::handle_type(new end_symbol);
}

grammar_symbol::handle_type symbol_factor::get_empty_symbol() {
    return _symbols_s[0].get()?_symbols_s[0]:_symbols_s[0]=grammar_symbol::handle_type(new empty_symbol);
}

grammar_symbol::handle_type symbol_factor::get_termination_symbol(char _name) {
    assert(islower(_name));
    return _symbols_s[_name].get()?_symbols_s[_name]:_symbols_s[_name]=grammar_symbol::handle_type(new termination_symbol(_name));
}

grammar_symbol::handle_type symbol_factor::get_nonterminal_symbol(char _name) {
    assert(isupper(_name)&&_symbols_s[_name].get());
    return _symbols_s[_name];
}

void symbol_factor::set_nonterminal_symbol(char _name, const std::vector<std::vector<grammar_symbol::handle_type> > &_productions) {
    assert(isupper(_name)&&!_symbols_s[_name].get()&&!_productions.empty()&&!_productions.front().empty());
    _symbols_s[_name]=grammar_symbol::handle_type(new nonterminal_symbol(_name, _productions));
}

void symbol_factor::set_start_symbol(char _name) {
    assert(isupper(_name)&&_symbols_s[_name]);
    _start_s=_name;
}

symbol_factor::map_type symbol_factor::_symbols_s;

char symbol_factor::_start_s;

int main(int argc, char *argv[]) {
    std::vector<std::vector<grammar_symbol::handle_type> > _psB;
    std::vector<grammar_symbol::handle_type> _pB;
    _pB.push_back(symbol_factor::get_termination_symbol('b'));
    _psB.push_back(_pB);
    symbol_factor::set_nonterminal_symbol('B', _psB);
    std::vector<std::vector<grammar_symbol::handle_type> > _psA;
    std::vector<grammar_symbol::handle_type> _pA;
    _pA.push_back(symbol_factor::get_nonterminal_symbol('B'));
    _pA.push_back(symbol_factor::get_termination_symbol('a'));
    _psA.push_back(_pA);
    symbol_factor::set_nonterminal_symbol('A', _psA);
    symbol_factor::set_start_symbol('A');
    const grammar_symbol::set_type _follow=symbol_factor::get_nonterminal_symbol('B')->follow();
    std::cout<<"{";
    for(grammar_symbol::set_type::const_iterator _i=_follow.begin(); _i!=_follow.end(); ++_i) {
        if(dynamic_cast<const end_symbol *>(_i->get())) {
        if(_i!=_follow.begin())
        std::cout<<", [end]";
        else
        std::cout<<"[end]";
    }
    else if(dynamic_cast<const empty_symbol *>(_i->get())) {
        if(_i!=_follow.begin())
        std::cout<<", [empty]";
        else
        std::cout<<"[empty]";
    }
     else {
        if(_i!=_follow.begin())
        std::cout<<", "<<dynamic_cast<const termination_symbol *>(_i->get())->name();
        else
        std::cout<<dynamic_cast<const termination_symbol *>(_i->get())->name();
    }
    }
    std::cout<<"}"<<std::endl;
    return 0;
}