我刚刚开始深入研究 Boost::Spirit,目前最新版本——V2.4。我的问题的本质如下:
我想解析像“1a2”或“3b4”这样的字符串。所以我使用的规则是:
(double_ >> lit('b') >> double_)
| (double_ >> lit('a') >> double_);
Run Code Online (Sandbox Code Playgroud)
规则的属性必须是“vector <double>”。我正在将其读入容器中。
完整代码:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cstring>
int main(int argc, char * argv[])
{
using namespace std;
using namespace boost::spirit;
using namespace boost::spirit::qi;
using boost::phoenix::arg_names::arg1;
char const * first = "1a2";
char const * last = first + std::strlen(first);
vector<double> h;
rule<char const *, vector<double>()> or_test;
or_test %= (double_ >> lit('b') >> …
Run Code Online (Sandbox Code Playgroud) 我正在使用 Boost Spirit 解析一个相当复杂的语法,并且遇到了一个具有 20 多种类型(此处为 21 种)的变体的问题:
namespace eddic { namespace ast {
typedef boost::mpl::vector<
Integer,
IntegerSuffix,
Float,
Litteral,
VariableValue,
DereferenceValue,
Expression,
Unary,
Null,
True,
False,
ArrayValue,
FunctionCall,
MemberFunctionCall,
Cast,
BuiltinOperator,
Assignment,
SuffixOperation,
PrefixOperation,
Ternary
> types_initial;
typedef boost::mpl::push_back<types_initial, New>::type types;
typedef boost::make_variant_over<types>::type Value;
}}
Run Code Online (Sandbox Code Playgroud)
Boost Spirit 无法识别使用push_back 添加的最后一个类型(eddic::ast::New)。当我解析具有此元素的内容时,它会失败并出现以下错误:
eddic: /usr/include/boost/variant/detail/visitation_impl.hpp:264: 类型名称 Visitor::result_type boost::detail::variant::visitation_impl(int, int, Visitor&, VoidPtrCV, mpl_::false_, NoBackupFlag, Which*, step0*) [with Which = mpl_::int_<0>; 步骤0 = boost::detail::variant::visitation_impl_step、boost::mpl::v_item、boost::mpl::v_item、boost::mpl::v_item、boost::mpl::v_item、boost::mpl: :v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item, boost::mpl::v_item , boost::mpl::v_item, boost::mpl::v_item, 0>, …
如何防止 X3 符号解析器匹配部分标记?在下面的示例中,我想匹配“foo”,但不匹配“foobar”。我尝试将符号解析器放入指令中,lexeme
就像处理标识符一样,但没有任何匹配。
感谢您的任何见解!
#include <string>
#include <iostream>
#include <iomanip>
#include <boost/spirit/home/x3.hpp>
int main() {
boost::spirit::x3::symbols<int> sym;
sym.add("foo", 1);
for (std::string const input : {
"foo",
"foobar",
"barfoo"
})
{
using namespace boost::spirit::x3;
std::cout << "\nParsing " << std::left << std::setw(20) << ("'" + input + "':");
int v;
auto iter = input.begin();
auto end = input.end();
bool ok;
{
// what's right rule??
// this matches nothing
// auto r = lexeme[sym - alnum];
// this matchs …
Run Code Online (Sandbox Code Playgroud) 我正在通过编写一个解析器来解析 NAMS 使用的两种十六进制数变体来学习 Boost Spirit:
0x
/0h
或前缀h
/ x
。$
and 的十六进制数字后必须跟一个十进制数字。这是我到目前为止和Coliru Session 提出的内容:
//#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/spirit/include/support_extended_variant.hpp>
namespace x3 = boost::spirit::x3;
namespace ast {
struct hex_data : std::string {};
struct pascal_hex_data : std::string {};
struct declared_data : boost::spirit::extended_variant<hex_data, pascal_hex_data>
{
declared_data () : base_type () { std::cout << "ctor default\n"; }
declared_data (hex_data const& rhs) : base_type (rhs) { std::cout << "ctor …
Run Code Online (Sandbox Code Playgroud) 我有一个boost::spirit
解析器,它应该简单地分配一个指向其属性的指针:
rule<CompoundExpression *(Scope &)> var_ref = var<CompoundExpression>()(_r1) [
_val = new_<Reference<Variable<CompoundExpression>>>(_1)
];
Run Code Online (Sandbox Code Playgroud)
wherevar<CompoundExpression>()
是一个 just 函数,它返回对执行实际解析的静态规则的引用。我Reference<Variable<T>>
在整个代码中对模板的其他实例使用相同的赋值操作,这很好,除了使用CompoundExpression
参数的那个。
字面 GCC 错误是这样的:
In file included from /usr/include/boost/phoenix/core/actor.hpp:20,
from /usr/include/boost/phoenix/core.hpp:12,
from /usr/include/boost/spirit/include/phoenix_core.hpp:11,
from /usr/include/boost/spirit/home/support/argument.hpp:18,
from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:29,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/include/qi_nonterminal.hpp:16,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/utilities.h:7,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.h:4,
from /home/ich/sync/ConTrAkt/gologpp/src/parser/compound_expression.cpp:1:
/usr/include/boost/phoenix/core/is_nullary.hpp: In instantiation of ‘struct boost::phoenix::result_of::is_nullary<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::attribute<0> >, 0>, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::tag::new_, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::phoenix::detail::target<gologpp::Reference<gologpp::Variable<gologpp::TypedExpression<gologpp::CompoundType> > > > >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2>, void>’:
/usr/include/boost/phoenix/core/actor.hpp:178:13: required from ‘struct boost::phoenix::result_of::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, …
Run Code Online (Sandbox Code Playgroud) 在阅读了 Spirit X3 关于错误处理的教程和一些实验之后。我得出了一个结论。
\n\n我相信 X3 中的错误处理主题还有一些改进的空间。从我的角度来看,一个重要的目标是提供有意义的错误消息。首先也是最重要的是添加一个将_pass(ctx)
成员设置为 false 的语义操作,\xe2\x80\x99 不会这样做,因为 X3 会尝试匹配其他内容。仅抛出 anx3::expectation_failure
会提前退出解析函数,即不尝试匹配其他任何内容。所以剩下的就是解析器指令expect[a]
和解析器operator>
以及手动抛出x3::expectation_failure
从语义操作中手动抛出。我确实相信有关此错误处理的词汇量太有限。请考虑以下 X3 PEG 语法行:
const auto a = a1 >> a2 >> a3;\nconst auto b = b1 >> b2 >> b3;\nconst auto c = c1 >> c2 >> c3;\n\nconst auto main_rule__def =\n(\n a |\n b |\n c );\n
Run Code Online (Sandbox Code Playgroud)\n\n现在对于表达式a
我不能使用expect[]
or operator>
,因为其他替代方案可能是有效的。我可能是错的,但我认为 X3 要求我拼写出可以匹配的备用错误表达式,如果它们匹配,它们可以抛出x3::expectation_failure
这很麻烦。
问题是,是否有一种好方法可以使用当前的 X3 设施通过 …
What is the simplest way to make a semantic action that extracts a string from a typical identifier parser based on boost::spirit::x3::lexeme
?
I thought it might be possible to bypass needing to unpack the attribute and just use iterators into the input stream but apparently x3::_where
does not do what I think it does.
The following yields output
being empty. I expected it to contain "foobar_hello".
namespace x3 = boost::spirit::x3;
using x3::_where;
using x3::lexeme;
using x3::alpha;
auto ctx_to_string = …
Run Code Online (Sandbox Code Playgroud) 使用 Boost.Spirit 将某些表达式转换为 AST 的正确方法是什么?
我试图构建它,但我认为它很混乱并且可以简化很多。
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace ast {
struct unary_operator;
struct binary_operator;
struct expression {
typedef boost::variant<
double,
std::string,
boost::recursive_wrapper<unary_operator>,
boost::recursive_wrapper<binary_operator>,
boost::recursive_wrapper<expression>
> type;
expression() {
}
template<typename Expr>
expression(const Expr &expr)
: expr(expr) {
}
expression &operator+=(expression rhs);
expression &operator-=(expression rhs);
expression &operator*=(expression rhs);
expression &operator/=(expression rhs);
expression &and_(expression rhs);
expression &or_(expression rhs);
expression &equals(expression rhs);
expression ¬_equals(expression rhs);
expression &less_than(expression rhs);
expression &less_equals(expression rhs);
expression &greater_than(expression rhs);
expression &greater_equals(expression rhs);
expression &factor(expression …
Run Code Online (Sandbox Code Playgroud) 所以,我正在使用boost 1.47.0并且我一直在尝试组合一个词法分析器.
我的目标是为我的词法分析器的一些标记添加一个包含语义的动作
spirit::lex::_pass = spirit::lex::pass_flags::pass_ignore
.但是,我无法编译任何语义操作.我在下面添加了一个(或多或少)最小的例子.我正在编译OS X 10.7.1上的clang.
clang++ -DBOOST_SPIRIT_DEBUG -DBOOST_SPIRIT_LEXERTL_DEBUG -DBOOST_SPIRIT_USE_PHOENIX_V3 -c input.cc
Run Code Online (Sandbox Code Playgroud)
#include <boost/phoenix.hpp>
#include <boost/spirit/home/lex.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/lexer.hpp>
namespace phoenix = boost::phoenix;
namespace spirit = boost::spirit;
struct vhdl_lexer : spirit::lex::lexer< spirit::lex::lexertl::lexer<> > {
vhdl_lexer() {
num = "[0-9]";
any = ".";
this->self
= num
| any
;
}
spirit::lex::token_def<> num, any;
};
Run Code Online (Sandbox Code Playgroud)
#include <boost/phoenix.hpp>
#include <boost/spirit/home/lex.hpp>
#include <boost/spirit/home/lex/lexer/lexertl/lexer.hpp>
namespace phoenix = boost::phoenix;
namespace spirit = boost::spirit;
struct vhdl_lexer : spirit::lex::lexer< spirit::lex::lexertl::lexer<> > {
vhdl_lexer() …
Run Code Online (Sandbox Code Playgroud) 下面我展示了一个不编译的编辑灵魂员工示例.我想解决的问题是解析为不是结构的类.我知道,除了公共/私人之外,它是完全相同的.但是我需要在将类/结构存储到向量之前使用构造函数.如何更改BOOST_FUSION_ADAPT_STRUCT?
我怎么能让它运行?
// STD HEADER
#include <iostream>
#include <string>
#include <complex>
// BOOST HEADER
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
class employee
{
public:
employee (
int _age
, std::string _surname
, std::string _forename
, double _salary
);
private:
int age_;
std::string surname_;
std::string forename_;
double salary_;
};
employee::employee (
int _age
, std::string _surname
, std::string _forename
, double _salary …
Run Code Online (Sandbox Code Playgroud)