我正在尝试学习 nom ,但遇到了take_while不接受is_digit或任何其他is_xxxx.
我想要解析的行看起来像这样
#123 = ABCDEF (...);
Run Code Online (Sandbox Code Playgroud)
我想得到“123”部分(最终还有 ABCDEF 和 (...) 部分。但当时我猜有一件事)。
我的解析器目前看起来像这样
use nom::{
bytes::complete::take_while,
character::is_digit,
error::ParseError,
IResult
};
// Get row id
fn id<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
take_while(is_digit)(i)
}
Run Code Online (Sandbox Code Playgroud)
定义is_digit看起来像这样
pub fn is_digit(chr: u8) -> bool
Run Code Online (Sandbox Code Playgroud)
由于id解析器采用 a&str它会抱怨类型不匹配。但是是否有可能以某种方式使用 is_digit 呢?我可以在某处进行类型转换而无需分配任何内容吗?我真的希望它尽可能高效。
感觉提供的is_xxxx函数应该在这种情况下使用,但我可能是错的。
谢谢!
我正在尝试为 Rust 项目学习 NOM。我有一个文本文件,其中包含:
[tag="#43674"]char[/tag]每行有多个背靠背的标签。我试图拉出“#43674”和“char”,将它们存储在一个元组中(x, y),然后将它们推入Vec<(x, y)>文本文件每一行的向量中。到目前为止,我已经成功地将解析器组合成两个函数;一个用于“#43674”,一个用于“char”,然后我将它们组合在一起以返回<IResult<&str, (String, String)>。这是代码:
fn color_tag(i: &str) -> IResult<&str, &str> {
delimited(tag("[color="), take_until("]"), tag("]"))(i)
}
fn char_take(i: &str) -> IResult<&str, &str> {
terminated(take_until("[/color]"), tag("[/color]"))(i)
}
pub fn color_char(i: &str) -> IResult<&str, (String, String)> {
let (i, color) = color_tag(i)?;
let (i, chara) = char_take(i)?;
let colors = color.to_string();
let charas = chara.to_string();
let tuple = (colors, charas);
Ok((i, tuple))
}
Run Code Online (Sandbox Code Playgroud)
如何在文本文件的给定行上迭代此函数?我已经有一个将文本文件迭代为行的函数,但我需要color_char对该行中的每个闭包重复该操作。我完全没有抓住重点吗?
我想用 nom 来解析这两个:
[
a,
b,
c
]
Run Code Online (Sandbox Code Playgroud)
[
a,
b,
c,
]
Run Code Online (Sandbox Code Playgroud)
目前我有这段代码可以解析第一个,但不能解析第二个(第一个函数是 nom 文档中的一个配方,它只解析空格):
[
a,
b,
c
]
Run Code Online (Sandbox Code Playgroud)
我是 nom 的新手,对当前的代码没有任何忠诚,所以很好地告诉我我做错了......
谢谢!
我尝试的一切都给了我Incomplete(Size(1)).我现在最好的猜测是:
named!(my_u64(&str) -> u64,
map_res!(recognize!(nom::digit), u64::from_str)
);
Run Code Online (Sandbox Code Playgroud)
测试:
#[cfg(test)]
mod test {
#[test]
fn my_u64() {
assert_eq!(Ok(("", 0)), super::my_u64("0"));
}
}
Run Code Online (Sandbox Code Playgroud)
有时在我的变体(例如添加complete!)中,如果我在最后添加一个字符,我已经能够解析它.
我想得到一个工作解析(最终我希望这将允许我为u64包装类型创建一个解析器)但更大的图片我想了解如何正确地自己构建一个解析器.
有一个文件里面有多个标题,但对我来说,它只重要一个和它后面的数据。此标头在文件中多次重复。
它的幻数是:ASCII 或0x65 0x51 0x48 0x54 0x52十六进制的A3046 。找到第一个字节后,解析器必须获取所有字节,直到0xffEOF,然后对剩余的头重复。
首先我加载了文件:
let mut file = OpenOptions::new()
.read(true)
.open("../assets/sample")
.unwrap();
let mut full_file: Vec<u8> = Vec::new();
file.read_to_end(&mut full_file);
Run Code Online (Sandbox Code Playgroud)
我用以下语句声明幻数:pub static QT_MAGIC: &[u8; 5] = b"A3046";
作为测试,我编写了以下函数只是为了尝试它是否可以找到第一个标头。
fn parse_block(input: &[u8]) -> IResult<&[u8], &[u8]> {
tag(QT_MAGIC)(input)
}
Run Code Online (Sandbox Code Playgroud)
但是,当测试运行时,Ok 有 None有价值。它肯定应该发现了什么。我做错了什么?
我没有发现使用 nom5 解析字节的例子,而且作为一个 rust 新手也无济于事。如何使用这些规则解析所有块?
我正在尝试使用nom的tuple功能。该文档提供了以下示例:
use nom::sequence::tuple;
use nom::character::complete::{alpha1, digit1};
let parser = tuple((alpha1, digit1, alpha1));
Run Code Online (Sandbox Code Playgroud)
当我尝试时,出现编译错误:
error[E0283]: type annotations needed
--> src/main.rs:20:18
|
20 | let parser = tuple((alpha1, digit1, alpha1));
| ------ ^^^^^ cannot infer type for type parameter `I` declared on the function `tuple`
| |
| consider giving `parser` a type
|
Run Code Online (Sandbox Code Playgroud)
如果我想为变量添加一个类型,它会是什么?我知道它必须是 的某种变体FnMut,但我不确定它到底是如何工作的。
Cargo.toml
[dependencies]
nom = ">=5.0"
Run Code Online (Sandbox Code Playgroud) 我可以很好地解析这样的数字:
map_res(digit1, |s: &str| s.parse::<u16>())
Run Code Online (Sandbox Code Playgroud)
但是如何仅解析某个范围内的数字呢?
我有以下数据
let data = r#"title1
title1 line1
title1 line2
sep/
title2
title2 line1
title2 line2
title2 line3
sep/
title3
title3 line1
sep/"#;
Run Code Online (Sandbox Code Playgroud)
基本上它代表三个条目:
struct Entry {
title: String,
body: String,
}
Run Code Online (Sandbox Code Playgroud)
每个条目都有标题和正文。标题消耗单行(不包括行结尾),正文消耗以下所有行,直到遇到分隔线 ( sep/)。我想要的结果是一个条目向量。我如何使用 nom 来解析它?我对 nom 很陌生,我无法让各个部分一起工作并形成一个有效的解析器。以下是我所拥有的:
use nom::IResult;
use nom::branch::alt;
use nom::bytes::complete::{tag, take_until, is_not, is_a};
use nom::error::ErrorKind::ParseTo;
use nom::sequence::{pair, tuple, delimited, terminated};
use nom::combinator::opt;
use nom::error::{Error, ErrorKind};
use nom::character::complete::line_ending;
use nom::regexp::str::{re_find, re_match, re_matches, re_capture};
use nom::multi::many0;
struct Entry {
title: String,
body: String,
}
fn get_entry_title(i: &str) …Run Code Online (Sandbox Code Playgroud) 我想解析一个包含单引号之间的 ASCII 字符的字符串,该字符串可以包含连续两个 ' 的转义单引号。
'包含在单引号之间的字符串值 -> '' 等等...'
这应该导致:
包含在单引号之间的字符串值 -> ' 等等...
use nom::{
bytes::complete::{tag, take_while},
error::{ErrorKind, ParseError},
sequence::delimited,
IResult,
};
fn main() {
let res = string_value::<(&str, ErrorKind)>("'abc''def'");
assert_eq!(res, Ok(("", "abc\'def")));
}
pub fn is_ascii_char(chr: char) -> bool {
chr.is_ascii()
}
fn string_value<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, &'a str, E> {
delimited(tag("'"), take_while(is_ascii_char), tag("'"))(i)
}
Run Code Online (Sandbox Code Playgroud)
如何检测转义引号而不是字符串的结尾?
nom我用7.1版本进行了测试:
use nom::bytes::complete::tag;
#[test]
fn test() {
let (s, t) = tag("1")("123").unwrap();
}
Run Code Online (Sandbox Code Playgroud)
跑步cargo test给予
use nom::bytes::complete::tag;
#[test]
fn test() {
let (s, t) = tag("1")("123").unwrap();
}
Run Code Online (Sandbox Code Playgroud)
它建议我指定tag::<T, Input, Error>()
我该如何处理这个问题?我还没有完全理解为什么会出现这个问题。
我尝试指定一些类型nom:
error[E0283]: type annotations needed
--> src/main.rs:5:18
|
5 | let (s, t) = tag("1")("123").unwrap();
| ^^^ cannot infer type for type parameter `Error` declared on the function `tag`
|
= note: cannot satisfy `_: ParseError<&str>`
note: required by a bound in `nom::bytes::complete::tag` …Run Code Online (Sandbox Code Playgroud) 解析器按预期工作,直到我要解析h:始终是字符串中最后一位的数字,并且编译器给了我
^ expected &str, found struct `nom::types::CompleteStr`
Run Code Online (Sandbox Code Playgroud)
我认为这是因为解析器正在向前看。我该如何停止,或如何表示已完成?
#[macro_use]
extern crate nom;
use nom::digit;
use nom::types::CompleteStr;
use std::str::FromStr;
#[derive(Debug, PartialEq)]
pub struct Order {
pub l: u64,
pub w: u64,
pub h: u64,
}
named!(order_parser<CompleteStr, Order>,
do_parse!(
l: map_res!(digit, u64::from_str) >>
tag!("x") >>
w: map_res!(digit, u64::from_str) >>
tag!("x") >>
h: map_res!(digit, u64::from_str) >>
(Order {l: l, w: w, h: h })
)
);
pub fn wrap_order(order: &str) -> Result<(CompleteStr, Order), nom::Err<&str>> {
order_parser(order)
}
#[test]
fn test_order_parser() { …Run Code Online (Sandbox Code Playgroud) 假设我想创建一个多次使用另一个解析器的组合器,例如,解析由两种引号分隔的字符串:
fn quoted<'a, F: 'a, O, E: ParseError<&'a str>>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
map(
alt((
tuple((tag("'"), f, tag("'"))),
tuple((tag("\""), f, tag("\"")))
)),
|(_, res, _)| res,
)
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,该解析器无法编译并出现“使用移动值”错误:
fn quoted<'a, F: 'a, O, E: ParseError<&'a str>>(f: F) -> impl Fn(&'a str) -> IResult<&'a str, O, E>
where
F: Fn(&'a str) -> IResult<&'a str, O, E>,
{
map(
alt((
tuple((tag("'"), f, tag("'"))),
tuple((tag("\""), f, …Run Code Online (Sandbox Code Playgroud)