1

我用 nom 写了一个完全无状态的解析器,现在我需要将它包装在几个有状态的层中。

我有一个名为的顶级解析函数alt_fn,它将为我提供下一个解析输出作为枚举变量,其中的细节可能并不重要。

我需要做三件涉及状态的事情:

1)我需要有条件地对输出进行转换,如果在作为我的结构alt_fn的一部分的非可变 HashMap 中有匹配项。State这应该基本上就像map!我的结构上的一个方法调用。像这样的东西:

named!(alt_fn<AllTags> ,alt!(// snipped for brevity));

fn applyMath(self, i:AllTags)->AllTags { // snipped for brevity }

method!(apply_math<State, &[u8], AllTags>, mut self, call_m!(self.applyMath, call!(alt_fn)));

这目前给了我:error: unexpected end of macro invocationalt_fn下划线。

2)我需要用我从输入中得到的数据更新状态结构的其他字段(例如计算校验和和更新时间戳等),然后用这个新知识再次转换输出。这可能如下所示:

fn updateState(mut self, i:AllTags) -> AllTags { // snipped for brevity }

method!(update_state<State, &[u8], AllTags>, mut self, call_m!(self.updateState, call_m!(self.applyMath)));

3)我需要重复调​​用第二部分中的方法,直到所有输入都用完:

method!(pub parse<State,&[u8],Vec<AllTags>>, mut self, many1!(update_state));

不幸的是,nom文档非常有限,而且我对宏语法不是很好,所以我不知道我做错了什么。

4

1 回答 1

1

当我需要做一些复杂的事情时nom,我通常会编写自己的函数。

例如

named!(my_func<T>, <my_macros>);

相当于

fn my_func(i: &[u8]) -> nom::IResult<T, &[u8]> {
    <my_macros>
}

附带条件是您必须传递i给宏(请参阅我的评论)。

创建自己的函数意味着您可以在其中拥有任何想要的控制流,nom只要它需要一个 &[u8] 并返回 nom::IResult ,其中输出 &[u8] 是剩余的未解析的原始数据,它就会很好用输入。

如果您需要更多信息评论,我会尽力改进我的答案!

于 2017-12-22T19:56:24.017 回答