Why does this parser fail in Boost Spirit C++?

Asked

Viewed 26 times

1

When I enter the input tt or tt the program returns me "parse failed". However, to me the grammar seems correct, so I believe it is some peculiarity of the library. Would anyone like to explain the reason for the mistake? Just follow my code.

#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/std_pair.hpp>

#include <iostream>
#include <string>
#include <complex>
#include <vector>

namespace client
{
    namespace fusion = boost::fusion;
    namespace phoenix = boost::phoenix;
    namespace qi = boost::spirit::qi;
    namespace ascii = boost::spirit::ascii;
    enum operators {op_plus, op_minus, op_times};
    //Declaration Types
    struct declaration;
    typedef boost::variant<int, std::string> valueType;
    struct dec
    {
        std::string tipoVarOuCons;
        std::string variable;
        valueType value;
    };

    typedef
    boost::variant<
    boost::recursive_wrapper<declaration>
    , dec
    >
            declarationTree;

    struct declaration
    {
        std::vector<declarationTree> children;
    };

    //Expression Types
    struct expOp;
    struct orExp;
    struct notExp;
    struct eqExp;
    using expression =  boost::variant< int,std::string,boost::recursive_wrapper<expOp>>;
    using boolExpression = boost::variant<std::string, eqExp, boost::recursive_wrapper<orExp>, boost::recursive_wrapper<notExp>>;
    struct expOp
    {
        expression exp1;
        std::vector<std::pair<std::string, expression>> exp2;
    };
    struct eqExp
    {
        expression exp1;
        std::string op;
        expression exp2;
    };
    struct assignment
    {
        std::string variable;
        std::string symbol;
        expression exp;
    };
    struct orExp
    {

        boolExpression exp1;
        std::string symbol;
        boolExpression exp2;
    };
    struct notExp
    {
        std::string symbol;
        boolExpression exp;
    };
}
//Declaration Fusion
BOOST_FUSION_ADAPT_STRUCT(
        client::dec,
(std::string, tipoVarOuCons)
(std::string, variable)
(client::valueType, value)
)

BOOST_FUSION_ADAPT_STRUCT(
        client::declaration,
(std::vector<client::declarationTree>, children)
)

//Expression Fusion
BOOST_FUSION_ADAPT_STRUCT(
        client::expOp,exp1, exp2)

BOOST_FUSION_ADAPT_STRUCT(
        client::eqExp,exp1,op, exp2)

BOOST_FUSION_ADAPT_STRUCT(
        client::assignment,variable,symbol, exp)
//Boolean Fusion
BOOST_FUSION_ADAPT_STRUCT(
        client::orExp,exp1,symbol, exp2)
BOOST_FUSION_ADAPT_STRUCT(
        client::notExp,symbol, exp)
namespace client
{
    template <typename Iterator>
    struct ast_parser : qi::grammar<Iterator, boolExpression(), ascii::space_type>
    {
        ast_parser() : ast_parser::base_type(boolExpressionR)
        {
            using qi::int_;
            using qi::lit;
            using qi::double_;
            using qi::lexeme;
            using ascii::char_;
            using qi::string;

            string_ %= lexeme[+(char_ - ' ')];
            typeR %= string("var") | string("cons");
            boolean %= string("tt") | string("ff");
            value %= qi::int_ | boolean;
            declarationAtom %= typeR >> string_ >> value;
            boperator %= string("+") | string("-") | string("*");

            simpleExpression %= ( '(' > expressionR > ')' ) | qi::int_ | string_;
            expOperator %= simpleExpression >> *(boperator > expressionR);
            expressionR %= expOperator;

            equalExpression %= expressionR >> string("==") >> expressionR;
            orExpression %=  boolExpressionR >> string("or") >> boolExpressionR;
            notExpression %= string("!") >> boolExpressionR;
            boolExpressionR %= boolean  | equalExpression | orExpression | notExpression;

            assignmentR %= string_ >> string("=") >> expressionR;
            //ifCommand %= lit("if") >> boolExpression >> lit("then") >> command >> lit("else") >> command;
            //command %= string("nil") | (command >> lit(";") >> command) | assignment | ifCommand | whileCommand;
            //declarationR %= declarations | declarationL;
            //program %= declarations;
        }

