2

目前正在为 Rebol 3 中的Firmata 协议解析 Midi 消息,并遇到了我以前从未见过的情况。

基本上,我有一个通用规则来在帧字节之间复制字节。然而,该规则正在吃掉帧字节。我已将代码简化为以下内容:

data: #{
    F06C00010101040E7F000101010308040E7F00010101040E7F0001010103
    08040E7F000101010308040E7F00010101040E7F00010101040E7F0001010103
    08040E7F000101010308040E7F000101010308040E7F00010101040E7F000101
    01040E7F00010101020A7F00010101020A7F00010101020A7F00010101020A7F
    00010101020A06017F00010101020A06017FF7
}

sysex-start: #{F0}
sysex-end: #{F7}
capability-query: #{6B}
capability-response: #{6C}
capability-end: #{7F}

received-rule: [
    sysex-start
    capability-response-rule 
    sysex-end
]

capability-response-rule: [
    capability-response
    [
        capability-end |
        some [copy pin 1 skip]
    ]
]
parse data received-rule

问题是some [copy pin 1 skip]正在吞噬sysex-end二进制文件。

  • 有没有办法可以重组规则(不sysex-end进入子规则)?

  • 在这种打破子规则的情况下,是否有一个 parse 关键字可以帮助?

(注意:我知道我没有根据规范解释数据。)

4

2 回答 2

3

当它以一种或另一种方式到达 sysex-end 时,您需要打破循环。

您可以每次在循环周围匹配 sysex-end 并在它命中时中断,或者您只匹配不是 sysex-end 的所有内容。

第一个选项显然将 sysex-end 带入子规则,但看起来很简单。如果我这样改写你的问题:

problem-rule: [
    (matched-bytes: none)
    copy matched-bytes some [skip]
]

那么使用 NOT 关键字的第一个解决方案可能是:

alternative-1: [
    (matched-bytes: none)
    copy matched-bytes some [
        not sysex-end
        skip
    ]
]

第二种选择不会将 sysex-end 带入子规则。你做了一个bitset!匹配除 sysex-end 之外的所有内容(247 对应于十六进制 F7):

not-sysex-end: bits: make bitset! [0 - 246 248 - 255]
alternative-2: [
    (matched-bytes: none)
    copy matched-bytes some [not-sysex-end]
]

我对 Rebol 3 位集不够熟悉,不知道是否有更好的方法来指定它。

这里的第二种选择可能更好,因为它满足您的要求并且可能比第一种选择执行得更快。

于 2014-06-22T13:59:31.790 回答
2

你可以(至少在 Rebol2 中)使用

pin-set: complement charset to-string #{F7} 

received-rule: [
    sysex-start
    capability-response-rule 
    sysex-end
]

capability-response-rule: [
    capability-response
    [
        capability-end |
        some  [copy pin pin-set  ]
    ]
]
parse data received-rule

== 真

于 2014-06-22T13:32:07.710 回答