После того, как я прочитал учебники по boost::spirit, они мне очень понравились из-за синтаксиса комбинатора парсеров. Создавать парсер так просто.
К сожалению, учебники были не так точны в вопросе получения сложной структуры данных из парсера. Я пытаюсь добраться до Kaleidoscope AST.
В любом случае, вот мой код AST:
#ifndef __AST_HPP__
#define __AST_HPP__
#include
#include
#include
#include
#include
#include
namespace ast {
struct add;
struct sub;
struct mul;
struct div;
struct func_call;
template struct binary_op;
typedef boost::variant>, boost::recursive_wrapper>,
boost::recursive_wrapper>, boost::recursive_wrapper<
binary_op>, boost::recursive_wrapper>
expression;
template
struct binary_op {
expression left;
expression right;
binary_op(const expression & lhs, const expression & rhs) :
left(lhs), right(rhs) {
}
};
struct func_call {
std::string callee;
std::vector args;
func_call(const std::string func, const std::vector &args) :
callee(func), args(args) {
}
};
struct prototype {
std::string name;
std::vector args;
prototype(const std::string &name, const std::vector &args) :
name(name), args(args) {
}
};
struct function {
prototype proto;
expression body;
function(const prototype &proto, const expression &body) :
body(body), proto(proto) {
}
};
}
#endif
Я опустил части BOOST_FUSION_ADAPT_STRUCT
, но они там есть.
А это мой парсер выражений:
#ifndef __PARSER_HPP__
#define __PARSER_HPP__
#include
#include
#include
#include
#include "ast.hpp"
namespace parser {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
template
struct expression: qi::grammar {
expression() :
expression::base_type(expr) {
using qi::lit;
using qi::lexeme;
using ascii::char_;
using ascii::string;
using ascii::alnum;
using ascii::alpha;
using qi::double_;
using namespace qi::labels;
using phoenix::at_c;
using phoenix::push_back;
number %= lexeme[double_];
varname %= lexeme[alpha >> *(alnum | '_')];
binop
= (expr >> '+' >> expr)[_val = ast::binary_op(_1, _3)]
| (expr >> '-' >> expr)[_val
= ast::binary_op(_1, _3)]
| (expr >> '*' >> expr)[_val
= ast::binary_op(_1, _3)]
| (expr >> '/' >> expr)[_val
= ast::binary_op(_1, _3)];
expr %= number | varname | binop;
}
qi::rule expr;
qi::rule binop;
qi::rule varname;
qi::rule number;
};
}
#endif
Проблема у меня в том, что у него, похоже, проблема с результирующим ast::expression
. Скомпилированное выражение выбрасывает более 200 строк ошибок сложного шаблона. Я подозреваю, что это что-то с тем, как я пытался получить информацию из правила binop
, но я не уверен.
Кто-нибудь может помочь?
8
задан Lanbo 10 December 2011 в 23:41
поделиться