#midi #rebol #rebol3 #firmata
#midi #ребол #ребол3 #firmata
Вопрос:
В настоящее время разбираю 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, которое помогло бы в этом случае выйти из подчиненного правила?
(Примечание: я знаю, что я не интерпретирую данные в соответствии со спецификацией.)
Комментарии:
1. В качестве примечания я склонен считать, что правило синтаксического анализа легче читать, если вы задаете
|
его собственную строку и выравниваете ее по скобкам в группе, в которую оно входит, когда вы помещаете альтернативы в их собственные строки. YMMV.
Ответ №1:
Вам нужно будет прервать цикл, когда он так или иначе попадет в 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