gpt4 book ai didi

parsing - Chomp 中的序列组合器是什么?

转载 作者:行者123 更新时间:2023-11-29 08:11:38 26 4
gpt4 key购买 nike

我正在尝试解析 JSON 的一个子集,该子集仅包含一个非嵌套对象,该对象仅包含可能包含转义序列的字符串值。例如

{
"A KEY": "SOME VALUE",
"Another key": "Escape sequences \n \r \\ \/ \f \t \u263A"
}

使用 Chomp Rust 中的解析器组合器。我让它解析这个忽略转义序列的结构,但我无法弄清楚如何处理转义序列。查看其他使用组合器的带引号的字符串解析器,例如:

它们各自使用一个序列组合器,Chomp 中的等价物是什么?

最佳答案

Chomp 基于 Attoparsec 和 Parsec,因此为了解析转义字符串,我会使用 scan解析器获取 " 字符之间的切片,同时保留任何转义的 " 字符。

序列组合器就是ParseResult::bind方法,用于链接 " 字符和转义字符串本身的匹配,以便它能够解析 "foo\\"bar" 而不仅仅是 foo\\"bar。当您使用 parse! 宏时,您可以免费获得它,每个 ; 都隐式转换为对链的 bind 调用解析器在一起。

链接的解析器使用 manyor组合子并为结果字符分配一个向量。 Paka 似乎没有对结果数组进行任何转换,PHP 正在使用带有回调的正则表达式来取消转义字符串。

这是翻译自Attoparsec's Aeson benchmark 的代码用于解析 JSON 字符串而不对任何转义字符进行转义。

#[macro_use]
extern crate chomp;

use chomp::*;
use chomp::buffer::IntoStream;
use chomp::buffer::Stream;

pub fn json_string(i: Input<u8>) -> U8Result<&[u8]> {
parse!{i;
token(b'"');
let escaped_str = scan(false, |s, c| if s { Some(false) }
else if c == b'"' { None }
else { Some(c == b'\\') });
token(b'"');

ret escaped_str
}
}

#[test]
fn test_it() {
let r = "\"foo\\\"bar\\tbaz\"".as_bytes().into_stream().parse(json_string);

assert_eq!(r, Ok(&b"foo\\\"bar\\tbaz"[..]));
}

上面的解析器不是等价的,它产生了从源缓冲区/切片中借来的 u8 切片。如果您想要数据的自有 Vec,您最好使用 [T]::to_vecString::from_utf8而不是使用 manyor 构建解析器,因为它不会像 scan 那样快并且结果是相同的。

如果你想解析 UTF-8 和转义序列,你可以过滤结果切片,然后在 Vec 上调用 String::from_utf8(Rust 字符串是 UTF -8,使用包含无效 UTF-8 的字符串会导致未定义的行为)。如果性能是一个问题,您最有可能将其构建到解析器中。

关于parsing - Chomp 中的序列组合器是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34102089/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com