gpt4 book ai didi

c++ - 灵气解析为嵌套函数的抽象语法树

转载 作者:太空狗 更新时间:2023-10-29 20:12:16 26 4
gpt4 key购买 nike

我正在尝试使用 boost 的 spirit qi 解析器创建一个解析器。它正在解析包含三种类型值的字符串。常量、变量或函数。这些函数可以相互嵌套。测试字符串为f(a, b) = f(g(z, x), g(x, h(x)), c),其中a-e为常量,f-r是函数,s-z是变量。我成功地创建了一个可以正确解析表达式的规则。当我将解析规则的函数更改为 grammar 时出现了问题.我能够修复几个错误。我几乎得到语法来解析表达式并将其转换为我创建的抽象语法树。但是我得到了关于 boost 库中包含的文件的错误,我无法弄清楚它来自哪里,因为我不理解编译器消息。我正在按照网站上的示例使用员工示例将数据从解析器放入结构:http://www.boost.org/doc/libs/1_41_0/libs/spirit/example/qi/employee.cpp

main.cpp

#include "Parser.h"
#include "Term.h"

#include <boost/spirit/include/qi.hpp>
#include <string>
#include <iostream>
#include <list>

using std::string;
using std::cout;
using std::endl;

int main()
{
cout << "Unification Algorithm" << endl << endl;

string phrase = "f(a, b) = f(g(z, x), g(x, h(x)), c)";
string::const_iterator itr = phrase.begin();
string::const_iterator last = phrase.end();

cout << phrase << endl;

// Parser grammar
Parser<string::const_iterator> g;

// Output data
Expression expression;

if (phrase_parse(itr, last, g, boost::spirit::ascii::space, expression))
{
cout << "Expression parsed." << endl;
}
else
{
cout << "Could not parse expression." << endl;
}
}

Parser.h

#ifndef _Parser_h_
#define _Parser_h_

#include "Term.h"

#include <boost/spirit/include/qi.hpp>
#include <vector>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename Iterator>
struct Parser : qi::grammar<Iterator, Expression(), ascii::space_type>
{
Parser() : Parser::base_type(expression)
{
using qi::char_;

const_char = char_("a-eA-E");
fn_char = char_("f-rF-R");
var_char = char_("s-zS-Z");

basic_fn = fn_char >> char_('(') >> (const_char | var_char) % char_(',') >> char_(')');
first_fn_wrapper = fn_char >> char_('(') >> (basic_fn | const_char | var_char) % char_(',') >> char_(')');
nested_fn = fn_char >> char_('(') >> (first_fn_wrapper | const_char | var_char) % char_(',') >> char_(')');

expression = nested_fn >> char_("=") >> nested_fn;
}
// Constant character a - e
qi::rule<Iterator, T_Cons, ascii::space_type> const_char;
// Function character f - r
qi::rule<Iterator, char(), ascii::space_type> fn_char;
// Variable character s - z
qi::rule<Iterator, T_Var, ascii::space_type> var_char;
// Allows for basic function parsing eg. f(x, y, z)
qi::rule<Iterator, T_Fn, ascii::space_type> basic_fn;
// Allows for single nested functions eg. f(g(x), y, z)
qi::rule<Iterator, T_Fn, ascii::space_type> first_fn_wrapper;
// Allows for fully nested functions eg. f(g(x, h(y)), z) and so on
qi::rule<Iterator, T_Fn, ascii::space_type> nested_fn;
// Full rule for a nested function expression
qi::rule<Iterator, Expression, ascii::space_type> expression;
};
#endif // _Parser_h_

Term.h

#ifndef _Term_h_
#define _Term_h_

#include <boost/fusion/include/adapt_struct.hpp>
#include <vector>

struct Term
{
char name;
};

BOOST_FUSION_ADAPT_STRUCT(Term, (char, name))

struct T_Cons : Term
{

};

BOOST_FUSION_ADAPT_STRUCT(T_Cons, (char, name))

struct T_Var : Term
{

};

BOOST_FUSION_ADAPT_STRUCT(T_Var, (char, name))

struct T_Fn : Term
{
std::vector<Term> * params;

T_Fn() { params = new std::vector<Term>(); }

~T_Fn() { delete params; }
};

BOOST_FUSION_ADAPT_STRUCT(T_Fn, (std::vector<Term>*, params))

struct Expression
{
Term lh_term;
Term rh_term;
};

BOOST_FUSION_ADAPT_STRUCT(Expression, (char, name) (Term, lh_term) (Term, rh_term))

#endif // _Term_h_

我无法链接来自编译器的整个错误消息,因为它非常长,但这里是最后几条。这些是它给出的编译错误:

boost_1_46_0\boost\mpl\assert.hpp|360|error: no matching function for call to 'assertion_failed(mpl_::failed************ (boost::spirit::qi::grammar<Iterator, T1, T2, T3, T4>::grammar(const boost::spirit::qi::rule<Iterator_, T1_, T2_, T3_, T4_>&, const string&) [with Iterator_ = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; T1_ = Expression; T2_ = boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::asci|
boost_1_46_0\boost\proto\extends.hpp|540|error: use of deleted function 'boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Expression(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type> > >, 0l>:|
boost_1_46_0\boost\proto\detail\expr0.hpp|165|error: no matching function for call to 'boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Expression(), boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type> >::reference()'|

最佳答案

UPDATE Showing a simplified parser with a a recursive ast parsing the sample expression shown

一如既往,断言消息恰恰导致了问题:

        // If you see the assertion below failing then the start rule
// passed to the constructor of the grammar is not compatible with
// the grammar (i.e. it uses different template parameters).
BOOST_SPIRIT_ASSERT_MSG(
(is_same<start_type, rule<Iterator_, T1_, T2_, T3_, T4_> >::value)
, incompatible_start_rule, (rule<Iterator_, T1_, T2_, T3_, T4_>));

