spirit.x3:将本地数据传递给解析器
Boost中的示例。Spirit文档似乎在两种情况下下降了:
1/定义一个函数中的解析器:语义动作可以访问本地变量和数据,因为它们是本地lambdas。像 push_back
在此处: https://www.boost.org/doc/libs/master/master/libs/spirit/spirit/doc/doc/x3/html/spirit_x3/spirit_x3/tutorials/number_list__stuffing__stuffing_numbers_numbers_numbers_numbers_numbers_numbers_aumbers_au_a_a_a_a_a
parcy_ecter parnige int partm 命名空间,就像这里: https://www.boost.org/doc/libs/1_69_0/libs/spirit/doc/doc/x3/html/spirit_x3/tutorials/minimal.html
似乎是必要的,这是必要的代码> boost_spirit_define 。
我的问题是:如何将两者(正确,没有全球群体)组合?我的梦想中的API是将一些参数转移到 phrase_parse
中,然后做一些 x3 :: _ arg(ctx)
,但我找不到这样的东西。
例如,这是我的解析器:现在,这些动作正在写入 std :: cerr
。如果我想写入自定义 std :: ostream&
,该怎么办,这将传递给 parse
函数怎么办?
using namespace boost::spirit;
using namespace boost::spirit::x3;
rule<struct id_action> action = "action";
rule<struct id_array> array = "array";
rule<struct id_empty_array> empty_array = "empty_array";
rule<struct id_atom> atom = "atom";
rule<struct id_sequence> sequence = "sequence";
rule<struct id_root> root = "root";
auto access_index_array = [] (const auto& ctx) { std::cerr << "access_array: " << x3::_attr(ctx) << "\n" ;};
auto access_empty_array = [] (const auto& ctx) { std::cerr << "access_empty_array\n" ;};
auto access_named_member = [] (const auto& ctx) { std::cerr << "access_named_member: " << x3::_attr(ctx) << "\n" ;};
auto start_action = [] (const auto& ctx) { std::cerr << "start action\n" ;};
auto finish_action = [] (const auto& ctx) { std::cerr << "finish action\n" ;};
auto create_array = [] (const auto& ctx) { std::cerr << "create_array\n" ;};
const auto action_def = +(lit('.')[start_action]
>> -((+alnum)[access_named_member])
>> *(('[' >> x3::int_ >> ']')[access_index_array] | lit("[]")[access_empty_array]));
const auto sequence_def = (action[finish_action] % '|');
const auto array_def = ('[' >> sequence >> ']')[create_array];
const auto root_def = array | action;
BOOST_SPIRIT_DEFINE(action)
BOOST_SPIRIT_DEFINE(array)
BOOST_SPIRIT_DEFINE(sequence)
BOOST_SPIRIT_DEFINE(root)
bool parse(std::string_view str)
{
using ascii::space;
auto first = str.begin();
auto last = str.end();
bool r = phrase_parse(
first, last,
parser::array_def | parser::sequence_def,
ascii::space
);
if (first != last)
return false;
return r;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于方法:
1/是,这对于小的,包含的解析器是可行的。通常仅在单个TU中使用,并通过非生成界面暴露。
2/这是您可能希望散布在TUS和/或在几个TU上实例化的(大多数)语法的方法。
请注意,您不需要
boost_spirit_define
,除非您[这变得非常复杂
如果要求之一是“没有全球群体”,则不能将某些内容与名称空间级别的声明结合在一起。
我不知道您的想法
x3 :: _ arg(ctx)
在那个特定的梦中会做什么:)现在这是一个具体的问题。我会说:使用上下文。
您可以做到这一点,以便可以使用
x3 :: get&lt; ostream&gt;(ctx)
返回流:现在您需要在解析过程中的上下文中将标记的参数放在:
live demo: http://coliru.stacked-crooked.com/a/a26c8eb0af6370b9 </
a26c8eb0af6370b9
调试输出:
但是等待#1-事件处理程序
看起来您正在解析类似于JSON指针或
JQ
语法的内容。如果您想提供回调式接口(SAX-事件),为什么不绑定回调界面而不是操作:现在您可以在一个接口中整齐地实现所有处理程序:
请参阅 <>
=“ nofollow noreferrer” >
http://coliru.stacked-crooked.com/a/a/a983e762a8a2afbf“ rel 将建立一个AST。另请参见增强精神:“语义动作是邪恶的”吗?
没有更多的ado:
当然,我正在做一些假设。规则可以简化:
解析功能返回AST :(
请注意,现在它投掷
x3 :: expection_failure
如果输入无效或不完全解析)现在打印:
请参阅 <
About the approaches:
1/ Yes, this is viable for small, contained parsers. Typically only used in a single TU, and exposed via non-generic interface.
2/ This is the approach for (much) larger grammars, that you might wish to spread across TUs, and/or are instantiated across several TU's generically.
Note that you do NOT need
BOOST_SPIRIT_DEFINE
unless youThe Question
You can't combine something with namespace level declarations, if one of the requiremenents is "without globals".
I don't know what you think
x3::_arg(ctx)
would do, in that particular dream :)Now that's a concrete question. I'd say: use the context.
You could make it so that you can use
x3::get<ostream>(ctx)
returns the stream:Now you need to put the tagged param in the context during parsing:
Live Demo: http://coliru.stacked-crooked.com/a/a26c8eb0af6370b9
Prints
Intermixed with the standard X3 debug output:
But Wait #1 - Event Handlers
It looks like you're parsing something similar to JSON Pointer or
jq
syntax. In the case that you wanted to provide a callback-interface (SAX-events), why not bind the callback interface instead of the actions:Now you can implement all handlers neatly in one interface:
See it Live On Coliru once again:
But Wait #2 - No Actions
The natural way to expose attributes would be to build an AST. See also Boost Spirit: "Semantic actions are evil"?
Without further ado:
Of course, I'm making some assumptions. The rules can be much simplified:
And the parsing function returns the AST:
(Note that it now throws
x3::expection_failure
if the input is invalid or not completely parsed)Now prints:
See it Live On Coliru