        qi::rule<Iterator, std::string(), ascii::space_type> string_;
        qi::rule<Iterator, std::string(), ascii::space_type> typeR;
        qi::rule<Iterator, std::string(), ascii::space_type> boolean;
        qi::rule<Iterator, valueType(), ascii::space_type> value;
        qi::rule<Iterator, std::string(), ascii::space_type> boperator;
        //qi::rule<Iterator, declaration(), ascii::space_type> declarationL;
        qi::rule<Iterator, dec(), ascii::space_type> declarationAtom;
        qi::rule<Iterator, expression(), ascii::space_type> simpleExpression;
        qi::rule<Iterator, expOp(), ascii::space_type> expOperator;
        qi::rule<Iterator, expression(), ascii::space_type> expressionR;
        qi::rule<Iterator, eqExp(), ascii::space_type> equalExpression;
        qi::rule<Iterator, assignment(), ascii::space_type> assignmentR;
        qi::rule<Iterator, orExp(), ascii::space_type> orExpression;
        qi::rule<Iterator, notExp(), ascii::space_type> notExpression;
        qi::rule<Iterator, boolExpression(), ascii::space_type> boolExpressionR;

        //qi::rule<Iterator, declaration(), ascii::space_type> declarations;
        //qi::rule<Iterator, program(), ascii::space_type> program;
        //qi::rule<Iterator, dec(), ascii::space_type> declarationAtom;
    };
    //]
}

int
main()
{

    using boost::spirit::ascii::space;
    typedef std::string::const_iterator iterator_type;
    typedef client::ast_parser<iterator_type> ast_parser;

    ast_parser g; // Our grammar
    std::string str;
    //client::dec d;
    while (getline(std::cin, str))
    {
        if (str.empty() || str[0] == 'q' || str[0] == 'Q')
            break;

        std::string::const_iterator iter = str.begin();
        std::string::const_iterator end = str.end();
        bool r = phrase_parse(iter, end, g, space);

        if (r && iter == end)
        {

            std::cout << "-------------------------\n";
            std::cout << "Parsing succeeded\n";
//            std::cout<<d.tipoVarOuCons;
            std::cout << "\n-------------------------\n";
        }
        else
        {
            std::cout << "-------------------------\n";
            std::cout << "Parsing failed\n";
            std::cout << "-------------------------\n";
        }
    }

    std::cout << "Bye... :-) \n\n";
    return 0;
}

EDIT: The grammar is this:
using qi::int_;
using qi:lit;
using qi::double_;
using qi:lexeme;
using ascii::char_;
using qi::string;

string_ %= lexeme[+(char_ - ' ')];
Typer %= string("var") | string("cons");
Boolean %= string("tt") | string("ff");
value %= qi::int_ | Boolean;
declarationAtom %= Typer >> string_>> value;
boperator %= string("+") | string("-") | string("*");

simpleExpression %= ( '(' > expressionR > ')' ) | qi::int_ | string_;
expOperator %= simpleExpression >> *(boperator > expressionR);
expressionR %= expOperator;

equalExpression %= expressionR >> string("==") >> expressionR;
orExpression %= boolExpressionR >>string("or") >> boolExpressionR;
notExpression %= string("!") >> boolExpressionR;
boolExpressionR %= Boolean | equalExpression | orExpression | notExpression;

assignmentR %= string_>> string("=") >> expressionR;

  • You can make it more visible, preferably outside the code in another block, which grammar you are using?

  • I put the grammar at the end. I am sorry, I had put a way that I found to make it work, which would put the OR >> boolExpressionR >> boolExpressionR. But it wasn’t what I wanted. With this graph I’m passing tt or ff using boolExpressionR as a start but it’s giving "parse failed".

No answers

Browser other questions tagged

You are not signed in. Login or sign up in order to post.