我有一个用于解析标识符的解析器foo, bar, baz和一个用于解析嵌套标识符的解析器,foo::bar, foo::bar.baz, foo::bar.baz.baham
它们都解析为相同的ast结构,如下所示:
struct identifier : x3::position_tagged{
std::vector <std::string> namespaces;
std::vector <std::string> classes;
std::string identifier;
};
Run Code Online (Sandbox Code Playgroud)
解析器identifier看起来像这样:
#define VEC_ATR x3::attr(std::vector<std::string>({})) //ugly hack
auto const identifier_def =
VEC_ATR
>> VEC_ATR
>> id_string;
Run Code Online (Sandbox Code Playgroud)
对于nested_identifier这样的:
auto const nested_identifier_def =
x3::lexeme[
(+(id_string >> "::") >> +(id_string >> ".") > id_string)
| (+(id_string >> "::") >> VEC_ATR > id_string)
| (VEC_ATR >> +(id_string >> ".") > id_string)
| identifier
];
Run Code Online (Sandbox Code Playgroud)
我知道这个宏让我感到羞耻.标识符解析器工作正常,但
nested_identifier有一个奇怪的行为,如果我尝试解析像foo::bar::baz落在了解析器的AST对象,拥有所有的命名空间,在这种情况下 …
如何防止 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) 是否有某个文档描述了各种spirit :: x3规则定义操作如何影响属性兼容性?
我很惊讶:
x3::lexeme[ x3::alpha > *(x3::alnum | x3::char_('_')) ]
Run Code Online (Sandbox Code Playgroud)
无法移动到融合适应的结构中:
struct Name {
std::string value;
};
Run Code Online (Sandbox Code Playgroud)
目前,我摆脱了第一个强制字母字符,但我仍然想表达一个规则,该规则定义名称字符串必须以字母开头.这是其中一种情况,我需要尝试添加eps,直到它工作,或有一个明确的原因,为什么上述不起作用?
如果在某处写下来,我道歉,我找不到它.
如果我有一个结构:
struct person{
bool is_male;
std::string name;
std::vector<std::string> friends;
}
Run Code Online (Sandbox Code Playgroud)
要么
enum class gender_t{male, female}
struct person{
gender_t gender;
std::string name;
std::vector<std::string> friends;
}
Run Code Online (Sandbox Code Playgroud)
如何使用boost.spirit X3解析此结构?规则如何解析“ alice male bob”之类的字符串,解析器将返回一个名称为alice的对象,该对象是male,并且有一个朋友bob。如果这个人不是女性,那么如果性别只是露骨的话,会是什么样?
(1)假设我们要解析一个简单的递归块{}.
{
Some text.
{
{
Some more text.
}
Some Text again.
{}
}
}
Run Code Online (Sandbox Code Playgroud)
这个递归解析器非常简单.
x3::rule<struct idBlock1> const ruleBlock1{"Block1"};
auto const ruleBlock1_def =
x3::lit('{') >>
*(
ruleBlock1 |
(x3::char_ - x3::lit('}'))
) >>
x3::lit('}');
BOOST_SPIRIT_DEFINE(ruleBlock1)
Run Code Online (Sandbox Code Playgroud)
(2)然后块变得更复杂.它也可能被包围[].
{
Some text.
[
{
Some more text.
}
Some Text again.
[]
]
}
Run Code Online (Sandbox Code Playgroud)
我们需要在某处存放我们拥有的开放式支架.由于x3没有本地,我们可能会使用attribute(x3::_val).
x3::rule<struct idBlock2, char> const ruleBlock2{"Block2"};
auto const ruleBlock2_def = x3::rule<struct _, char>{} =
(
x3::lit('{')[([](auto& ctx){x3::_val(ctx)='}';})] |
x3::lit('[')[([](auto& ctx){x3::_val(ctx)=']';})]
) …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) 在阅读了 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 );\nRun 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 x3进行解析.我完成了语法,解析器按预期解析.现在我想添加错误处理,所以我必须为我的语法添加期望点.我的问题是我何时可以使用期望运算符>而不是"跟随"运算符>>?我只能用它像a > b如果a >> b在语法的另一部分永远不会发生?
Spirit X3如此“无状态”的目的是什么?
回顾Spirit V2,“语法”在许多方面在概念上都是有状态的。这是因为语法是类实例。
基本上,使语法(甚至任何一条规则)变得有状态有很多不良方面:
从理论上讲,添加外部状态会使您的语法变得不平凡。
相反,您可以说任何解析器都是有状态的(因为它解析当前上下文并且上下文是状态)。下面是程序员添加其他“上下文”的一个好例子:
quoted_string_ = as_string [omit [char_("'\"") [_a = _1]] >> *(char_ - lit(_a)) >> lit(_a)]
Run Code Online (Sandbox Code Playgroud)
qi::locals是非外部国家的好兆头。
程序员可以在语法中添加一些“外部状态”,并且在大多数情况下,它们只是在做错误的事情:
func_call_ = func_name_ >> lit('(') >> eps [ref(is_inside_function_call) = true] >> ...
Run Code Online (Sandbox Code Playgroud)
但是,在某些极端情况下,外部状态很有用。
macro_type_1_ =
lit("{{{") [PUSH_STATE(macro_ctx, Macro::Type1)] >> (
((any_expr_ - end_of_macro_ctx_) >> lit("}}}") >> eps [POP_STATE(macro_ctx)]) |
(eps [POP_STATE(macro_ctx)] >> eps [_pass = false])
)
;
macro_type_2_ =
lit("[[[") [PUSH_STATE(macro_ctx, Macro::Type2)] >> (
((any_expr_ - end_of_macro_ctx_) >> …Run Code Online (Sandbox Code Playgroud) boost-spirit ×10
boost-spirit-x3 ×10
c++ ×10
boost ×3
parsing ×3
c++14 ×2
c++11 ×1
recursion ×1