提升解析器中的 Spirit 段错误

2024-04-29

我一直在尝试将我在本科编译器中编写的一些 lex 和 yacc 代码转换为精神代码以学习精神,我发现了一个我似乎无法弄清楚的段错误。我这样写了词法分析器:

namespace lex = boost::spirit::lex;

enum Tokens
{
    k_andTok = 1,
    k_def = 2,
    k_elihw = 3,
    k_elseTok = 4,
    k_falseTok = 5,
    k_fed = 6,
    k_fi = 7,
    k_ifTok = 8,
    k_input = 9,
    k_notTok = 10,
    k_orTok = 11,
    k_print = 12,
    k_returnTok = 13,
    k_trueTok = 14,
    k_whileTok = 15,
    k_plues = 16,
    k_minus = 17,
    k_mult = 18,
    k_div = 19,
    k_bang = 20,
    k_equalTo = 21,
    k_greaterEq = 22,
    k_lessEq = 23,
    k_notEq = 24,
    k_less = 25,
    k_greater = 26,
    k_assign = 27,
    k_comma = 28,
    k_colon = 29,
    k_leftParen = 30,
    k_rightParen = 31,
    k_leftBracket = 32,
    k_rightBracket = 33,
    k_nonTerminal = 34,
    k_terminal = 35
};

template <typename Lexer>
struct LexerTokens : lex::lexer<Lexer>
{
    LexerTokens() :
       whiteSpace("[ \\t\\n]"),
       andTok("and"),
       def("def"),
       elihw("elihw"),
       elseTok("else"),
       falseTok("false"),
       fed("fed"),
       fi("fi"),
       ifTok("if"),
       input("input"),
       notTok("not"),
       orTok("or"),
       print("print"),
       returnTok("return"),
       trueTok("true"),
       whileTok("while"),
       plus("\\+"),
       minus("\\-"),
       mult("\\*"),
       div("\\/"),
       bang("\\!"),
       equalTo("=="),
       greaterEq(">="),
       lessEq("<="),
       notEq("!="),
       less("<"),
       greater(">"),
       assign("="),
       comma(","),
       colon(":"),
       leftParen("\\("),
       rightParen("\\)"),
       leftBracket("\\["),
       rightBracket("\\["),
       nonTerminal("[a-z][a-zA-Z0-9]*"),
       terminal("[0-9]")
    {
        this->self("WHITESPACE") = whiteSpace;

        this->self.add
            (andTok, k_andTok)
            (def, k_def)
            (elihw, k_elihw)
            (elseTok, k_elseTok)
            (falseTok, k_falseTok)
            (fed, k_fed)
            (fi, k_fi)
            (ifTok, k_ifTok)
            (andTok, k_andTok)
            (input, k_input)
            (notTok, k_notTok)
            (orTok, k_orTok)
            (print, k_print)
            (returnTok, k_returnTok)
            (trueTok, k_trueTok)
            (whileTok, k_whileTok)
            (plus, k_plues)
            (minus, k_minus)
            (mult, k_mult)
            (div, k_div)
            (bang, k_bang)
            (equalTo, k_equalTo)
            (greaterEq, k_greaterEq)
            (lessEq, k_lessEq)
            (notEq, k_notEq)
            (less, k_less)
            (greater, k_greater)
            (assign, k_assign)
            (comma, k_comma)
            (colon, k_colon)
            (leftParen, k_leftParen)
            (rightParen, k_rightParen)
            (leftBracket, k_leftBracket)
            (rightBracket, k_rightBracket)
            (nonTerminal, k_nonTerminal)
            (terminal, k_terminal);
    }

