我正在尝试使用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"))`', srcparser.rs:69:9
stack backtrace:
如果我使用类似alphanumeric
函数的东西,这会很好,但这并不能捕获我想要的正则表达式。
我可以亲自编写代码,并以某种方式检查第一个字符和随后的字符,但在其他几种情况下,我需要解析不同的正则表达式,这将变得无法维护。
获取与正则表达式匹配的部分并继续解析其余较大输入的正确方法是什么?
我试过了,部分问题是正则表达式末尾的$。这将告诉正则表达式匹配器匹配整个输入直到结束,否则将不匹配。
另一个问题是re_match((。在nom-docs中,如果找到匹配项(无论匹配多少个字符(,re_match将返回整个输入。您想要的是re_find((函数,它将返回第一个匹配项。