boost::spirit पर tutorials पढ़ने के बाद, मुझे इसे पार्सर संयोजक वाक्यविन्यास के कारण पसंद आया। एक पार्सर बनाना इतना आसान है।बढ़ावा से एएसटी पुनर्प्राप्त :: भावना पार्सर
दुर्भाग्य से, ट्यूटोरियल पार्सर से जटिल डेटा संरचना प्राप्त करने के मामले में सटीक नहीं थे। मैं Kaleidoscope 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
नियम से जानकारी प्राप्त करने का प्रयास किया है, लेकिन मुझे यकीन नहीं है।
क्या कोई मदद कर सकता है?
धन्यवाद कि 'निर्माण <>' वास्तव में बहुत सारी त्रुटियों को दूर कर लिया। अब मैं केवल एक के साथ छोड़ दिया गया है: 'parser.hpp: 38: 81: त्रुटि: 'boost :: spirit :: _ 1' का मान निरंतर अभिव्यक्ति में उपयोग करने योग्य नहीं है 'और' नोट: 'boost :: spirit :: _1 'घोषित नहीं किया गया' constexpr '। कोई मदद? – Lanbo
ठीक है स्क्रैप कि, मैंने आपके समाधान को लिखने में गलती की है। धन्यवाद! – Lanbo
उस आत्मा अनुप्रयोग लिंक में सूचीबद्ध कुछ महान उदाहरण स्रोत हैं, धन्यवाद! – rvalue