    lex::token_def<lex::omit> whiteSpace;
    lex::token_def<std::string> andTok;
    lex::token_def<std::string> def;
    lex::token_def<std::string> elihw;
    lex::token_def<std::string> elseTok;
    lex::token_def<std::string> falseTok;
    lex::token_def<std::string> fed;
    lex::token_def<std::string> fi;
    lex::token_def<std::string> ifTok;
    lex::token_def<std::string> input;
    lex::token_def<std::string> notTok;
    lex::token_def<std::string> orTok;
    lex::token_def<std::string> print;
    lex::token_def<std::string> returnTok;
    lex::token_def<std::string> trueTok;
    lex::token_def<std::string> whileTok;
    lex::token_def<std::string> plus;
    lex::token_def<std::string> minus;
    lex::token_def<std::string> mult;
    lex::token_def<std::string> div;
    lex::token_def<std::string> bang;
    lex::token_def<std::string> equalTo;
    lex::token_def<std::string> greaterEq;
    lex::token_def<std::string> lessEq;
    lex::token_def<std::string> notEq;
    lex::token_def<std::string> less;
    lex::token_def<std::string> greater;
    lex::token_def<std::string> assign;
    lex::token_def<std::string> comma;
    lex::token_def<std::string> colon;
    lex::token_def<std::string> leftParen;
    lex::token_def<std::string> rightParen;
    lex::token_def<std::string> leftBracket;
    lex::token_def<std::string> rightBracket;
    lex::token_def<std::string> nonTerminal;
    lex::token_def<std::string> terminal;
};

和解析器

namespace qi = boost::spirit::qi;
template <typename Iterator, typename Skipper>
struct InterpreterGrammar : qi::grammar<Iterator, Skipper>
{        
//    using boost::phoenix::ref;
//    using boost::phoenix::size;

    template <typename TokenDef>
    InterpreterGrammar(TokenDef const& tok)
        : InterpreterGrammar::base_type(start),
        connect(0)
    {
        start %= functionList >> endList >> qi::eoi;

        // different expressions
        exp %= exp >> qi::token(k_equalTo) >> exp
              |
              exp >> qi::token(k_notEq) >> exp
              |
              exp >> qi::token(k_less) >> exp
              |
              exp >> qi::token(k_lessEq) >> exp
              |
              exp >> qi::token(k_greater) >> exp
              |
              exp >> qi::token(k_greaterEq) >> exp
              |
              exp >> qi::token(k_andTok) >> exp
              |
              exp >> qi::token(k_orTok) >> exp
              |
              qi::token(k_notTok) >> exp 
              |
              exp >> qi::token(k_plues) >> exp
              |
              exp >> qi::token(k_minus) >> exp
              |
              exp >> qi::token(k_mult) >> exp
              |
              qi::token(k_minus) >> exp
              |
              qi::token(k_leftParen) >> exp >> qi::token(k_rightParen)
              |
              qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp >> qi::token(k_rightBracket) 
              |
              qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> qi::token(k_rightParen)
              |
              qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> exp >> qi::token(k_rightParen)
              |
              qi::token(k_nonTerminal)
              |
              qi::token(k_terminal)
              |
              qi::token(k_trueTok)
              |
              qi::token(k_falseTok);

        // parameter list
        paramList %= paramList >> qi::token(k_comma) >> exp
                    |
                    exp;

        // return statements
        returnStatement %= returnStatement >> exp
                         |
                         returnStatement;

        // function call statements
        callStatement %= qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> qi::token(k_rightParen)
                        |
                        qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> paramList >> qi::token(k_rightParen);

        // variable assignment
        assignmentStatement %= qi::token(k_nonTerminal) >> qi::token(k_assign) >> exp
                              |
                              qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp
                                  >> qi::token(k_rightBracket) >> qi::token(k_assign) >> exp;

        // list of integers
        intList %= intList >> qi::token(k_comma) >> qi::token(k_terminal)
                  |
                  qi::token(k_terminal);

        // print out a variable
        printStatement %= qi::token(k_print) >> exp;

        // take input
        inputStatement %= qi::token(k_nonTerminal) >> qi::token(k_input);

        // conditional statement
        conditionStatement %= qi::token(k_ifTok) >> exp >> qi::token(k_colon) >> statements >> optionalElse;

        // consitions have optional else
        optionalElse %= qi::token(k_elseTok) >> qi::token(k_colon) >> statements
                       |
                       qi::eps;

        // while loop
        whileStatement %= qi::token(k_whileTok) >> exp >> qi::token(k_colon) >> statements >> qi::token(k_elihw);

        // actual program statements
        endList %= endList >> end
                  |
                  end;

        // end possibilities of program in global space
        end %= callStatement
              |
              printStatement
              |
              qi::token(k_nonTerminal) >> qi::token(k_assign) >> qi::token(k_input)
              |
              qi::token(k_nonTerminal) >> qi::token(k_assign) >> exp
              |
              qi::token(k_nonTerminal) >> qi::token(k_assign) >> qi::token(k_leftBracket) >> intList
                  >> qi::token(k_rightBracket)
              |
              qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp >> qi::token(k_rightBracket)
                  >> qi::token(k_assign) >> exp;

        // function parameters
        paramList %= paramList >> qi::token(k_comma) >> qi::token(k_nonTerminal)
                    |
                    qi::token(k_nonTerminal)
                    |
                    qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> qi::token(k_rightBracket);

        // define a statement as assignment print input condition while or call
        statement %= assignmentStatement
                    |
                    printStatement
                    |
                    inputStatement
                    |
                    conditionStatement
                    |
                    whileStatement
                    |
                    callStatement
                    |
                    returnStatement;

        // general statement list
        statements %= statements >> statement
                     |
                     statement;

        // functions
        functionList %= qi::token(k_def) >> qi::token(k_nonTerminal) >> qi::token(k_leftParen)
                           >> paramList >> qi::token(k_rightParen) >> qi::token(k_colon)
                           >> statements >> qi::token(k_fed)
                       |
                       qi::token(k_def) >> qi::token(k_nonTerminal) >> qi::token(k_leftParen)
                           >> qi::token(k_rightParen) >> qi::token(k_colon) >> statements >> qi::token(k_fed);
                       | qi::eps;

        BOOST_SPIRIT_DEBUG_NODES((start)(functionList));
        debug(start);
    }

