Разобрать строку с экранированными одинарными кавычками - PullRequest
2 голосов
/ 22 октября 2019

Я хочу проанализировать строку, содержащую символы 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)
}

Как я могу обнаружить экранированные кавычки, а не конец строки?

1 Ответ

1 голос
/ 23 октября 2019

Это довольно сложно, но работает следующее:

//# nom = "5.0.1"
use nom::{
    bytes::complete::{escaped_transform, tag},
    character::complete::none_of,
    combinator::{recognize, map_parser},
    multi::{many0, separated_list},
    sequence::delimited,
    IResult,
};

fn main() {
    let (_, res) = parse_quoted("'abc''def'").unwrap();
    assert_eq!(res, "abc'def");
    let (_, res) = parse_quoted("'xy@$%!z'").unwrap();
    assert_eq!(res, "xy@$%!z");
    let (_, res) = parse_quoted("'single quotes -> '' and so on...'").unwrap();
    assert_eq!(res, "single quotes -> ' and so on...");
}

fn parse_quoted(input: &str) -> IResult<&str, String> {
    let seq = recognize(separated_list(tag("''"), many0(none_of("'"))));
    let unquote = escaped_transform(none_of("'"), '\'', tag("'"));
    let res = delimited(tag("'"), map_parser(seq, unquote), tag("'"))(input)?;

    Ok(res)
}

Некоторые объяснения:

  1. парсер seq распознает любую последовательность, которая чередуется между двойными кавычками и чем-то еще;
  2. unquote преобразует любые двойные кавычки в одинарные;
  3. map_parser затем объединяет их вместе для получения желаемого результата.

Имейте в виду, чтоиз-за использования комбинатора escaped_transform результат анализа равен String вместо &str. Т.е. есть дополнительные отчисления.

...