Как выйти из подправления, когда определенная часть правила соблюдается?

В настоящее время анализирует сообщения Midi для протокола Firmata в Rebol 3, и столкнулся с ситуацией, которую я раньше не видел.

По сути, у меня есть общее правило для копирования байтов между обрамляющими байтами. Тем не менее, это правило съедает кадрирующие байты. Я сократил код до следующего:

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, которое поможет в этом случае вырваться из subrule?

(Примечание: я знаю, что не интерпретирую данные в соответствии со спецификацией.)

2 ответа

Решение

Вам нужно будет разорвать цикл, когда он попадет в конец sysex так или иначе.

Вы либо сопоставляете sysex-end каждый раз в цикле и прерываете его, либо вы совпадаете только со всем, что не является sysex-end.

Первый вариант, очевидно, вводит sysex-end в subrule, но он кажется простым. Если я переделываю вашу проблему следующим образом:

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 в subrule. Вы делаете битсет! соответствовать всему, кроме 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 bitsets, чтобы знать, есть ли лучший способ указать это.

Второй вариант здесь, вероятно, лучше, потому что он отвечает вашим требованиям и, вероятно, будет работать намного быстрее, чем первый вариант.

Вы могли бы (по крайней мере, в 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

== правда

Другие вопросы по тегам