    qi::rule<Iterator, Skipper> start;
    qi::rule<Iterator, Skipper> functionList;
    qi::rule<Iterator, Skipper> endList;
    qi::rule<Iterator, Skipper> paramList;
    qi::rule<Iterator, Skipper> statements;
    qi::rule<Iterator, Skipper> statement;
    qi::rule<Iterator, Skipper> assignmentStatement;
    qi::rule<Iterator, Skipper> printStatement;
    qi::rule<Iterator, Skipper> inputStatement;
    qi::rule<Iterator, Skipper> conditionStatement;
    qi::rule<Iterator, Skipper> whileStatement;
    qi::rule<Iterator, Skipper> callStatement;
    qi::rule<Iterator, Skipper> returnStatement;
    qi::rule<Iterator, Skipper> exp;
    qi::rule<Iterator, Skipper> intList;
    qi::rule<Iterator, Skipper> optionalElse;
    qi::rule<Iterator, Skipper> end;
};

以及主要部分

int main(int argc, char** argv)
{
namespace lex = boost::spirit::lex;
namespace qi = boost::spirit::qi;

typedef lex::lexertl::token< char const*, lex::omit, boost::mpl::true_ > token_type;
typedef lex::lexertl::lexer<token_type> lexer_type;
typedef interpreter::LexerTokens<lexer_type>::iterator_type iterator_type;
typedef qi::in_state_skipper<interpreter::LexerTokens<lexer_type>::lexer_def> skipper_type;

LexerTokens< lexer_type > lexer;
InterpreterGrammar< iterator_type, skipper_type > parser(lexer);

// read the file
if (argc != 2)
{
    std::cout << "File required" << std::endl;
    return 1;
}

std::ifstream t(argv[1]); 

t.seekg(0, std::ios::end);   
sourceCode.reserve(t.tellg());
t.seekg(0, std::ios::beg);

sourceCode.assign(std::istreambuf_iterator<char>(t), 
                  std::istreambuf_iterator<char>());

char const* first = sourceCode.c_str();
char const* last = &first[sourceCode.size()];
bool r = lex::tokenize_and_phrase_parse(first, last, lexer, parser, qi::in_state("WHITESPACE")[lexer.self]);

std::cout << "Remaining " << std::string(first,last) << std::endl;
std::cout << "R is " << r << std::endl;
}

该语言中的一个例子是:

def add(x,y) :                                                                                                                              
  if (x <= 0) : return y fi
   return 1 + add(x-1,y) 
fed
y = add(5,4)
print y

我遇到的错误是调用语法时解析器段错误。

我看到如果我

  • 注释掉部分相关规则(funtionList)直至该部分 语法需要调用另一个规则(如 paramList)
  • 并删除发送到词法分析器/解析器的部分源代码 仅包括令牌部分,

语法不会出现段错误并正确解析表达式。

