Parsing 如何将字符串向量与nom匹配?
我正在尝试使用nom创建一个解析器,它将解析一些文本,这可能是许多选项之一。诺姆有alt!因为当值在编译时是已知的,但我的值不会 这是我试图创建自己的解析器的尝试,可以使用Vec进行匹配,我遇到了几个问题Parsing 如何将字符串向量与nom匹配?,parsing,rust,nom,Parsing,Rust,Nom,我正在尝试使用nom创建一个解析器,它将解析一些文本,这可能是许多选项之一。诺姆有alt!因为当值在编译时是已知的,但我的值不会 这是我试图创建自己的解析器的尝试,可以使用Vec进行匹配,我遇到了几个问题 #[macro_use] extern crate nom; use nom::IResult; fn alternative_wrapper<'a>(input: &'a [u8], alternatives: Vec<String>) -> IRe
#[macro_use]
extern crate nom;
use nom::IResult;
fn alternative_wrapper<'a>(input: &'a [u8], alternatives: Vec<String>) -> IResult<&'a [u8], &'a [u8]> {
for alternative in alternatives {
// tag!("alternative");
println!("{}", alternative);
}
return IResult::Done(input, "test".as_bytes());
}
#[test]
fn test_date() {
let input = "May";
named!(alternative, call!(alternative_wrapper));
let months = vec!(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
).iter().map(|s| s.to_string()).collect();
println!("{:?}", alternative("May".as_bytes(), months));
}
如何从函数中创建解析器?以及如何使用现有的解析器,如tag!在alternative_wrapper?中,我对nom不是很熟悉,并且仍在学习Rust,但我过去使用过解析器组合器 撇开警告不谈,它看起来像是命名的!宏生成一个只接受一个参数的函数,即要分析的字符串 为了满足nom的期望,我想我应该考虑将alternative_包装器编写为一个返回函数的函数。测试结果如下所示:
#[test]
fn test_date() {
let months = vec!(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
).iter().map(|s| s.to_string()).collect();
let parser = generate_alternative_parser(months);
named!(alternative, call!(parser));
println!("{:?}", alternative("May".as_bytes()));
}
看起来你需要构造一个alt!从标签表达!s、 但从文件上看,我并不清楚你会怎么做
您的选项列表最终来自哪里
根据你想要完成的事情,可能还有其他一些方法来完成你想要完成的事情。例如,您可能能够解析任何单词,然后根据您的一个选项对其进行验证。我对nom不是很熟悉,仍在学习Rust,但我过去使用过解析器组合器 撇开警告不谈,它看起来像是命名的!宏生成一个只接受一个参数的函数,即要分析的字符串 为了满足nom的期望,我想我应该考虑将alternative_包装器编写为一个返回函数的函数。测试结果如下所示:
#[test]
fn test_date() {
let months = vec!(
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
).iter().map(|s| s.to_string()).collect();
let parser = generate_alternative_parser(months);
named!(alternative, call!(parser));
println!("{:?}", alternative("May".as_bytes()));
}
看起来你需要构造一个alt!从标签表达!s、 但从文件上看,我并不清楚你会怎么做
您的选项列表最终来自哪里
根据你想要完成的事情,可能还有其他一些方法来完成你想要完成的事情。例如,您可能能够解析任何单词,然后根据其中一个选项对其进行验证。从错误开始,第一个错误是由于命名!只接受一个参数,即输入字符串。命名!将为您声明一个函数,在本例中使用签名fn&[u8]>IResult。任何其他参数都没有神奇之处,所以尝试将月向量作为第二个参数传递是行不通的。有一个命名的变体!叫阿格斯!它可以用来声明具有更多参数的函数,而不仅仅是应该进行排序的输入 第二个错误类似,但相反。您正在通过call!仅使用输入而不使用向量调用替代_包装器!。电话!宏实际上可以传递参数,但必须显式传递,即调用!我的朋友,蒙兹 在整理出错误的原因后,您将询问如何创建解析器。实际上,alternative_wrapper已经是一个通过签名的nom解析器了,但是由于您没有通过nom宏声明它,所以没有任何神奇的输入传递发生,这就是为什么标记!当您尝试时,在函数体中不起作用 为了在您自己声明的函数中使用其他组合符,必须手动将输入传递到最外层的宏。在这种情况下,它是唯一的标签!,但是如果你要使用,比如说,不要解析!然后在其中包含多个宏,您只需传递输入即可执行\u parse!。我将在这里提供一个工作版本,其中包含一些额外的调整:
#[macro_use]
extern crate nom;
use std::str;
use nom::IResult;
fn alternative<'a>(input: &'a [u8], alternatives: &Vec<String>) -> IResult<&'a [u8], &'a [u8]> {
for alternative in alternatives {
match tag!(input, alternative.as_bytes()) {
done@IResult::Done(..) => return done,
_ => () // continue
}
}
IResult::Error(nom::ErrorKind::Tag) // nothing found.
}
fn main() {
let months: Vec<String> = vec![
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
].into_iter().map(String::from).collect();
fn print_res(r: IResult<&[u8],&[u8]>) {
println!("{:?}", r);
println!("{:?}\n", str::from_utf8(r.unwrap().1).unwrap());
}
print_res(alternative(b"May", &months));
print_res(alternative(b"August", &months));
print_res(alternative(b"NoGood", &months));
}
您可以在中查看。从错误开始,第一个错误是由于命名错误引起的!只接受一个参数,即输入字符串。命名!将为您声明一个函数,在本例中使用签名fn&[u8]>IResult。任何其他参数都没有神奇之处,所以尝试将月向量作为第二个参数传递是行不通的。有一个命名的变体!叫阿格斯!它可以用来声明具有更多参数的函数,而不仅仅是应该进行排序的输入 第二个错误类似,但相反。您正在通过call!仅使用输入而不使用向量调用替代_包装器!。电话!宏实际上可以传递参数,但必须显式传递,即调用!我的朋友,蒙兹 在整理出错误的原因后,您将询问如何创建解析器。实际上,alternative_wrapper已经是一个通过签名的nom解析器了,但是由于您没有通过nom宏声明它,所以没有任何神奇的输入传递发生,这就是为什么标记!当您尝试时,在函数体中不起作用 为了在您自己声明的函数中使用其他组合符,必须手动将输入传递到最外层的宏。在这种情况下,它是唯一的标签!,但是如果你要使用,比如说,不要解析!然后是多个宏w 在这方面,您只需传递输入即可进行解析!。我将在这里提供一个工作版本,其中包含一些额外的调整:
#[macro_use]
extern crate nom;
use std::str;
use nom::IResult;
fn alternative<'a>(input: &'a [u8], alternatives: &Vec<String>) -> IResult<&'a [u8], &'a [u8]> {
for alternative in alternatives {
match tag!(input, alternative.as_bytes()) {
done@IResult::Done(..) => return done,
_ => () // continue
}
}
IResult::Error(nom::ErrorKind::Tag) // nothing found.
}
fn main() {
let months: Vec<String> = vec![
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
].into_iter().map(String::from).collect();
fn print_res(r: IResult<&[u8],&[u8]>) {
println!("{:?}", r);
println!("{:?}\n", str::from_utf8(r.unwrap().1).unwrap());
}
print_res(alternative(b"May", &months));
print_res(alternative(b"August", &months));
print_res(alternative(b"NoGood", &months));
}
您可以在使用Nom 4的.中查看它,这里是一个完全通用的输入,无论您的解析器对什么进行操作都有效:
/// Dynamic version of `alt` that takes a slice of strings
fn alternative<T>(input: T, alternatives: &[&'static str]) -> IResult<T, T>
where
T: InputTake,
T: Compare<&'static str>,
T: InputLength,
T: AtEof,
T: Clone,
{
let mut last_err = None;
for alternative in alternatives {
let inp = input.clone();
match tag!(inp, &**alternative) {
done @ Ok(..) => return done,
err @ Err(..) => last_err = Some(err), // continue
}
}
last_err.unwrap()
}
/// Usage
named!(test<Span, Span>,
call!(alternative, &["a", "b", "c"])
);
对于Nom 4,这里是一个完全通用的输入,无论您的解析器对其进行操作:
/// Dynamic version of `alt` that takes a slice of strings
fn alternative<T>(input: T, alternatives: &[&'static str]) -> IResult<T, T>
where
T: InputTake,
T: Compare<&'static str>,
T: InputLength,
T: AtEof,
T: Clone,
{
let mut last_err = None;
for alternative in alternatives {
let inp = input.clone();
match tag!(inp, &**alternative) {
done @ Ok(..) => return done,
err @ Err(..) => last_err = Some(err), // continue
}
}
last_err.unwrap()
}
/// Usage
named!(test<Span, Span>,
call!(alternative, &["a", "b", "c"])
);