我是Rust和Nom的新手,我试图解析一个(单)加引号的字符串,其中可能包含转义的引号,例如'foo\' 🤖 bar'
或'λx → x'
,''
或' '
。
我找到了escaped!
宏,其documentation表示:
因为我想在匹配器中匹配除“正常字符”之外的任何反斜杠,所以我尝试使用 take_till!
:
named!(till_backslash<&str, &str>, take_till!(|ch| ch == '\\'));
named!(esc<&str, &str>, escaped!(call!(till_backslash), '\\', one_of!("'n\\")));
let (input, _) = nom::character::complete::char('\'')(input)?;
let (input, value) = esc(input)?;
let (input, _) = nom::character::complete::char('\'')(input)?;
// … use `value`
但是,当尝试解析
'x'
时,这将返回Err(Incomplete(Size(1)))
。搜索时,人们通常建议使用CompleteStr
,但这不是Nom 5中的方法。解决此问题的正确方法是什么? 最佳答案
当在所谓的流模式下运行时,nom
可能会返回Incomplete
来指示它无法确定并需要更多数据。 nom
4引入了CompleteStr
。除了CompleteByteSlice
之外,它们都是&str
和&[u8]
的完整输入对应物。解析器将它们作为完成模式下的输入工作。
它们已在nom
5中消失了。在nom
5中,基于宏的解析器始终以流模式工作,正如您所观察到的。对于将在流模式和完整模式下工作的解析器组合器,它们在不同的子模块中有不同的版本,例如nom::bytes::streaming
和nom::bytes::complete
。
对于所有这些细节,您可能需要 check out this blog post,尤其是Streaming VS complete解析器这一节。
同样,在nom
5中,函数组合器比宏组合器更可取。这是一种实现方法:
//# nom = "5.0.1"
use nom::{
branch::alt,
bytes::complete::{escaped, tag},
character::complete::none_of,
sequence::delimited,
IResult,
};
fn main() {
let (_, res) = parse_quoted(r#"'foo\' 🤖 bar'"#).unwrap();
assert_eq!(res, r#"foo\' 🤖 bar"#);
let (_, res) = parse_quoted("'λx → x'").unwrap();
assert_eq!(res, "λx → x");
let (_, res) = parse_quoted("' '").unwrap();
assert_eq!(res, " ");
let (_, res) = parse_quoted("''").unwrap();
assert_eq!(res, "");
}
fn parse_quoted(input: &str) -> IResult<&str, &str> {
let esc = escaped(none_of("\\\'"), '\\', tag("'"));
let esc_or_empty = alt((esc, tag("")));
let res = delimited(tag("'"), esc_or_empty, tag("'"))(input)?;
Ok(res)
}
关于rust - 使用Nom 5解析带转义引号的单引号字符串,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58904604/