oni_comb_parser/text/
escaped.rs1use alloc::string::String;
2
3use crate::error::{ExpectError, Expected, ParseError};
4use crate::fail::{Fail, PResult};
5use crate::input::Input;
6use crate::parser::Parser;
7use crate::str_input::StrInput;
8
9pub struct Escaped<F> {
10 open: char,
11 close: char,
12 escape: char,
13 handler: F,
14}
15
16pub fn escaped<F>(open: char, close: char, escape: char, handler: F) -> Escaped<F>
17where
18 F: FnMut(char) -> Option<char>, {
19 Escaped {
20 open,
21 close,
22 escape,
23 handler,
24 }
25}
26
27impl<'a, F> Parser<StrInput<'a>> for Escaped<F>
28where
29 F: FnMut(char) -> Option<char>,
30{
31 type Error = ParseError;
32 type Output = String;
33
34 #[inline]
35 fn parse_next(&mut self, input: &mut StrInput<'a>) -> PResult<String, ParseError> {
36 let pos = input.offset();
37 let remaining = input.as_str();
38 let mut chars = remaining.chars();
39
40 match chars.next() {
42 Some(c) if c == self.open => {}
43 _ => {
44 return Err(Fail::Backtrack(ParseError::from_expected(
45 pos,
46 Expected::Char(self.open),
47 )));
48 }
49 }
50
51 let mut result = String::new();
52 let mut consumed = self.open.len_utf8();
53
54 loop {
55 match chars.next() {
56 Some(c) if c == self.close => {
57 consumed += c.len_utf8();
58 input.advance(consumed);
59 return Ok(result);
60 }
61 Some(c) if c == self.escape => {
62 consumed += c.len_utf8();
63 match chars.next() {
64 Some(next) => {
65 consumed += next.len_utf8();
66 match (self.handler)(next) {
67 Some(replacement) => result.push(replacement),
68 None => {
69 return Err(Fail::Cut(ParseError::from_expected(
70 pos + consumed - next.len_utf8(),
71 Expected::Description("valid escape sequence"),
72 )));
73 }
74 }
75 }
76 None => {
77 return Err(Fail::Cut(ParseError::from_expected(
78 pos + consumed,
79 Expected::Description("escape character"),
80 )));
81 }
82 }
83 }
84 Some(c) => {
85 consumed += c.len_utf8();
86 result.push(c);
87 }
88 None => {
89 return Err(Fail::Cut(ParseError::from_expected(
90 pos + consumed,
91 Expected::Char(self.close),
92 )));
93 }
94 }
95 }
96 }
97}