当我在调试器中运行代码时,我看到在 代码段错误,打印一个大表达式,其中所有成员都具有 字符串说,

读取变量时出错:无法访问地址 0x7fffff7fefe0 处的内存

我检查了其他类似的帖子,其中的错误是精神上的段错误, 然而,

  • 我不认为这个错误是由于语法递归造成的,或者 规则中存在临时语法,因为我编写了 LL 解析器 以前在 lex 和 yacc 中成功地可以解析该语句,并且我 相信所有规则将在程序的整个运行过程中存在。

任何正确方向的观点或对当前代码的批评都将是 非常感激。


如果您使用AddressSanitizer,它会告诉您:

<start>...
  <try>[]</try>...
ASAN:DEADLYSIGNAL...
=================================================================...
==8985==ERROR: AddressSanitizer: stack-overflow on address 0x7ffeb280dfc8 (pc 0x0000004c9cf6 bp 0x7f...
    #0 0x4c9cf5 in __asan_memcpy (/home/sehe/Projects/stackoverflow/sotest+0x4c9cf5)...
    #1 0x68eb77 in bool boost::spirit::any_if<boost::spirit::traits::attribute_not_unused<boost::spi...
    #2 0x68e844 in bool boost::spirit::qi::sequence_base<boost::spirit::qi::sequence<boost::fusion::...
    #3 0x68e487 in bool boost::spirit::qi::sequence_base<boost::spirit::qi::sequence<boost::fusion::...
    #4 0x68e190 in bool boost::spirit::qi::detail::alternative_function<boost::spirit::lex::lexertl:...
    #5 0x68de4a in bool boost::spirit::qi::detail::alternative_function<boost::spirit::lex::lexertl:...
    #6 0x68d8b5 in bool boost::spirit::qi::detail::alternative_function<boost::spirit::lex::lexertl:...
    #7 0x6e085c in bool boost::fusion::detail::linear_any<boost::fusion::cons_iterator<boost::fusion...
    #8 0x6e053f in bool boost::fusion::detail::any<boost::fusion::cons<boost::spirit::qi::sequence<b...
    #9 0x6e0218 in bool boost::fusion::any<boost::fusion::cons<boost::spirit::qi::sequence<boost::fu...
    #10 0x6dffc5 in bool boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::seque...
    #11 0x6dfbf7 in bool boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boo...
    #12 0x6de330 in boost::detail::function::function_obj_invoker4<boost::spirit::qi::detail::parser...
    #13 0x5d633a in boost::function4<bool, boost::spirit::lex::lexertl::iterator<boost::spirit::lex:...
    #14 0x5d58e8 in bool boost::spirit::qi::rule<boost::spirit::lex::lexertl::iterator<boost::spirit...
    #15 0x5d54e9 in bool boost::spirit::qi::reference<boost::spirit::qi::rule<boost::spirit::lex::le...
    #16 0x5d49bf in bool boost::spirit::qi::detail::fail_function<boost::spirit::lex::lexertl::itera...
    #17 0x68f56c in bool boost::fusion::detail::linear_any<boost::fusion::cons_iterator<boost::fusio...
    #18 0x68f267 in bool boost::fusion::detail::any<boost::fusion::cons<boost::spirit::qi::reference...
    #19 0x68ef6e in bool boost::fusion::any<boost::fusion::cons<boost::spirit::qi::reference<boost::...
    #20 0x68ebae in bool boost::spirit::any_if<boost::spirit::traits::attribute_not_unused<boost::sp...
    #21 0x68e844 in bool boost::spirit::qi::sequence_base<boost::spirit::qi::sequence<boost::fusion:...
    [ snip repeated frames ]
    #250 0x68e487 in bool boost::spirit::qi::sequence_base<boost::spirit::qi::sequence<boost::fusion...


SUMMARY: AddressSanitizer: stack-overflow (/home/sehe/Projects/stackoverflow/sotest+0x4c9cf5) in __a...
==8985==ABORTING...

所以,这显然是左递归导致堆栈溢出。

其他解析器生成器处理它的事实意义不大:Spirit 是一个 PEG 解析器生成器,左递归是不可能的。

你需要重写类似的东西

    exp %= exp >> qi::token(k_equalTo) >> exp

变成一些让 lhs 更具体的东西。

注意:我必须解决您呈现代码的方式中的一些随机问题。这是我用来重现的:

Live On Coliru http://coliru.stacked-crooked.com/a/30b54ffba48eaa22

#include <boost/spirit/include/lex.hpp>
#include <boost/spirit/include/lex_lexertl.hpp>
#include <boost/spirit/include/qi.hpp>
namespace lex = boost::spirit::lex;

namespace interpreter {
    enum Tokens
    {
        k_andTok = 1,
        k_def = 2,
        k_elihw = 3,
        k_elseTok = 4,
        k_falseTok = 5,
        k_fed = 6,
        k_fi = 7,
        k_ifTok = 8,
        k_input = 9,
        k_notTok = 10,
        k_orTok = 11,
        k_print = 12,
        k_returnTok = 13,
        k_trueTok = 14,
        k_whileTok = 15,
        k_plues = 16,
        k_minus = 17,
        k_mult = 18,
        k_div = 19,
        k_bang = 20,
        k_equalTo = 21,
        k_greaterEq = 22,
        k_lessEq = 23,
        k_notEq = 24,
        k_less = 25,
        k_greater = 26,
        k_assign = 27,
        k_comma = 28,
        k_colon = 29,
        k_leftParen = 30,
        k_rightParen = 31,
        k_leftBracket = 32,
        k_rightBracket = 33,
        k_nonTerminal = 34,
        k_terminal = 35
    };

    template <typename Lexer>
    struct LexerTokens : lex::lexer<Lexer>
    {
        LexerTokens() :
           whiteSpace("[ \\t\\n]"),
           andTok("and"),
           def("def"),
           elihw("elihw"),
           elseTok("else"),
           falseTok("false"),
           fed("fed"),
           fi("fi"),
           ifTok("if"),
           input("input"),
           notTok("not"),
           orTok("or"),
           print("print"),
           returnTok("return"),
           trueTok("true"),
           whileTok("while"),
           plus("\\+"),
           minus("\\-"),
           mult("\\*"),
           div("\\/"),
           bang("\\!"),
           equalTo("=="),
           greaterEq(">="),
           lessEq("<="),
           notEq("!="),
           less("<"),
           greater(">"),
           assign("="),
           comma(","),
           colon(":"),
           leftParen("\\("),
           rightParen("\\)"),
           leftBracket("\\["),
           rightBracket("\\["),
           nonTerminal("[a-z][a-zA-Z0-9]*"),
           terminal("[0-9]")
        {
            this->self("WHITESPACE") = whiteSpace;

            this->self.add
                (andTok, k_andTok)
                (def, k_def)
                (elihw, k_elihw)
                (elseTok, k_elseTok)
                (falseTok, k_falseTok)
                (fed, k_fed)
                (fi, k_fi)
                (ifTok, k_ifTok)
                (andTok, k_andTok)
                (input, k_input)
                (notTok, k_notTok)
                (orTok, k_orTok)
                (print, k_print)
                (returnTok, k_returnTok)
                (trueTok, k_trueTok)
                (whileTok, k_whileTok)
                (plus, k_plues)
                (minus, k_minus)
                (mult, k_mult)
                (div, k_div)
                (bang, k_bang)
                (equalTo, k_equalTo)
                (greaterEq, k_greaterEq)
                (lessEq, k_lessEq)
                (notEq, k_notEq)
                (less, k_less)
                (greater, k_greater)
                (assign, k_assign)
                (comma, k_comma)
                (colon, k_colon)
                (leftParen, k_leftParen)
                (rightParen, k_rightParen)
                (leftBracket, k_leftBracket)
                (rightBracket, k_rightBracket)
                (nonTerminal, k_nonTerminal)
                (terminal, k_terminal);
        }

        lex::token_def<lex::omit> whiteSpace;
        lex::token_def<std::string> andTok;
        lex::token_def<std::string> def;
        lex::token_def<std::string> elihw;
        lex::token_def<std::string> elseTok;
        lex::token_def<std::string> falseTok;
        lex::token_def<std::string> fed;
        lex::token_def<std::string> fi;
        lex::token_def<std::string> ifTok;
        lex::token_def<std::string> input;
        lex::token_def<std::string> notTok;
        lex::token_def<std::string> orTok;
        lex::token_def<std::string> print;
        lex::token_def<std::string> returnTok;
        lex::token_def<std::string> trueTok;
        lex::token_def<std::string> whileTok;
        lex::token_def<std::string> plus;
        lex::token_def<std::string> minus;
        lex::token_def<std::string> mult;
        lex::token_def<std::string> div;
        lex::token_def<std::string> bang;
        lex::token_def<std::string> equalTo;
        lex::token_def<std::string> greaterEq;
        lex::token_def<std::string> lessEq;
        lex::token_def<std::string> notEq;
        lex::token_def<std::string> less;
        lex::token_def<std::string> greater;
        lex::token_def<std::string> assign;
        lex::token_def<std::string> comma;
        lex::token_def<std::string> colon;
        lex::token_def<std::string> leftParen;
        lex::token_def<std::string> rightParen;
        lex::token_def<std::string> leftBracket;
        lex::token_def<std::string> rightBracket;
        lex::token_def<std::string> nonTerminal;
        lex::token_def<std::string> terminal;
    };

    namespace qi = boost::spirit::qi;
    template <typename Iterator, typename Skipper>
    struct InterpreterGrammar : qi::grammar<Iterator, Skipper>
    {        
    //    using boost::phoenix::ref;
    //    using boost::phoenix::size;

        template <typename TokenDef>
        InterpreterGrammar(TokenDef const& )
            : InterpreterGrammar::base_type(start)
              //, connect(0)
        {
            start 
                = functionList >> endList >> qi::eoi
                ;

            // different expressions
            exp = exp >> qi::token(k_equalTo) >> exp
                | exp >> qi::token(k_notEq) >> exp
                | exp >> qi::token(k_less) >> exp
                | exp >> qi::token(k_lessEq) >> exp
                | exp >> qi::token(k_greater) >> exp
                | exp >> qi::token(k_greaterEq) >> exp
                | exp >> qi::token(k_andTok) >> exp
                | exp >> qi::token(k_orTok) >> exp
                | qi::token(k_notTok) >> exp 
                | exp >> qi::token(k_plues) >> exp
                | exp >> qi::token(k_minus) >> exp
                | exp >> qi::token(k_mult) >> exp
                | qi::token(k_minus) >> exp
                | qi::token(k_leftParen) >> exp >> qi::token(k_rightParen)
                | qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp >> qi::token(k_rightBracket) 
                | qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> qi::token(k_rightParen)
                | qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> exp >> qi::token(k_rightParen)
                | qi::token(k_nonTerminal)
                | qi::token(k_terminal)
                | qi::token(k_trueTok)
                | qi::token(k_falseTok)
                ;

            // parameter list
            paramList 
                = paramList >> qi::token(k_comma) >> exp
                | exp
                ;

            // return statements
            returnStatement 
                = returnStatement >> exp
                | returnStatement
                ;

            // function call statements
            callStatement 
                = qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> qi::token(k_rightParen)
                | qi::token(k_nonTerminal) >> qi::token(k_leftParen) >> paramList >> qi::token(k_rightParen)
                ;

            // variable assignment
            assignmentStatement 
                = qi::token(k_nonTerminal) >> qi::token(k_assign) >> exp
                | qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp
                    >> qi::token(k_rightBracket) >> qi::token(k_assign) >> exp
                ;

            // list of integers
            intList 
                = intList >> qi::token(k_comma) >> qi::token(k_terminal)
                | qi::token(k_terminal)
                ;

            // print out a variable
            printStatement 
                = qi::token(k_print) >> exp
                ;

            // take input
            inputStatement 
                = qi::token(k_nonTerminal) >> qi::token(k_input)
                ;

            // conditional statement
            conditionStatement 
                = qi::token(k_ifTok) >> exp >> qi::token(k_colon) >> statements >> optionalElse
                ;

            // consitions have optional else
            optionalElse 
                = qi::token(k_elseTok) >> qi::token(k_colon) >> statements
                | qi::eps
                ;

            // while loop
            whileStatement 
                = qi::token(k_whileTok) >> exp >> qi::token(k_colon) >> statements >> qi::token(k_elihw)
                ;

            // actual program statements
            endList 
                = endList >> end
                | end
                ;

            // end possibilities of program in global space
            end = callStatement
                | printStatement
                | qi::token(k_nonTerminal) >> qi::token(k_assign) >> qi::token(k_input)
                | qi::token(k_nonTerminal) >> qi::token(k_assign) >> exp
                | qi::token(k_nonTerminal) >> qi::token(k_assign) >> qi::token(k_leftBracket) >> intList
                    >> qi::token(k_rightBracket)
                | qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> exp >> qi::token(k_rightBracket)
                    >> qi::token(k_assign) >> exp
                ;

            // function parameters
            paramList 
                = paramList >> qi::token(k_comma) >> qi::token(k_nonTerminal)
                | qi::token(k_nonTerminal)
                | qi::token(k_nonTerminal) >> qi::token(k_leftBracket) >> qi::token(k_rightBracket)
                ;

            // define a statement as assignment print input condition while or call
            statement 
                = assignmentStatement
                | printStatement
                | inputStatement
                | conditionStatement
                | whileStatement
                | callStatement
                | returnStatement
                ;

            // general statement list
            statements 
                = statements >> statement
                | statement
                ;

            // functions
            functionList 
                = qi::token(k_def) >> qi::token(k_nonTerminal) >> qi::token(k_leftParen)
                               >> paramList >> qi::token(k_rightParen) >> qi::token(k_colon)
                               >> statements >> qi::token(k_fed)
                | qi::token(k_def) >> qi::token(k_nonTerminal) >> qi::token(k_leftParen)
                               >> qi::token(k_rightParen) >> qi::token(k_colon) >> statements >> qi::token(k_fed)
                | qi::eps
                ;

            BOOST_SPIRIT_DEBUG_NODES((start)(functionList));
        }

        qi::rule<Iterator, Skipper> start;
        qi::rule<Iterator, Skipper> functionList;
        qi::rule<Iterator, Skipper> endList;
        qi::rule<Iterator, Skipper> paramList;
        qi::rule<Iterator, Skipper> statements;
        qi::rule<Iterator, Skipper> statement;
        qi::rule<Iterator, Skipper> assignmentStatement;
        qi::rule<Iterator, Skipper> printStatement;
        qi::rule<Iterator, Skipper> inputStatement;
        qi::rule<Iterator, Skipper> conditionStatement;
        qi::rule<Iterator, Skipper> whileStatement;
        qi::rule<Iterator, Skipper> callStatement;
        qi::rule<Iterator, Skipper> returnStatement;
        qi::rule<Iterator, Skipper> exp;
        qi::rule<Iterator, Skipper> intList;
        qi::rule<Iterator, Skipper> optionalElse;
        qi::rule<Iterator, Skipper> end;
    };
}

#include <fstream>
#include <iterator>

int main(int argc, char** argv) {
    namespace lex = boost::spirit::lex;
    namespace qi = boost::spirit::qi;

    typedef lex::lexertl::token< char const*, lex::omit, boost::mpl::true_ > token_type;
    typedef lex::lexertl::lexer<token_type> lexer_type;
    typedef interpreter::LexerTokens<lexer_type>::iterator_type iterator_type;
    typedef qi::in_state_skipper<interpreter::LexerTokens<lexer_type>::lexer_def> skipper_type;

    interpreter::LexerTokens< lexer_type > lexer;
    interpreter::InterpreterGrammar< iterator_type, skipper_type > parser(lexer);

    // read the file
    if (argc != 2)
    {
        std::cout << "File required" << std::endl;
        return 1;
    }

    std::ifstream t(argv[1]); 
    std::string const sourceCode { std::istreambuf_iterator<char>(t), {} };

    char const* first = sourceCode.data();
    char const* last = first + sourceCode.size();
    bool r = lex::tokenize_and_phrase_parse(first, last, lexer, parser, qi::in_state("WHITESPACE")[lexer.self]);

    std::cout << "Remaining " << std::string(first,last) << std::endl;
    std::cout << "R is " << r << std::endl;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

提升解析器中的 Spirit 段错误 的相关文章

  • 为什么存在 async 关键字

    浏览 msdn 9 频道视频时 我发现以下未答复的评论 希望有人能解释一下 我不明白 async 关键字的意义 为什么不直接允许 任何时候方法返回任务时都会使用await关键字 就像迭代器一样 可以在任何返回 IEnumerable 的方法
  • 具有不同大小结构的结构数组的 malloc()

    如果每个结构都包含一个大小不同的字符串数组 那么如何正确地 malloc 一个结构数组 因此每个结构可能有不同的大小 并且不可能 realloc 结构体数量 sizeof 结构体名称 after malloc 初始大小 sizeof 结构名
  • 通过增加索引之和来生成排序组合的有效方法

    对于启发式算法 我需要一个接一个地评估特定集合的组合 直到达到停止标准 由于它们很多 目前我正在使用以下内存高效迭代器块生成它们 受到 python 的启发 itertools combinations http docs python o
  • 内联函数/方法

    声明 内联函数必须在调用之前定义 这个说法正确吗 EDIT 该问题最初是德语 内联功能穆森 弗 伊赫雷姆 奥夫鲁夫定义 sein 也许它对任何人都有帮助 是的 它是正确的 但只是部分正确 它可能正确地重新构建如下 内联函数必须在每个翻译单位
  • 从多线程程序中调用 system()

    我们正在开发一个用 C 编写的多线程内存消耗应用程序 我们必须执行大量的 shellscript linux 命令 并获取返回码 读完之后article http www linuxprogrammingblog com threads a
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • mprotect 之后 malloc 导致分段错误

    在使用 mprotect 保护内存区域后第一次调用 malloc 时 我遇到分段错误 这是执行内存分配和保护的代码片段 define PAGESIZE 4096 void paalloc int size Allocates and ali
  • 将字符串转换为正确的 URI 格式?

    有没有简单的方法可以将电子邮件地址字符串转换为正确的 URI 格式 Input http mywebsite com validate email 3DE4ED727750215D957F8A1E4B117C38E7250C33 email
  • 如何生成 appsettings..json 文件?

    我有一个 ASP NET Core 2 WebAPI 它将部署在以下环境中 INT QA STAGE 生产环境 基于上述 我需要有appsettings
  • HttpWebRequest vs Webclient(特殊场景)

    我知道这个问题之前已经回答过thread https stackoverflow com questions 1694388 webclient vs httpwebrequest httpwebresponse 但我似乎找不到详细信息 在
  • 为什么 clang 使用 -O0 生成低效的 asm(对于这个简单的浮点和)?

    我正在 llvm clang Apple LLVM 版本 8 0 0 clang 800 0 42 1 上反汇编此代码 int main float a 0 151234 float b 0 2 float c a b printf f c
  • .NET 客户端中 Google 表格中的条件格式请求

    我知道如何在 Google Sheets API 中对值和其他格式进行批量电子表格更新请求 但条件格式似乎有所不同 我已正确设置请求 AddConditionalFormatRuleRequest formatRequest new Add
  • asp.net网格分页的SQL查询

    我在用iBatis and SQLServer 使用偏移量和限制进行分页查询的最佳方法是什么 也许我添加该列ROW NUMBER OVER ORDER BY Id AS RowNum 但这只会阻止简单查询的数据访问 在某些情况下 我使用选择
  • 为什么要在 C++ 中使用 typedef?

    可以说我有 set
  • ASP.NET JQuery AJAX POST 返回数据,但在 401 响应内

    我的应用程序中有一个网页 需要调用我设置的 Web 服务来返回对象列表 这个调用是这样设置的 document ready function var response ajax type POST contentType applicati
  • 初始化 LPCTSTR /LPCWSTR [重复]

    这个问题在这里已经有答案了 我很难理解并使其正常工作 基本上归结为我无法成功初始化这种类型的变量 它需要有说的内容7 2E25DC9D 0 USB003 有人可以解释 展示这种类型的正确初始化和类似的值吗 我已查看此站点上的所有帮助 将项目
  • C 中带有指针的结构的内存开销[重复]

    这个问题在这里已经有答案了 我意识到当我的结构包含指针时 它们会产生内存开销 这里有一个例子 typedef struct int num1 int num2 myStruct1 typedef struct int p int num2
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同

    System Net WebException 服务器响应 PASV 命令返回的地址与建立 FTP 连接的地址不同 在 System Net FtpWebRequest CheckError 在 System Net FtpWebReque
  • C#中为线程指定特殊的cpu

    我有 2 个线程 我想告诉其中一个在第一个 cpu 上运行 第二个在第二个 cpu 上运行 例如在具有两个 cpu 的机器中 我怎样才能做到这一点 这是我的代码 UCI UCIMain new UCI Thread UCIThread ne

随机推荐