C++ Boost Spirit X3代数解析器(带变量)
我一直在用spirit x3为代数表达式编写解析器。我的目标是在calc4c示例解析器的基础上进行构建,以便它包含带有变量、指数和括号的表达式作为乘法运算符。我在这方面已经做了很长时间了,我完全没有主意了 我从“move.hpp”、“move_to.hpp”和“transform_attribute.hpp”中得到了各种各样的错误,但它们没有帮助。然而,这可能是因为我对boost的了解相当有限 这是我得到的,任何帮助都将不胜感激 AST:C++ Boost Spirit X3代数解析器(带变量),c++,boost-spirit,boost-spirit-x3,C++,Boost Spirit,Boost Spirit X3,我一直在用spirit x3为代数表达式编写解析器。我的目标是在calc4c示例解析器的基础上进行构建,以便它包含带有变量、指数和括号的表达式作为乘法运算符。我在这方面已经做了很长时间了,我完全没有主意了 我从“move.hpp”、“move_to.hpp”和“transform_attribute.hpp”中得到了各种各样的错误,但它们没有帮助。然而,这可能是因为我对boost的了解相当有限 这是我得到的,任何帮助都将不胜感激 AST: 命名空间客户端{namespace ast { //AS
命名空间客户端{namespace ast
{
//AST
结构nil{};
结构指数;
结构letNum;
结构签名;
结构参数;
结构程序;
typedefx3::variant<
无
浮动
烧焦
,std::list
,x3::向前
,x3::向前
,x3::向前
,x3::向前
,x3::向前
>
操作数;
结构指数
{
操作数优先;
操作数秒;
};
结构letNum
{
浮点数;
std::列表let;
};
结构签名_
{
字符符号;
操作数操作数;
};
结构参数
{
std::列表参数列表;
};
结构操作
{
字符算子;
操作数操作数;
};
结构程序
{
操作数优先;
std::列出其余部分;
};
}}
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::指数、第一、第二)
BOOST\u FUSION\u ADAPT\u STRUCT(client::ast::letNum,num,let)
BOOST\u FUSION\u ADAPT\u结构(客户机::ast::有符号、有符号、操作数)
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::paren,parenList)
BOOST\u FUSION\u ADAPT\u结构(客户端::ast::操作、运算符、操作数)
BOOST\u FUSION\u ADAPT\u STRUCT(客户机::ast::程序,第一,rest)
}
语法:
namespace client
{
//Simplify Grammar
namespace simplify_grammar
{
using x3::float_;
using x3::char_;
using x3::alpha;
x3::real_parser<float, x3::ureal_policies<float> > const ureal_float_ = {};
x3::rule<class expression, ast::program> const expression("expression");
x3::rule<class term, ast::program> const term("term");
x3::rule<class exponent, ast::exponential> const exponent("exponent");
x3::rule<class factor, ast::operand> const factor("factor");
x3::rule<class factorSigned, ast::signed_> const factorSigned("factorSigned");
x3::rule<class factorParen, ast::paren> const factorParen("factorParen");
x3::rule<class letters, std::list<char> > const letters("letters");
x3::rule<class combo, ast::letNum> const combo("combo");
auto const expression_def =
term >> *( (char('+') >> term)
| (char('-') >> term))
;
auto const term_def =
(exponent | factor | factorSigned | factorParen) >> *( (char('*') >> (exponent | factor | factorSigned | factorParen))
| (char('/') >> (exponent | factor | factorSigned | factorParen))
)
;
auto const exponent_def =
( ( (ureal_float_ | alpha | ('(' >> expression >> ')'))
>> '^'
>> (factor | ('(' >> expression >> ')')))
| ( char('-')
>> (ureal_float_ | alpha | ('(' >> expression >> ')'))
>> '^'
>> (factor | ('(' >> expression >> ')')))
)
;
auto const factor_def =
combo
| ureal_float_
| letters
;
auto const factorSigned_def =
char('-') >> factor
;
auto const factorParen_def =
( (factor | factorSigned) >> +('(' >> expression >> ')'))
|
( '(' >> expression >> ')' >> +('(' >> expression >> ')'))
;
auto const letters_def =
+alpha
;
auto const combo_def =
ureal_float_ >> letters
;
BOOST_SPIRIT_DEFINE(
expression
, term
, exponent
, factor
, factorSigned
, factorParen
, letters
, combo
);
parser_type simplify()
{
return expression;
}
}
}
命名空间客户端
{
//简化语法
名称空间简化语法
{
使用x3::float_2;;
使用x3::char\ux;
使用x3::alpha;
x3::real_parser const ureal_float_={};
x3::规则常量表达式(“表达式”);
x3::规则常量术语(“术语”);
x3::规则常数指数(“指数”);
x3::规则常量因子(“因子”);
x3::规则常量factorSigned(“factorSigned”);
x3::规则常量factorParen(“factorParen”);
x3::规则常量字母(“字母”);
x3::规则常量组合(“组合”);
自动常量表达式=
术语>>*((字符(+')>>术语)
|(字符('-'>>术语))
;
自动常数项=
(指数|因子|因子|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计|因子设计)
|(字符(“/”)>>(指数|因子|因子签名|因子页))
)
;
自动常数指数=
(((ureal_float|alpha |)('('>>表达式>>')))
>> '^'
>>(因子|('('>>表达式>>')))
|(字符('-'))
>>(ureal_float|alpha |('('>>表达式>>'))
>> '^'
>>(因子|('('>>表达式>>')))
)
;
自动常数因子=
联合体
|乌拉尔浮球_
|信件
;
自动常数因子已指定=
字符('-')>>因子
;
自动常数系数=
((factor | factorSigned)>>+('('>>表达式>>'))
|
('('>>表达式>>')'>>+('('>>表达式>>')'))
;
自动常量字母=
+阿尔法
;
自动常量组合定义=
ureal_float_>>字母
;
提升精神(
表达
学期
,指数
因素
,系数化
,factorpain
,信件
,组合
);
解析器_type simplify()
{
返回表达式;
}
}
}
编辑:
解析器类型定义:
namespace client
{
///////////////////////////////////////////////////////////////////////////////
// The calculator grammar
///////////////////////////////////////////////////////////////////////////////
namespace calculator_grammar
{
using parser_type =
x3::any_parser<
std::string::const_iterator
, ast::program
, decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
>;
parser_type calculator();
}
auto const calculator = calculator_grammar::calculator();
}
命名空间客户端
{
///////////////////////////////////////////////////////////////////////////////
//计算器语法
///////////////////////////////////////////////////////////////////////////////
名称空间计算器语法
{
使用parser\u类型=
x3::任何_解析器<
std::string::const_迭代器
,ast::程序
,decltype(x3::生成上下文(x3::ascii::空格))
>;
解析器_类型计算器();
}
自动常量计算器=计算器\语法::计算器();
}
什么是解析器类型?您要解析的输入是什么?@sehe我在帖子中包含了parser_type的定义。我没有具体的输入,但能够解析像“2x(3xy)^2+2x/y”这样复杂的东西是我的目标。你想解析它什么/as/,因为它看起来不是要反映表达式结构,而是词汇输入?我看了一遍,但我真的不知道如何开始阅读语法。我不习惯生成与数学结构不匹配的AST(嵌套的二进制/一元运算)。我在这个网站上有很多不同方法的表达式解析器示例,所以您可以比较一下。否则,我建议你减少产量,直到你只有一个问题。所以,基本上,不要只写200行非常复杂的C++,然后点击编译。相反,从10行开始,绿色条,添加简单的测试用例,让它们通过,
namespace client
{
///////////////////////////////////////////////////////////////////////////////
// The calculator grammar
///////////////////////////////////////////////////////////////////////////////
namespace calculator_grammar
{
using parser_type =
x3::any_parser<
std::string::const_iterator
, ast::program
, decltype(x3::make_context<x3::skipper_tag>(x3::ascii::space))
>;
parser_type calculator();
}
auto const calculator = calculator_grammar::calculator();
}