Parsing Chomp中的序列组合子是什么?

Parsing Chomp中的序列组合子是什么?,parsing,rust,Parsing,Rust,我试图解析JSON的一个子集,该子集只包含一个非嵌套的对象,该对象的值可能只包含转义序列的字符串。例如 { "A KEY": "SOME VALUE", "Another key": "Escape sequences \n \r \\ \/ \f \t \u263A" } 在Rust中使用解析器组合器。我在解析这个结构时忽略了转义序列,但是我在解决如何处理转义序列时遇到了困难。查看其他使用组合符的引用字符串解析器,例如: 它们各自使用一个序列组合符,在Chomp?状态中的等

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

{
  "A KEY": "SOME VALUE",
  "Another key": "Escape sequences \n \r \\ \/ \f \t \u263A"
}
在Rust中使用解析器组合器。我在解析这个结构时忽略了转义序列,但是我在解决如何处理转义序列时遇到了困难。查看其他使用组合符的引用字符串解析器,例如:

它们各自使用一个序列组合符,在
Chomp

状态中的等价物是什么(强调我的):

使用解析器几乎完全是使用
parse宏,它使我们能够执行三项不同的操作:

  • 剩余输入上的序列解析器
  • 将中间结果存储到数据类型中
  • 在末尾返回一个数据类型,它可能是对中间结果进行任意计算的结果
然后,它提供了解析由两个数字和一个常量字符串组成的序列的示例:

fn f(i: Input<u8>) -> U8Result<(u8, u8, u8)> {
    parse!{i;
        let a = digit();
        let b = digit();
                string(b"missiles");
        ret (a, b, a + b)
    }
}

fn digit(i: Input<u8>) -> U8Result<u8> {
    satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0')
}
各国(强调我国):

使用解析器几乎完全是使用
parse宏,它使我们能够执行三项不同的操作:

  • 剩余输入上的序列解析器
  • 将中间结果存储到数据类型中
  • 在末尾返回一个数据类型,它可能是对中间结果进行任意计算的结果
然后,它提供了解析由两个数字和一个常量字符串组成的序列的示例:

fn f(i: Input<u8>) -> U8Result<(u8, u8, u8)> {
    parse!{i;
        let a = digit();
        let b = digit();
                string(b"missiles");
        ret (a, b, a + b)
    }
}

fn digit(i: Input<u8>) -> U8Result<u8> {
    satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0')
}

Chomp基于Attoparsec和Parsec,因此对于解析转义字符串,我将使用解析器获取
字符之间的片段,同时保留任何转义的
字符

#[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"[..]));
}
序列组合器只是一种方法,用于链接
字符和转义字符串本身的匹配,以便它能够解析
“foo\\”bar“
,而不仅仅是
foo”\\“条形码。当您使用宏时,每个
,您都可以免费获得此信息
隐式转换为
bind
调用,以将解析器链接在一起

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

这是从中翻译的代码,用于解析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"[..]));
}
#[宏使用]
外部板条箱咀嚼;
使用chomp::*;
使用chomp::buffer::IntoStream;
使用chomp::buffer::Stream;
pub fn json_字符串(i:Input)->U8Result{
解析!{i;
代币(b’);
设escape_str=scan(false,| s,c | if s{Some(false)}
如果c==b'{None}
else{Some(c==b'\\'});
代币(b’);
雷特街
}
}
#[测试]
fn测试_it(){
让r=“\”foo\\\”bar\\tbaz\”。作为\u字节()。转换为\u流()。解析(json字符串);
断言(r,Ok(&b“foo\\\”bar\\tbaz”[…]);
}
上面的解析器不是等价的,它从源缓冲区/切片中借用
u8
切片。如果您想要拥有数据的
Vec
,最好使用,或者不要使用
many
构建解析器,因为它不会像
扫描
那么快,结果是一样的。


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

Chomp基于Attoparsec和Parsec,因此对于解析转义字符串,我将使用解析器获取
字符之间的片段,同时保留所有转义的
字符

#[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"[..]));
}
序列组合器只是一种方法,用于链接
字符和转义字符串本身的匹配,以便它能够解析
“foo\\”bar“
,而不仅仅是
foo\\”bar
。当您使用宏时,每个
,您都可以免费获得此信息
隐式转换为
bind
调用,以将解析器链接在一起

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

这是从中翻译的代码,用于解析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"[..]));
}
#[宏使用]
外部板条箱咀嚼;
使用chomp::*;
使用chomp::buffer::IntoStream;
使用chomp::buffer::Stream;
pub fn json_字符串(i:Input)->U8Result{
解析!{i;
代币(b’);
设escape_str=scan(false,| s,c | if s{Some(false)}
如果c==b'{None}
else{Some(c==b'\\'});
代币(b’);
雷特街
}
}
#[测试]
fn测试_it(){
让r=“\”foo\\\”bar\\tbaz\”。作为\u字节()。转换为\u流()。解析(json字符串);
断言(r,Ok(&b“foo\\\”bar\\tbaz”[…]);
}
上面的解析器不是等价的,它从源缓冲区/切片中借用
u8
切片。如果您想要拥有数据的
Vec
,最好使用,或者不要使用
many
构建解析器,因为它不会像
扫描
那么快,结果是一样的。

如果要解析UTF-8和转义序列,可以过滤生成的片段,然后在
Vec上调用
String::from_utf8