一旦满足规则的某一部分,如何打破一个子规则?

时间:2014-06-22 01:22:10

标签: midi rebol rebol3 firmata

目前正在为Rebol 3中的Firmata protocol解析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移到子规则中)?

  • 是否有一个解析关键字可以帮助解决这个问题?

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

2 个答案:

答案 0 :(得分: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引入子规则。你搞砸了!匹配除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位集不够熟悉,知道是否有更好的方法来指定它。

这里的第二种选择可能更好,因为它符合您的要求,并且可能比第一种选择更快。

答案 1 :(得分: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

== true