Boost Spirit罗马数字解析器示例
Boost Spirit Roman Numeral Parser Example
尝试学习boost spirit和文档中给出的示例让我有点困惑。
参照这段代码:
http://www.boost.org/doc/libs/1_46_1/libs/spirit/example/qi/roman.cpp尤其是这段语法:
start = eps [_val = 0] >>
(
+lit('M') [_val += 1000]
|| hundreds [_val += _1]
|| tens [_val += _1]
|| ones [_val += _1]
)
谁能给我解释一下为什么是+lit('M')而不是*lit('M') ?因为毕竟不能有0个或多个M而不是1个或多个M吗?
Spirit中的a || b
运算符是指a
或b
,如果出现a
,则a
之后是b
。在运算符的含义中,没有M
的情况是隐含的(因为M
的匹配可能存在,也可能不存在)。此外,在*lit('M')
的情况下,如果有NO M
,您会说第一个规则是匹配的吗?无论如何,它都是有效的,并且_val
将增加1000。
+lit('M')
和*lit('M')
都正确。但在我看来,前者比后者更具可读性(语义上),因为前者说如果有one
匹配,则将 1000
添加到_val
,并重复执行。另一方面,后者很难读取,因为人们可以将其读取为将 1000
添加到_val
,即使是零匹配也是错误的。1000
没有被添加到_val
进行零次匹配,然而解析器*lit('M')
似乎也匹配零次匹配(似乎有点令人困惑)。
所以+lit('M')
是最好的。
好吧。我读了你的评论。CCLLIX
不是一个有效的罗马数字。你认为它的价值是什么?309
吗?如果是这样,那么CCCIX
的值是多少?太309了,这是正确的。你的错了。因此,当您使用*lit('M')
时,解析器会停止。还要注意,即使对错误的输入使用+lit('M')
,解析器也会停止。
它是(一个或多个m)或百或十或一。(零个或多个m)或百位或十位或一将不匹配m,即空字符串,并无意义地添加1000。
在Qi中匹配表达式A || B
意味着只匹配A
,或者只匹配B
或A followed by B
。因此,在您的示例中,+lit('M') || hundreds
表示+lit('M')
、hundreds
或+lit('M')followed by hundreds
。由于这个原因,语法允许匹配任何罗马数字,甚至不以M
开头。
- Boost Spirit,获取迭代器内部语义动作
- boost::spirit::karma 替代生成器,带有 boost::variant 由字符串和字符串别名组成
- boost::spirit::x3 中的通用解析器生成器
- Boost.Spirit将表达转换为AST
- 使用 Boost.Spirit 解析具有混合数据类型的 OBJ 文件?
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- Boost Spirit X3:将(一些)空格解析为枚举
- Boost Spirit x3 条件(三元)运算符解析器
- 你如何从 Boost Spirit X3 词法解析器中获取字符串?
- 将 Boost.Spirit.X3 解析器拆分为多个 TU
- boost::spirit::x3 中的简单字符串解析器不起作用
- boost::spirit指针属性是用nullptr初始化的吗?
- Boost.Spirit Alternative Parser parallelization
- 如何在 boost::spirit::qi 中将某些语义操作排除在 AST 之外
- 自定义预期失败的完整错误消息(boost::spirit::x3)
- boost::spirit--试图编译大多数简单代码的编译器错误
- Boost.Spirit.Qi 语法,用于 Boost.Fusion 自适应结构中的默认值
- 使用 Boost.Spirit 解析嵌套列表
- (如何)我可以在不安装完整的提升库的情况下使用 boost::spirit X3 吗?
- n-ary布尔语法从中缀到前缀的Boost::Spirit转换?