Как реализовать подобный take_until_and_consume комбинатор парсера, который не пропускает тег?
Я хотел бы написать комбинатор имени синтаксического анализатора, который занимает столько байтов до и включая последовательность тегов. Я пытался с помощью take_until_and_consume!
, но я обнаружил, что сгенерированный синтаксический анализатор отбрасывает последовательность тегов:
#[macro_use]
extern crate nom;
named!(up_to_and_including_backslash, take_until_and_consume!("\\"));
fn main() {
let res = up_to_and_including_backslash(b" \\");
println!("{:?}", res);
}
Результаты в:
Done([], [32, 32, 32, 32])
Я хотел бы, чтобы последовательность тегов (в данном случае символ обратной косой черты) была включена в результат:
Done([], [32, 32, 32, 32, 92])
Как я могу сделать это?
2 ответа
Обновить:
Вы хотите использовать recognize!
на take_until_and_consume!("\\")
чтобы добавить все, что он потребляет на выходе.
Вы бы написали свою функцию парсера следующим образом:
#[macro_use]
extern crate nom;
named!(up_to_and_including_backslash, recognize!( take_until_and_consume!("\\") ));
fn main() {
let res = up_to_and_including_backslash(b" \\");
println!("{:?}", res);
}
В случае, если вам нужно включить потребляемые символы нескольких парсеров в ваш вывод, вы можете поместить их все в do_parse!
в recognize!
, Вот так:
recognize!( do_parse!( tag!("\\") >> take_until_and_consume!("\\") >> take!(4) >> () ) )
старый:Единственный способ заставить это работать - это мерзкая мерзость.
named!(up_to_and_including_backslash,
do_parse!(
line: take_until_and_consume!("\\") >>
(
{
let mut complete_line:Vec<u8> = line.to_vec();
complete_line.extend_from_slice(b"\\");
&*complete_line
}
)
)
);
Прямо сейчас вы используете метод take_until_and_consume
чья документация гласит:
генерирует синтаксический анализатор байтов, пока не будет найдена указанная последовательность байтов, и потребляет ее
Потребляющая часть важна, так как это то, чего вы хотите избежать.
Вы могли бы сделать что-то похожее на это:
named!(up_to_and_including_backslash,
do_parse!(
line: take_until!("\\") >> char!('\\') >>
(line)
)
);
Который должен вернуть линию с вашим сепаратором.