我正在尝试std::array使用boost :: spirit的最新版本x3(包含在boost 1.54中)将数字列表解析为固定大小的容器.由于std::array具有必要的功能,因此它被检测为容器,但缺少插入功能,使其不兼容.这是我想要完成的一个简短示例:
#include <boost/spirit/home/x3.hpp>
#include <array>
#include <iostream>
#include <string>
namespace x3 = boost::spirit::x3;
namespace ascii = boost::spirit::x3::ascii;
typedef std::array<double, 3> Vertex;
int main(int, char**) {
using x3::double_;
using ascii::blank;
std::string input = "3.1415 42 23.5";
auto iter = input.begin();
auto vertex = x3::rule<class vertex, Vertex>{} =
double_ >> double_ >> double_;
Vertex v;
bool const res = x3::phrase_parse(iter, input.end(), vertex, blank, v);
if (!res || iter != input.end()) return EXIT_FAILURE;
std::cout << "Match:" …Run Code Online (Sandbox Code Playgroud) 所以,我已经编写了我的语法,并希望提供一些调试信息,如行号,以便能够使用我自己的调试器逐步生成生成的可执行代码.
经过一些谷歌搜索后,我发现可以完全定义规则中使用的标记类,如下所示:
x3::rule<class CodeLine, ast::InstructionOrDirectiveAndArgs> const code_line = "code_line";
auto const code_line_def = ...
class CodeLine {
public:
template <typename T, typename Iterator, typename Context>
inline void on_success(Iterator const& first, Iterator const& last, T& ast, Context const& context) {
static std::uint64_t line = 0;
auto& error_handler = x3::get<error_handler_tag>(context).get();
error_handler.tag(ast, first, last);
ast.line_no = line;
if (*last == '\0') {
line = 0;
} else {
line += 1;
}
}
};
Run Code Online (Sandbox Code Playgroud)
在这个完全定义的标记类中,可以实现on_success方法,该方法在成功匹配规则时调用.所以我为匹配一行代码的规则实现了标记类.但由于我找不到从精神中获取当前行号的方法,因此我采用了跟踪当前行的静态变量.问题是要知道何时重置行计数器,正如你在我非常愚蠢的尝试中看到的那样.
这似乎是一种非常复杂的方式来跟踪行号,因此必须有更好的方法.
现在的问题是,获得当前行号的最佳或正确方法是什么?
谢谢阅读!
使用boost::spirit::x3::position_tagged某些AST节点的基类(如何选择应标记哪些,例如用于类C语言?)以及在规则ID定义中使用的其他结构时的逻辑是什么,如:
struct error_handler_tag;
struct error_handler_base
{
template< typename Iterator, typename Exception, typename Context >
x3::error_handler_result
on_error(Iterator & /*first*/, Iterator const & /*last*/,
Exception const & x, Context const & context)
{
std::string message_ = "Error! Expecting: " + x.which() + " here:";
auto & error_handler = x3::get< error_handler_tag >(context).get();
error_handler(x.where(), message_);
return x3::error_handler_result::fail;
}
};
struct annotation_base
{
template< typename T, typename Iterator, typename Context >
void
on_success(Iterator const & first, Iterator const & last,
T & ast, …Run Code Online (Sandbox Code Playgroud) 我试图在将结构解析为AST时使用具有语义动作的Boost Spirit X3.如果我使用没有单独定义和实例化的规则它可以正常工作,例如:
#include <vector>
#include <string>
#include <iostream>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/home/x3.hpp>
namespace ast
{
struct ast_struct
{
int number;
std::vector<int> numbers;
};
}
BOOST_FUSION_ADAPT_STRUCT(
ast::ast_struct,
(int, number)
(std::vector<int>, numbers)
)
namespace x3 = boost::spirit::x3;
using namespace std;
void parse( const std::string &data )
{
string::const_iterator begin = data.begin();
string::const_iterator end = data.end();
unsigned n(0);
auto f = [&n]( auto &ctx )
{
n = x3::_attr(ctx);
};
ast::ast_struct ast;
bool r = x3::parse( begin, end,
x3::int_[f] >> +( x3::omit[+x3::blank] …Run Code Online (Sandbox Code Playgroud) 使用Boost.Spirit X3,我想将逗号分隔的范围列表和单个数字(例如1-4,6,7,9-12)解析为单个std::vector<int>.这是我想出的:
namespace ast {
struct range
{
int first_, last_;
};
using expr = std::vector<int>;
}
namespace parser {
template<typename T>
auto as_rule = [](auto p) { return x3::rule<struct _, T>{} = x3::as_parser(p); };
auto const push = [](auto& ctx) {
x3::_val(ctx).push_back(x3::_attr(ctx));
};
auto const expand = [](auto& ctx) {
for (auto i = x3::_attr(ctx).first_; i <= x3::_attr(ctx).last_; ++i)
x3::_val(ctx).push_back(i);
};
auto const number = x3::uint_;
auto const range = as_rule<ast::range> (number >> …Run Code Online (Sandbox Code Playgroud) 我试图找出istream使用x3 解析的正确方法。较旧的文档指的是multi_pass东西,我仍然可以使用它吗?还是有其他方法来缓冲X3的流,以便它可以回溯?
我正在尝试用Spirit X3编写一个解析器,但我还没有走得太远,因为我遇到了一个我无法弄清楚的编译错误.我想我知道编译器在抱怨什么,但我不明白为什么它会关心.以下代码编译(clang 3.9,Boost 1.62.0)并且有效.(我意识到它的结构很差,并且有常量的内置解析器;我只是试图证明这个问题.)
#define BOOST_SPIRIT_X3_DEBUG
#include <iostream>
#include <boost/spirit/home/x3.hpp>
using namespace std;
namespace x3 = boost::spirit::x3;
namespace lang {
using namespace x3;
struct Constant {
};
rule<class constant_id, Constant> const constant = "constant";
auto const integer_literal = -char_('-') >> +digit;
auto const float_literal = -char_('-') >> +digit >> -(char_('.') >> *digit);
auto const constant_def = (integer_literal)[([](auto &ctx) { _val(ctx) = Constant(); })];
BOOST_SPIRIT_DEFINE(constant);
}
int main(int argc, char *argv[]) {
string s("3.14159");
if (x3::phrase_parse(s.begin(), s.end(), lang::constant, x3::space)) {
cout …Run Code Online (Sandbox Code Playgroud) 我在boost :: spirit :: x3中编写了以下递归规则,但它似乎只在g ++/clang中编译,而不是VS2017(15.5.3):
#include <iostream>
#include <boost/spirit/home/x3.hpp>
namespace lex3
{
namespace x3 = boost::spirit::x3;
x3::rule<struct foo_class> const foo = "foo";
x3::rule<struct bar_class> const bar = "bar";
auto bar_def = *((x3::char_ - "/*") - "*/") >> *(foo > *((x3::char_ - "/*") - "*/"));
auto foo_def = "/*" > bar > "*/";
BOOST_SPIRIT_DEFINE(foo)
BOOST_SPIRIT_DEFINE(bar)
}
int main(int argc, char** argv)
{
std::string input = "/* a /* nested */ comment */";
auto f = input.begin();
auto l = input.end(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试编写一个解析器,它解析a int32_t或a double.作为第一次尝试,我写了这个解析器:
const auto int_or_double = boost::spirit::x3::int32 | boost::spirit::x3::double_;
Run Code Online (Sandbox Code Playgroud)
我期望得到一个boost::variant<int32_t, double>
解析器成功解析整数,12, 100, -42, 7但它无法解析双打像13.243, 42.7, 12.0 -10000.3
这是一个现场演示
为什么这个解析器在双打时失败?
我正在尝试使用Boost.Sprit x3将两个整数的序列匹配成一个std::pair<int, int>.根据文档判断,以下代码应该编译:
#include <string>
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
int main()
{
using namespace boost::spirit::x3;
std::string input("1 2");
std::pair<int, int> result;
parse(input.begin(), input.end(), int_ >> int_, result);
}
Run Code Online (Sandbox Code Playgroud)
但是,它只匹配第一个整数.如果我改变std::pair<int, int> result;对int result;,然后打印result,我得到1我的输出.
为什么会这样?这不是int_ >> int_定义匹配(并设置为属性)两个整数的解析器的正确方法吗?
boost-spirit-x3 ×10
c++ ×10
boost-spirit ×6
c++14 ×5
boost ×4
parsing ×2
boost-fusion ×1
stdarray ×1