lundi 23 février 2015

Spirit qi parsing to an Abstract Syntax Tree for nested functions


I am trying to create a parser using boost's spirit qi parser. It is parsing a string that contains three types of values. A constant, a variable, or a function. The functions can be nested inside of each other. The test string is f(a, b) = f(g(z, x), g(x, h(x)), c), where a-e are constants, f-r are functions, and s-z are variables. I successfully created a rule that can correctly parse the expression. The trouble arose when I changed the function parsing the rule into a grammar. There were several errors that I was able to fix. I almost got the grammar to parse the expression and turn it into an abstract syntax tree I created. However I got this error about a file contained in the boost library and I could not figure out where it is coming from because I don't understand the compiler message. I was following the example put up on the website for putting data from a parser to a struct using the employee example: http://ift.tt/17Ohwic


main.cpp



#include "Parser.h"
#include "Term.h"

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
#include <list>

using std::string;
using std::cout;
using std::endl;

int main()
{
cout << "Unification Algorithm" << endl << endl;

string phrase = "f(a, b) = f(g(z, x), g(x, h(x)), c)";
string::const_iterator itr = phrase.begin();
string::const_iterator last = phrase.end();

cout << phrase << endl;

// Parser grammar
Parser<string::const_iterator> g;

// Output data
Expression expression;

if (phrase_parse(itr, last, g, boost::spirit::ascii::space, expression))
{
cout << "Expression parsed." << endl;
}
else
{
cout << "Could not parse expression." << endl;
}
}


Parser.h



#ifndef _Parser_h_
#define _Parser_h_

#include "Term.h"

#include <boost/spirit/include/qi.hpp>
#include <vector>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
struct Parser : qi::grammar<Iterator, Expression(), ascii::space_type>
{
Parser() : Parser::base_type(expression)
{
using qi::char_;

const_char = char_("a-eA-E");
fn_char = char_("f-rF-R");
var_char = char_("s-zS-Z");

basic_fn = fn_char >> char_('(') >> (const_char | var_char) % char_(',') >> char_(')');
first_fn_wrapper = fn_char >> char_('(') >> (basic_fn | const_char | var_char) % char_(',') >> char_(')');
nested_fn = fn_char >> char_('(') >> (first_fn_wrapper | const_char | var_char) % char_(',') >> char_(')');

expression = nested_fn >> char_("=") >> nested_fn;
}
// Constant character a - e
qi::rule<Iterator, T_Cons, ascii::space_type> const_char;
// Function character f - r
qi::rule<Iterator, char(), ascii::space_type> fn_char;
// Variable character s - z
qi::rule<Iterator, T_Var, ascii::space_type> var_char;
// Allows for basic function parsing eg. f(x, y, z)
qi::rule<Iterator, T_Fn, ascii::space_type> basic_fn;
// Allows for single nested functions eg. f(g(x), y, z)
qi::rule<Iterator, T_Fn, ascii::space_type> first_fn_wrapper;
// Allows for fully nested functions eg. f(g(x, h(y)), z) and so on
qi::rule<Iterator, T_Fn, ascii::space_type> nested_fn;
// Full rule for a nested function expression
qi::rule<Iterator, Expression, ascii::space_type> expression;
};
#endif // _Parser_h_


Term.h



#ifndef _Term_h_
#define _Term_h_

#include <boost/fusion/include/adapt_struct.hpp>
#include <vector>

struct Term
{
char name;
};

BOOST_FUSION_ADAPT_STRUCT(Term, (char, name))

struct T_Cons : Term
{

};

BOOST_FUSION_ADAPT_STRUCT(T_Cons, (char, name))

struct T_Var : Term
{

};

BOOST_FUSION_ADAPT_STRUCT(T_Var, (char, name))

struct T_Fn : Term
{
std::vector<Term> * params;

T_Fn() { params = new std::vector<Term>(); }

~T_Fn() { delete params; }
};

BOOST_FUSION_ADAPT_STRUCT(T_Fn, (std::vector<Term>*, params))

struct Expression
{
Term lh_term;
Term rh_term;
};

BOOST_FUSION_ADAPT_STRUCT(Expression, (char, name) (Term, lh_term) (Term, rh_term))

#endif // _Term_h_


I cannot link the entire error message from the compiler because it is extremely long, but here are the last few. These are the compile errors that it gave:



boost_1_46_0\boost\mpl\assert.hpp|360|error: no matching function for call to 'assertion_failed(mpl_::failed************ (boost::spirit::qi::grammar<Iterator, T1, T2, T3, T4>::grammar(const boost::spirit::qi::rule<Iterator_, T1_, T2_, T3_, T4_>&, const string&) [with Iterator_ = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; T1_ = Expression; T2_ = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::asci|
boost_1_46_0\boost\proto\extends.hpp|540|error: use of deleted function 'boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Expression(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type> > >, 0l>:|
boost_1_46_0\boost\proto\detail\expr0.hpp|165|error: no matching function for call to 'boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Expression(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type> >::reference()'|



Aucun commentaire:

Enregistrer un commentaire