Sau khi tôi đã đọc tutorials trên boost::spirit, tôi rất thích nó vì cú pháp trình kết hợp phân tích cú pháp. Làm cho một trình phân tích cú pháp rất dễ dàng.Lấy AST khỏi tăng :: trình phân tích cú pháp tinh thần
Thật không may, các hướng dẫn không chính xác về vấn đề lấy cấu trúc dữ liệu phức tạp ra khỏi trình phân tích cú pháp. Tôi đang cố gắng truy cập vào Kaleidoscope AST.
Dù sao, đây là mã AST tôi:
#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
Tôi đã bỏ qua BOOST_FUSION_ADAPT_STRUCT
phần, nhưng họ đang có.
Và đây phân tích cú pháp biểu hiện của tôi:
#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
Tôi có vấn đề là nó dường như có một vấn đề với các kết quả ast::expression
. Các biên dịch ném ra hơn 200 dòng lỗi mẫu phức tạp. Tôi nghi ngờ nó là một cái gì đó với cách tôi đã cố gắng để có được thông tin trong số các quy tắc binop
, nhưng tôi không chắc chắn.
Có ai giúp được không?
Cảm ơn 'kiến trúc <>' thực sự đã loại bỏ rất nhiều lỗi. Bây giờ tôi chỉ còn lại một: 'parser.hpp: 38: 81: error: giá trị của 'boost :: spirit :: _ 1' không thể sử dụng trong một biểu thức liên tục' và' note: 'boost :: spirit :: _1 'không được khai báo' constexpr''. Bất kỳ giúp đỡ? – Lanbo
Ok mẩu tin lưu niệm đó, tôi đã nhầm lẫn khi viết ra giải pháp của bạn. Cảm ơn! – Lanbo
Liên kết Ứng dụng Thần linh đó có một số nguồn ví dụ tuyệt vời được liệt kê, cảm ơn! – rvalue