- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我是 Boost Spirit 的新手,正在努力创建一个正确的表达式来解析以下输入(实际上是某些命令的标准输出的结果):
^+ line-17532.dyn.kponet.fi 2 7 377 1 +1503us[+9103us] +/- 55ms
我需要将其解析为一组字符串和整数并记录在变量中。该行的大部分内容应该被解析为适当类型(字符串或整数)的变量。所以最后,我得到:
string: "^+", "line-17532.dyn.kponet.fi", "+1503us", "+9103us", "55ms"
int : 2, 7, 377, 1
一对
+1503us[+9103us]
也可以带空格
+503us[ +103us]
我需要将方括号之前和方括号中的内容放在单独的字符串中。
此外,时间指定可以表示为
ns, ms, us, s
我很欣赏有关如何处理它的示例,因为可用的文档非常稀疏且不连贯。
大块日志,以及描述各个字段的标题:
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^+ ns2.sdi.fi 2 9 377 381 -1476us[-1688us] +/- 72ms
^+ line-17532.dyn.kponet.fi 2 10 377 309 +302us[ +302us] +/- 59ms
^* heh.fi 2 10 377 319 -1171us[-1387us] +/- 50ms
^+ stara.mulimuli.fi 3 10 377 705 -1253us[-1446us] +/- 73ms
最佳答案
一如既往,我从绘制有用的 AST 开始:
namespace AST {
using clock = std::chrono::high_resolution_clock;
struct TimeSample {
enum Direction { up, down } direction; // + or -
clock::duration value;
};
struct Record {
std::string prefix; // "^+"
std::string fqdn; // "line-17532.dyn.kponet.fi"
int a, b, c, d; // 2, 7, 377, 1
TimeSample primary, braced;
clock::duration tolerance;
};
}
现在我们知道我们想要解析什么,我们主要只是用规则模仿 AST,有点:
using namespace qi;
start = skip(blank) [record_];
record_ = prefix_ >> fqdn_ >> int_ >> int_ >> int_ >> int_ >> sample_ >> '[' >> sample_ >> ']' >> tolerance_;
prefix_ = string("^+"); // or whatever you need to match here
fqdn_ = +graph; // or whatever additional constraints you have
sample_ = direction_ >> duration_;
duration_ = (long_ >> units_) [ _val = _1 * _2 ];
tolerance_= "+/-" >> duration_;
当然,有趣的是单位和方向:
struct directions : qi::symbols<char, AST::TimeSample::Direction> {
directions() { add("+", AST::TimeSample::up)("-", AST::TimeSample::down); }
} direction_;
struct units : qi::symbols<char, AST::clock::duration> {
units() {
using namespace std::literals::chrono_literals;
add("s", 1s)("ms", 1ms)("us", 1us)("µs", 1us)("ns", 1ns);
}
} units_;
空白接受由 skipper 管理;我为非词素规则选择了qi::blank_type
:
using Skipper = qi::blank_type;
qi::rule<It, AST::Record()> start;
qi::rule<It, AST::Record(), Skipper> record_;
qi::rule<It, AST::TimeSample(), Skipper> sample_;
qi::rule<It, AST::clock::duration(), Skipper> duration_, tolerance_;
// lexemes:
qi::rule<It, std::string()> prefix_;
qi::rule<It, std::string()> fqdn_;
把它们放在一起,使用它:
int main() {
std::istringstream iss(R"(^+ line-17532.dyn.kponet.fi 2 7 377 1 +1503us[+9103us] +/- 55ms
)");
std::string line;
while (getline(iss, line)) {
auto f = line.cbegin(), l = line.cend();
AST::Record record;
if (parse(f, l, parser<>{}, record))
std::cout << "parsed: " << boost::fusion::as_vector(record) << "\n";
else
std::cout << "parse error\n";
if (f!=l)
std::cout << "remaining unparsed input: '" << std::string(f,l) << "'\n";
}
}
打印: Live On Coliru
parsed: (^+ line-17532.dyn.kponet.fi 2 7 377 1 +0.001503s +0.009103s 0.055s)
(下面的调试输出)
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <sstream>
#include <chrono>
namespace std { namespace chrono {
// for debug
std::ostream& operator<<(std::ostream& os, duration<double> d) { return os << d.count() << "s"; }
} }
namespace AST {
using clock = std::chrono::high_resolution_clock;
struct TimeSample {
enum Direction { up, down } direction; // + or -
clock::duration value;
// for debug:
friend std::ostream& operator<<(std::ostream& os, Direction d) {
char const* signs[] = {"+","-"};
return os << signs[d];
}
friend std::ostream& operator<<(std::ostream& os, TimeSample const& sample) {
return os << sample.direction << std::chrono::duration<double>(sample.value).count() << "s";
}
};
struct Record {
std::string prefix; // "^+"
std::string fqdn; // "line-17532.dyn.kponet.fi"
int a, b, c, d; // 2, 7, 377, 1
TimeSample primary, braced;
clock::duration tolerance;
};
}
BOOST_FUSION_ADAPT_STRUCT(AST::Record, prefix, fqdn, a, b, c, d, primary, braced, tolerance)
BOOST_FUSION_ADAPT_STRUCT(AST::TimeSample, direction, value)
namespace qi = boost::spirit::qi;
template <typename It = std::string::const_iterator>
struct parser : qi::grammar<It, AST::Record()> {
parser() : parser::base_type(start) {
using namespace qi;
start = skip(blank) [record_];
record_ = prefix_ >> fqdn_ >> int_ >> int_ >> int_ >> int_ >> sample_ >> '[' >> sample_ >> ']' >> tolerance_;
prefix_ = string("^+"); // or whatever you need to match here
fqdn_ = +graph; // or whatever additional constraints you have
sample_ = direction_ >> duration_;
duration_ = (long_ >> units_) [ _val = _1 * _2 ];
tolerance_= "+/-" >> duration_;
BOOST_SPIRIT_DEBUG_NODES(
(start)(record_)
(prefix_)(fqdn_)(sample_)(duration_)(tolerance_)
)
}
private:
struct directions : qi::symbols<char, AST::TimeSample::Direction> {
directions() { add("+", AST::TimeSample::up)("-", AST::TimeSample::down); }
} direction_;
struct units : qi::symbols<char, AST::clock::duration> {
units() {
using namespace std::literals::chrono_literals;
add("s", 1s)("ms", 1ms)("us", 1us)("µs", 1us)("ns", 1ns);
}
} units_;
using Skipper = qi::blank_type;
qi::rule<It, AST::Record()> start;
qi::rule<It, AST::Record(), Skipper> record_;
qi::rule<It, AST::TimeSample(), Skipper> sample_;
qi::rule<It, AST::clock::duration(), Skipper> duration_, tolerance_;
// lexemes:
qi::rule<It, std::string()> prefix_;
qi::rule<It, std::string()> fqdn_;
};
int main() {
std::istringstream iss(R"(^+ line-17532.dyn.kponet.fi 2 7 377 1 +1503us[+9103us] +/- 55ms
)");
std::string line;
while (getline(iss, line)) {
auto f = line.cbegin(), l = line.cend();
AST::Record record;
if (parse(f, l, parser<>{}, record))
std::cout << "parsed: " << boost::fusion::as_vector(record) << "\n";
else
std::cout << "parse error\n";
if (f!=l)
std::cout << "remaining unparsed input: '" << std::string(f,l) << "'\n";
}
}
<start>
<try>^+ line-17532.dyn.kp</try>
<record_>
<try>^+ line-17532.dyn.kp</try>
<prefix_>
<try>^+ line-17532.dyn.kp</try>
<success> line-17532.dyn.kpon</success>
<attributes>[[^, +]]</attributes>
</prefix_>
<fqdn_>
<try>line-17532.dyn.kpone</try>
<success> 2 7 377 </success>
<attributes>[[l, i, n, e, -, 1, 7, 5, 3, 2, ., d, y, n, ., k, p, o, n, e, t, ., f, i]]</attributes>
</fqdn_>
<sample_>
<try> +1503us[+9103us] </try>
<duration_>
<try>1503us[+9103us] +/- </try>
<success>[+9103us] +/- 55ms</success>
<attributes>[0.001503s]</attributes>
</duration_>
<success>[+9103us] +/- 55ms</success>
<attributes>[[+, 0.001503s]]</attributes>
</sample_>
<sample_>
<try>+9103us] +/- 55ms</try>
<duration_>
<try>9103us] +/- 55ms</try>
<success>] +/- 55ms</success>
<attributes>[0.009103s]</attributes>
</duration_>
<success>] +/- 55ms</success>
<attributes>[[+, 0.009103s]]</attributes>
</sample_>
<tolerance_>
<try> +/- 55ms</try>
<duration_>
<try> 55ms</try>
<success></success>
<attributes>[0.055s]</attributes>
</duration_>
<success></success>
<attributes>[0.055s]</attributes>
</tolerance_>
<success></success>
<attributes>[[[^, +], [l, i, n, e, -, 1, 7, 5, 3, 2, ., d, y, n, ., k, p, o, n, e, t, ., f, i], 2, 7, 377, 1, [+, 0.001503s], [+, 0.009103s], 0.055s]]</attributes>
</record_>
<success></success>
<attributes>[[[^, +], [l, i, n, e, -, 1, 7, 5, 3, 2, ., d, y, n, ., k, p, o, n, e, t, ., f, i], 2, 7, 377, 1, [+, 0.001503s], [+, 0.009103s], 0.055s]]</attributes>
</start>
关于c++ - 使用 Boost Spirit Qi 解析特定字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42888172/
假设我们要解析一个内积表达式并得到结果。 "SUM({1, 2, 3} .* {4, 5, 6})" qi::_1 和 qi::_2 非常方便地在解析器中引用第 i 个属性。 void Test(st
无法弄清楚为什么这条规则 unary_msg 不起作用,它说属性类型是 qi::unused_type 但这对我来说毫无意义。为什么 boost 会这样折磨我? template struct g3:
从测试中我可以得到 qi::uint_parser()与 qi::uint_ 相同.他们从 0 解析整数至 UINT_MAX . 我不明白的是qi::uint_parser需要 std::numeri
bool EqnExprEvaluator::SetEqn(const std::string& eqnStr) { typedef std::string::const_iterator
我一直在使用 Boost 库中的 Spirit Qi 用 C++ 编写语法。作为该语言的新手,很难习惯该库的语法和怪癖,但现在我有点了解它的工作原理。 我在使用 qi::lexeme 时遇到错误。我的
我需要跟踪一些项目在我使用提升灵气解析的文本中的位置。我找到了 this example并适应这样: #include #include #include #include #include
我想做的是在运行时从 ABNF 语法文件创建一个解析器。我已经在 qi::grammar 中实现了所有 ABNF 规则,如下所示: typedef /*qi::rule or struct conta
我在boost_1.59中使用spirit来解析类c语言(名为stone,最初由java编写)。但是我在使用 boost::spirit::qi 解析 c 风格的字符串时遇到了麻烦。整个代码位于 co
我正在用 Boost.Spirit 做一个 IRC 消息解析器,但是当我尝试解析一个输入时我遇到了一个(很长的)错误。我遵循了“Roman Numerals”示例。此外,我将 g++4.7 与 -st
如何解析可能包含 double 或 int 的字符串,具体取决于是否设置了点。例如。 6.0是double类型,6是int类型。规则是 rule,skipper> r = qi::double_|qi
在 boost::spirit::traits::transform_attribute 中指示解析失败的正确方法是什么?我可以抛出任何旧的异常,还是它要我做的特定事情? namespace boos
我正在尝试使用 qi 创建通用解析器元素,因为不幸的是(必须支持 MSVC)无法使用 X3。这个想法是有一个模板化的结构: template struct parse_type; 我可以这样使用: t
我正在尝试创建一个返回 function 的规则通过柯里化(Currying) Phoenix 表达式构造。例如, start = int_[_val = xxx]; rule start; 应该做什
我正在解析一个文本文件,可能有几 GB 的大小,由以下几行组成: 11 0.1 14 0.78 532 -3.5 基本上,每行一个整数和一个 float 。整数应该是有序的并且是非负的。我想验证数据是
我想提出一个让我陷入困境的主题,并提出了一个关于齐::符号。 这一切都始于我查看新的野兽图书馆并阅读 atutorial example 它以一个从 http 路径猜测 mime 类型的函数开始扩展。
我有一段 boost::spirit::qi 代码可以匹配 "M7.x.y.z" 或 "M7.x.y.z ",但我想要一个在前一个输入上失败的解析器。 我想我需要在其中插入 qi::lexeme[]
我正在尝试为一种语言的多个子集定义一些 Boost::spirit::qi 解析器,代码重复最少。为此,我创建了一些基本的规则构建函数。原来的解析器工作正常,但一旦我开始使用组合函数,我的解析器似乎就
假设我有一个简单的类型foo: struct foo { void bar(int) { // do something } }; 我想使用 Boost.Qi 来解析字符串中的整数字段,并使用结果值调
(免责声明,我正在学习提升精神) 我正在尝试解析这样的表达式:F( 1 ) 并希望将 1 作为字符串(“1”而不是数字(与 qi::int_ 一起使用))。 我试过这样的事情(这是错误的,但也许我的方
假设我有两个用逗号分隔的 double 来解析返回它们的总和。在 Haskell 中我可能会这样做: import Data.Attoparsec.Text import Data.Text (pac
我是一名优秀的程序员,十分优秀!