keyvalues_parser/text/parse/
escaped.rs1use super::*;
2
3pub type PestError = pest::error::Error<Rule>;
4type BoxedState<'a> = Box<pest::ParserState<'a, Rule>>;
5type ParseResult<'a> = pest::ParseResult<BoxedState<'a>>;
6
7common_parsing!(pest_parse, Rule, true);
8
9#[deprecated(since = "0.2.3", note = "Moved to `keyvalues_parser::parse()`")]
11pub fn parse(s: &str) -> Result<PartialVdf<'_>> {
12 parse_(s)
13}
14
15#[allow(non_camel_case_types, clippy::upper_case_acronyms)]
16#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
17pub enum Rule {
18 EOI,
20 WHITESPACE,
21 COMMENT,
22 vdf,
23 base_macro,
24 quoted_raw_string,
25 quoted_raw_inner,
26 pairs,
27 pair,
28 key,
29 value,
30 obj,
31 quoted_string,
32 quoted_inner,
33 char,
34 unquoted_string,
35 unquoted_char,
36}
37
38mod rules {
39 #![allow(non_snake_case)]
40
41 use super::{any, skip, soi, whitespace, BoxedState, ParseResult, Rule};
42
43 use pest::Atomicity;
44
45 #[inline]
46 pub fn vdf(s: BoxedState<'_>) -> ParseResult<'_> {
47 s.sequence(|s| {
48 soi(s)
49 .and_then(skip)
50 .and_then(|s| {
51 s.sequence(|s| {
52 s.optional(|s| {
53 base_macro(s).and_then(|s| {
54 s.repeat(|s| s.sequence(|s| skip(s).and_then(base_macro)))
55 })
56 })
57 })
58 })
59 .and_then(skip)
60 .and_then(pair)
61 .and_then(skip)
62 .and_then(|s| s.optional(|s| s.match_string("\0")))
63 .and_then(skip)
64 .and_then(EOI)
65 })
66 }
67 pub fn base_macro(s: BoxedState<'_>) -> ParseResult<'_> {
68 s.rule(Rule::base_macro, |s| {
69 s.sequence(|s| {
70 s.match_string("#base")
71 .and_then(skip)
72 .and_then(|s| quoted_raw_string(s).or_else(unquoted_string))
73 })
74 })
75 }
76 #[inline]
77 pub fn quoted_raw_string(s: BoxedState<'_>) -> ParseResult<'_> {
78 s.atomic(Atomicity::CompoundAtomic, |s| {
79 s.rule(Rule::quoted_raw_string, |s| {
80 s.sequence(|s| {
81 s.match_string("\"")
82 .and_then(quoted_raw_inner)
83 .and_then(|s| s.match_string("\""))
84 })
85 })
86 })
87 }
88 #[inline]
89 pub fn quoted_raw_inner(s: BoxedState<'_>) -> ParseResult<'_> {
90 s.rule(Rule::quoted_raw_inner, |s| {
91 s.atomic(Atomicity::Atomic, |s| s.skip_until(&["\""]))
92 })
93 }
94 #[inline]
95 pub fn pairs(s: BoxedState<'_>) -> ParseResult<'_> {
96 s.sequence(|s| {
97 s.optional(|s| {
98 pair(s).and_then(|s| s.repeat(|s| s.sequence(|s| skip(s).and_then(pair))))
99 })
100 })
101 }
102 #[inline]
103 pub fn pair(s: BoxedState<'_>) -> ParseResult<'_> {
104 s.rule(Rule::pair, |s| {
105 s.sequence(|s| key(s).and_then(skip).and_then(value))
106 })
107 }
108 #[inline]
109 pub fn key(s: BoxedState<'_>) -> ParseResult<'_> {
110 quoted_string(s).or_else(unquoted_string)
111 }
112 #[inline]
113 pub fn value(s: BoxedState<'_>) -> ParseResult<'_> {
114 quoted_string(s).or_else(obj).or_else(unquoted_string)
115 }
116 #[inline]
117 pub fn obj(s: BoxedState<'_>) -> ParseResult<'_> {
118 s.rule(Rule::obj, |s| {
119 s.sequence(|s| {
120 s.match_string("{")
121 .and_then(skip)
122 .and_then(pairs)
123 .and_then(skip)
124 .and_then(|s| s.match_string("}"))
125 })
126 })
127 }
128 #[inline]
129 pub fn quoted_string(s: BoxedState<'_>) -> ParseResult<'_> {
130 s.atomic(Atomicity::CompoundAtomic, |s| {
131 s.rule(Rule::quoted_string, |s| {
132 s.sequence(|s| {
133 s.match_string("\"")
134 .and_then(quoted_inner)
135 .and_then(|s| s.match_string("\""))
136 })
137 })
138 })
139 }
140 #[inline]
141 pub fn quoted_inner(s: BoxedState<'_>) -> ParseResult<'_> {
142 s.rule(Rule::quoted_inner, |s| {
143 s.atomic(Atomicity::Atomic, |s| s.repeat(char))
144 })
145 }
146 #[inline]
147 pub fn char(s: BoxedState<'_>) -> ParseResult<'_> {
148 s.rule(Rule::char, |s| {
149 s.sequence(|s| {
150 s.lookahead(false, |s| {
151 s.match_string("\"").or_else(|s| s.match_string("\\"))
152 })
153 .and_then(skip)
154 .and_then(any)
155 })
156 .or_else(|s| {
157 s.sequence(|s| {
158 s.match_string("\\").and_then(skip).and_then(|s| {
159 s.match_string("\"")
160 .or_else(|s| s.match_string("\\"))
161 .or_else(|s| s.match_string("n"))
162 .or_else(|s| s.match_string("r"))
163 .or_else(|s| s.match_string("t"))
164 })
165 })
166 })
167 })
168 }
169 #[inline]
170 pub fn unquoted_string(s: BoxedState<'_>) -> ParseResult<'_> {
171 s.rule(Rule::unquoted_string, |s| {
172 s.atomic(Atomicity::Atomic, |s| {
173 s.sequence(|s| unquoted_char(s).and_then(|s| s.repeat(unquoted_char)))
174 })
175 })
176 }
177 #[inline]
178 pub fn unquoted_char(s: BoxedState<'_>) -> ParseResult<'_> {
179 s.rule(Rule::unquoted_char, |s| {
180 s.sequence(|s| {
181 s.lookahead(false, |s| {
182 s.match_string("\"")
183 .or_else(|s| s.match_string("{"))
184 .or_else(|s| s.match_string("}"))
185 .or_else(whitespace)
186 })
187 .and_then(skip)
188 .and_then(any)
189 })
190 })
191 }
192 pub fn EOI(s: BoxedState<'_>) -> ParseResult<'_> {
193 s.rule(Rule::EOI, |s| s.end_of_input())
194 }
195}
196
197pub fn pest_parse(input: &str) -> std::result::Result<pest::iterators::Pairs<'_, Rule>, PestError> {
198 pest::state(input, rules::vdf)
199}