所以它告诉你应该将语法与开始规则相匹配:你有

struct Parser : qi::grammar<Iterator, Expression(), ascii::space_type>

但是

qi::rule<Iterator, Expression, ascii::space_type> expression;

显然你忘记了括号:

qi::rule<Iterator, Expression(), ascii::space_type> expression;

使用通用库时的指南:

其中一些“规则”是普遍适用的,除了没有。 2 与 Boost Spirit 具体相关:

  1. 婴儿学步;从小处开始(空的,甚至)
  2. 从 AST 开始以准确匹配语法
  3. 逐步建立,
  4. 编译沿途的每一步

更新

这是一个非常简化的语法。如前所述,在刚刚的“第一条 spirit 规则”中,从AST开始以精确匹配语法:

namespace ast {

namespace tag {
struct constant;
struct variable;
struct function;
}

template <typename Tag> struct Identifier { char name; };

using Constant = Identifier<tag::constant>;
using Variable = Identifier<tag::variable>;
using Function = Identifier<tag::function>;

struct FunctionCall;

using Expression = boost::make_recursive_variant<
Constant,
Variable,
boost::recursive_wrapper<FunctionCall>
>::type;

struct FunctionCall {
Function function;
std::vector<Expression> params;
};

struct Equation {
Expression lhs, rhs;
};
}

当然,这可能简单得多,因为所有标识符都只是 char 并且您可以动态切换 ( impression ) .

现在,语法必须遵循。 1. 保持简单2. 仔细格式化3. 直接匹配ast,4. 添加调试宏:

template <typename It, typename Skipper = ascii::space_type>
struct Parser : qi::grammar<It, ast::Equation(), Skipper>
{
Parser() : Parser::base_type(equation_)
{
using namespace qi;

constant_ = qi::eps >> char_("a-eA-E");
function_ = qi::eps >> char_("f-rF-R");
variable_ = qi::eps >> char_("s-zS-Z");

function_call = function_ >> '(' >> -(expression_ % ',') >> ')';
expression_ = constant_ | variable_ | function_call;
equation_ = expression_ >> '=' >> expression_;

BOOST_SPIRIT_DEBUG_NODES((constant_)(function_)(variable_)(function_call)(expression_)(equation_))
}
qi::rule<It, ast::Constant()> constant_;
qi::rule<It, ast::Function()> function_;
qi::rule<It, ast::Variable()> variable_;

qi::rule<It, ast::FunctionCall(), Skipper> function_call;
qi::rule<It, ast::Expression(), Skipper> expression_;
qi::rule<It, ast::Equation(), Skipper> equation_;
};

Note how the comments have become completely unneeded. Also note how recursively using expression_ solved your biggest headache!

完整程序

Live On Coliru

//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

namespace ast {

namespace tag {
struct constant;
struct variable;
struct function;
}

template <typename Tag> struct Identifier { char name; };

using Constant = Identifier<tag::constant>;
using Variable = Identifier<tag::variable>;
using Function = Identifier<tag::function>;

struct FunctionCall;

using Expression = boost::make_recursive_variant<
Constant,
Variable,
boost::recursive_wrapper<FunctionCall>
>::type;

struct FunctionCall {
Function function;
std::vector<Expression> params;
};

struct Equation {
Expression lhs, rhs;
};
}

BOOST_FUSION_ADAPT_STRUCT(ast::Constant, (char, name))
BOOST_FUSION_ADAPT_STRUCT(ast::Variable, (char, name))
BOOST_FUSION_ADAPT_STRUCT(ast::Function, (char, name))
BOOST_FUSION_ADAPT_STRUCT(ast::FunctionCall, (ast::Function, function)(std::vector<ast::Expression>, params))
BOOST_FUSION_ADAPT_STRUCT(ast::Equation, (ast::Expression, lhs)(ast::Expression, rhs))

namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;

template <typename It, typename Skipper = ascii::space_type>
struct Parser : qi::grammar<It, ast::Equation(), Skipper>
{
Parser() : Parser::base_type(equation_)
{
using namespace qi;

constant_ = qi::eps >> char_("a-eA-E");
function_ = qi::eps >> char_("f-rF-R");
variable_ = qi::eps >> char_("s-zS-Z");

function_call = function_ >> '(' >> -(expression_ % ',') >> ')';
expression_ = constant_ | variable_ | function_call;
equation_ = expression_ >> '=' >> expression_;

BOOST_SPIRIT_DEBUG_NODES((constant_)(function_)(variable_)(function_call)(expression_)(equation_))
}
qi::rule<It, ast::Constant()> constant_;
qi::rule<It, ast::Function()> function_;
qi::rule<It, ast::Variable()> variable_;

qi::rule<It, ast::FunctionCall(), Skipper> function_call;
qi::rule<It, ast::Expression(), Skipper> expression_;
qi::rule<It, ast::Equation(), Skipper> equation_;
};

int main() {
std::cout << "Unification Algorithm\n\n";

std::string const phrase = "f(a, b) = f(g(z, x), g(x, h(x)), c)";
using It = std::string::const_iterator;
It itr = phrase.begin(), last = phrase.end();

std::cout << phrase << std::endl;

Parser<It> g;
ast::Equation parsed;

if (phrase_parse(itr, last, g, ascii::space, parsed)) {
std::cout << "Expression parsed.\n";
} else {
std::cout << "Could not parse equation.\n";
}

if (itr != last) {
std::cout << "Remaining unparsed input: '" << std::string(itr,last) << "'\n";
}
}

关于c++ - 灵气解析为嵌套函数的抽象语法树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28681381/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com