灵气条件解析
Spirit Qi conditional parsing
我正在写一个pdf解析库。
曾几何时,我有一个像这样解析的输入:
1 0 obj
(anything)
endobj
我已经为外部容器创建了解析规则,然后为内部对象创建了单独的规则:
CONTAINER_PARSER %=
number >> number >> "obj" >> OBJECT_PARSER >> "endobj";
OBJECT_PARSER %= number | value | ...
这没有任何问题。但是,出于各种原因,我不得不重新设计规则,以便两个容器值都属于对象本身。
容器本身只是可选的。意思是,前面的代码和下面的代码表示相同的对象,没有额外的容器信息:
(anything)
我有 2 个想法,如何解决这个问题,但在我看来,这两个想法都不符合 Qi 方法。
替代解析器
我想告诉解析器,要么解析包含在 obj - endobj 中的值,要么只解析该值。
start %=
(
object_number
>> generation_number
>> qi::lit("obj")
>> object
> qi::lit("endobj")
) | object;
// I intentionally missed some semantic actions assigning the values to the object,
because it is out of the scope of my problem
我没能成功,因为交替的两个部分具有相同的公开属性,编译器感到困惑。
可选方法
我试图告诉解析器,前一个容器对于解析值来说只是可选的。
start %=
-(
object_number
>> generation_number
>> qi::lit("obj")
)
>> object
> -qi::lit("endobj");
这种方法的问题是,如果第一部分也存在,那么最后一部分 "endobj" 必须存在。
解决方案可能很简单,但我真的无法从代码、文档和 Whosebug 答案中找出答案。
更新评论后:
start =
(
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
) >> "obj" >> object > "endobj"
| qi::attr(1) >> qi::attr(0) >> object
)
;
假设您对(可选)数字不感兴趣:
start =
-qi::omit [ object_number >> generation_number ]
>> "obj" >> object > "endobj"
;
如果您有兴趣并且有合适的默认值:
start =
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
)
>> "obj" >> object > "endobj"
;
当然可以
将收件人类型更改为 object_numbers 的 optional<int>
,这样您就可以简单地 -object_number >> -generation_number
;这有点草率,因为它还允许 "1 obj (anything) endobj"
将收件人类型更改为变体:
boost::variant<simple_object, object_contaier>
在这种情况下,您的 AST 与您问题中的 "alternative" 方法(第一个)相匹配
我正在写一个pdf解析库。
曾几何时,我有一个像这样解析的输入:
1 0 obj
(anything)
endobj
我已经为外部容器创建了解析规则,然后为内部对象创建了单独的规则:
CONTAINER_PARSER %=
number >> number >> "obj" >> OBJECT_PARSER >> "endobj";
OBJECT_PARSER %= number | value | ...
这没有任何问题。但是,出于各种原因,我不得不重新设计规则,以便两个容器值都属于对象本身。
容器本身只是可选的。意思是,前面的代码和下面的代码表示相同的对象,没有额外的容器信息:
(anything)
我有 2 个想法,如何解决这个问题,但在我看来,这两个想法都不符合 Qi 方法。
替代解析器
我想告诉解析器,要么解析包含在 obj - endobj 中的值,要么只解析该值。
start %=
(
object_number
>> generation_number
>> qi::lit("obj")
>> object
> qi::lit("endobj")
) | object;
// I intentionally missed some semantic actions assigning the values to the object,
because it is out of the scope of my problem
我没能成功,因为交替的两个部分具有相同的公开属性,编译器感到困惑。
可选方法
我试图告诉解析器,前一个容器对于解析值来说只是可选的。
start %=
-(
object_number
>> generation_number
>> qi::lit("obj")
)
>> object
> -qi::lit("endobj");
这种方法的问题是,如果第一部分也存在,那么最后一部分 "endobj" 必须存在。
解决方案可能很简单,但我真的无法从代码、文档和 Whosebug 答案中找出答案。
更新评论后:
start =
(
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
) >> "obj" >> object > "endobj"
| qi::attr(1) >> qi::attr(0) >> object
)
;
假设您对(可选)数字不感兴趣:
start =
-qi::omit [ object_number >> generation_number ]
>> "obj" >> object > "endobj"
;
如果您有兴趣并且有合适的默认值:
start =
( object_number >> generation_number
| qi::attr(1) > qi::attr(0) // defaults
)
>> "obj" >> object > "endobj"
;
当然可以
将收件人类型更改为 object_numbers 的
optional<int>
,这样您就可以简单地-object_number >> -generation_number
;这有点草率,因为它还允许"1 obj (anything) endobj"
将收件人类型更改为变体:
boost::variant<simple_object, object_contaier>
在这种情况下,您的 AST 与您问题中的 "alternative" 方法(第一个)相匹配