boost::spirit에있는 tutorials을 읽은 후에 파서 결합기 구문 때문에 매우 마음에 들었습니다. 파서 만들기가 너무 쉽습니다.boost :: spirit parser에서 AST 가져 오기
불행히도 튜토리얼은 파서에서 복잡한 데이터 구조를 가져 오는 문제와 정확히 일치하지 않았습니다. 나는 Kaleidoscope AST에 도착하려고 노력하고있다.
어쨌든, 여기 내 AST 코드 수 :
#ifndef __AST_HPP__
#define __AST_HPP__
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <string>
#include <vector>
namespace ast {
struct add;
struct sub;
struct mul;
struct div;
struct func_call;
template<typename OpTag> struct binary_op;
typedef boost::variant<double, std::string, boost::recursive_wrapper<binary_op<
add>>, boost::recursive_wrapper<binary_op<sub>>,
boost::recursive_wrapper<binary_op<mul>>, boost::recursive_wrapper<
binary_op<div>>, boost::recursive_wrapper<func_call>>
expression;
template<typename OpTag>
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<expression> args;
func_call(const std::string func, const std::vector<expression> &args) :
callee(func), args(args) {
}
};
struct prototype {
std::string name;
std::vector<std::string> args;
prototype(const std::string &name, const std::vector<std::string> &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 <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include "ast.hpp"
namespace parser {
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
namespace phoenix = boost::phoenix;
template<typename Iterator>
struct expression: qi::grammar<Iterator, ast::expression(), ascii::space_type> {
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<ast::add>(_1, _3)]
| (expr >> '-' >> expr)[_val
= ast::binary_op<ast::sub>(_1, _3)]
| (expr >> '*' >> expr)[_val
= ast::binary_op<ast::mul>(_1, _3)]
| (expr >> '/' >> expr)[_val
= ast::binary_op<ast::div>(_1, _3)];
expr %= number | varname | binop;
}
qi::rule<Iterator, ast::expression(), ascii::space_type> expr;
qi::rule<Iterator, ast::expression(), ascii::space_type> binop;
qi::rule<Iterator, std::string, ascii::space_type> varname;
qi::rule<Iterator, double, ascii::space_type> number;
};
}
#endif
내가 가진 문제는 ast::expression
을 결과에 문제가있는 것이다. 컴파일하면 복잡한 템플릿 오류가 200 줄 이상 발생합니다. 나는 이것이 내가 binop
규칙에서 정보를 얻으려고하는 방식과 관련이 있다고 의심하지만 확실하지 않다.
아무도 도와 줄 수 있습니까?
'construct <>'로 인해 많은 오류가 발생했습니다. 'parser.hpp : 38 : 81 : error : 'boost :: spirit :: _ 1'의 값을 상수 표현식에서 사용할 수 없습니다.''note : 'boost :: spirit :: _1 '은'constexpr '으로 선언되지 않았습니다. 어떤 도움이 필요합니까? – Lanbo
좋아, 그 실수를 저질렀습니다. 감사! – Lanbo
Spirit Applications 링크에는 멋진 예제 소스가 나열되어있어 감사합니다! – rvalue