boost::spirit numaralı telefondan tutorials'u okuduktan sonra, çözümleyici birleştirici sözdizimi nedeniyle oldukça beğendim. Bir çözümleyici yapmak çok kolay. Ne yazık ki, eğiticiler ayrıştırıcıdan karmaşık bir veri yapısı elde etme konusunda kesin olarak doğru değildi. Kaleidoscope AST'a ulaşmaya çalışıyorum.AST'den yükseltme AST :: spirit ayrıştırıcı
Neyse, işte benim AST kodu olması:
#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
Ben BOOST_FUSION_ADAPT_STRUCT
parça ihmal ettik, ama onlar vardır.
#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
Ben sorun ast::expression
çıkan bir sorun var gibi görünüyor olmasıdır. Derlenmiş, 200'den fazla karmaşık şablon hatası çıkarır. Ben binop
kuralından bilgi almak için çalıştı yolu ile bir şey olduğundan şüpheleniyorum, ama emin değilim.
Herkes yardımcı olabilir mi?
Yapın <> 'gerçekten çok fazla hata aldı. Şimdi sadece bir tane bırakıyorum: 'parser.hpp: 38: 81: hata: 'boost :: spirit :: _ 1' değeri sabit bir ifadede kullanılamaz ve not: 'boost :: spirit :: _1 '' constexpr 'olarak bildirilmedi. Herhangi bir yardım? – Lanbo
Tamam, bu, çözümünüzü yazarken bir hata yaptım. Teşekkürler! – Lanbo
Bu Ruh Uygulamaları linkinde listelenen bazı harika örnek kaynaklar var, teşekkürler! – rvalue