Я пытаюсь использовать Nom 6.1.2 для анализа относительно простого Lisp-подобного языка, где мне нужно захватывать идентификаторы формы [a-z][a-zA-Z0-9_\-\.]
. Я попытался использовать re_match
, но ожидается, что весь input
будет соответствовать не только первой части строки. Я хочу иметь возможность сопоставлять эти идентификаторы как часть более крупного контекста, поэтому я хочу, чтобы он возвращал оставшуюся часть ввода для передачи другим синтаксическим анализаторам в виде комбинатора синтаксического анализатора.
fn name(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
let re = Regex::new(r"^[A-Za-z][a-zA-Z0-9_\.\-]*$").unwrap();
context("name", re_match(re))(input)
}
Я хочу пройти следующий тест:
#[test]
fn test_name() {
assert_eq!(name("test"), Ok(("", "test")));
assert_eq!(name("test1-test2"), Ok(("", "test1-test2")));
assert_eq!(name("test1.test2"), Ok(("", "test1.test2")));
assert_eq!(name("test1_test2"), Ok(("", "test1_test2")));
assert_eq!(name("Test1_Test2"), Ok(("", "Test1_Test2")));
assert!(name("123Test").is_err());
//this last assertion fails
assert_eq!(name("test1 test2$!%"), Ok((" test2$!%", "test1")));
}
Последнее утверждение в приведенном выше тесте не выполняется.
thread 'parser::tests::test_name' panicked at 'assertion failed: `(left == right)`
left: `Err(Error(VerboseError { errors: [("test1 test2$!%", Nom(RegexpMatch)), ("test1 test2$!%", Context("name"))] }))`,
right: `Ok((" test2$!%", "test1"))`', src\parser.rs:69:9
stack backtrace:
Если бы я использовал что-то вроде функции alphanumeric
, это работало бы нормально, но это не захватывает нужное мне регулярное выражение.
Я мог бы вручную написать код и каким-то образом проверить первый символ и последующие, но у меня есть несколько других ситуаций, когда мне нужно анализировать разные регулярные выражения, и это станет недостижимым.
Как правильно выбрать часть, которая соответствует регулярному выражению, и продолжить синтаксический анализ остальной части более крупного ввода?