Я использую nom для анализа некоторых двоичных данных сборки 65c816. Часть моей структуры парсера разбивает коды операций на отдельные формы, а затем получает их параметры, если они есть. Пример парсера в настоящее время выглядит так:
named!(absolute_long<Instruction>,
do_parse!(op: bits!(alt!(
opcode!(0x0F) | opcode!(0x22) | opcode!(0x2F) | opcode!(0x4F) |
opcode!(0x5C) | opcode!(0x6F) | opcode!(0x8F) | opcode!(0xAF) |
opcode!(0xCF) | opcode!(0xEF)))
>> param: le_u24
>> (Instruction::AbsoluteLong(op, param))));
Где opcode!
— это макрос, который я сделал следующим образом:
macro_rules! opcode(
($i:expr, $op:expr) => (
tag_bits!($i, u8, 8, $op);
);
($i:expr, $f:expr) => (
opcode!($i, call!($f));
);
);
Вместо этого я хотел бы иметь код, подобный следующему, но не могу понять, как сделать макрос или функцию для этого:
named!(absolute_long<Instruction>,
do_parse!(op: opcodes!(
0x0F, 0x22, 0x2F, 0x4F, 0x5C, 0x6F, 0x8F, 0xAF,
0xCF, 0xEF)
>> param: le_u24
>> (Instruction::AbsoluteLong(op, parm)));
Самое близкое, что я получил, это сделать этот макрос, но он почти сразу упирается в ограничения рекурсии и в целом кажется действительно неоптимальным:
macro_rules! opcodes(
($i:expr, $op:expr) => {
opcode!($i, $op)
};
($i:expr, $op:expr, $($more:expr), *) => (
bits!($i, alt!(opcode!($op) | opcodes!($($more),*)))
);
);
Есть ли способ реализовать что-то подобное или мне лучше просто использовать tag_bits
? Я чувствую, что должен иметь возможность использовать one_of
, но я не могу заставить его работать с байтами.