1use combine::char::{char, digit, string};
2use combine::error::{ParseError, ParseResult};
3use combine::parser::combinator::recognize;
4use combine::{
5 choice, eof, from_str, look_ahead, many, many1, none_of, not_followed_by, one_of, optional,
6 parser, skip_many, skip_many1, token, Parser, Stream,
7};
8
9pub(crate) fn symbol<I>(name: &'static str) -> impl Parser<Input = I, Output = &'static str>
10where
11 I: Stream<Item = char>,
12 I::Error: ParseError<I::Item, I::Range, I::Position>,
13{
14 lex(symbol_(name))
15}
16
17fn symbol_<I>(name: &'static str) -> impl Parser<Input = I, Output = &'static str>
18where
19 I: Stream<Item = char>,
20 I::Error: ParseError<I::Item, I::Range, I::Position>,
21{
22 string(name)
23 .and(look_ahead(
24 one_of(" \t\n\\[]{}".chars()).or(eof().map(|_| ' ')),
25 ))
26 .map(|(x, _)| x)
27}
28
29pub(crate) fn float<I>() -> impl Parser<Input = I, Output = f64>
30where
31 I: Stream<Item = char>,
32 I::Error: ParseError<I::Item, I::Range, I::Position>,
33{
34 lex(float_())
35}
36
37fn float_<I>() -> impl Parser<Input = I, Output = f64>
38where
39 I: Stream<Item = char>,
40 I::Error: ParseError<I::Item, I::Range, I::Position>,
41{
42 from_str(recognize::<String, _>((
43 optional(token('-')),
44 (token('.').and(skip_many1(digit())).map(|_| '0')).or((
45 token('0').skip(not_followed_by(digit())).or((
46 one_of("123456789".chars()),
47 skip_many(digit()),
48 )
49 .map(|_| '0')),
50 optional((token('.'), skip_many(digit()))),
51 )
52 .map(|_| '0')),
53 optional((
54 (one_of("eE".chars()), optional(one_of("+-".chars()))),
55 skip_many1(digit()),
56 )),
57 )))
58 .expected("float")
59}
60
61pub(crate) fn item<I>() -> impl Parser<Input = I, Output = String>
62where
63 I: Stream<Item = char>,
64 I::Error: ParseError<I::Item, I::Range, I::Position>,
65{
66 lex(item_())
67}
68
69fn item_<I>() -> impl Parser<Input = I, Output = String>
70where
71 I: Stream<Item = char>,
72 I::Error: ParseError<I::Item, I::Range, I::Position>,
73{
74 item_literal()
75 .or(item_literal_braces())
76 .or(item_head()
77 .and(many(parser(item_body)))
78 .map(|(x, y): (_, Vec<String>)| {
79 let mut ret = String::new();
80 ret.push(x);
81 for s in y {
82 ret.push_str(&s);
83 }
84 ret
85 }))
86}
87
88fn item_literal<I>() -> impl Parser<Input = I, Output = String>
89where
90 I: Stream<Item = char>,
91 I::Error: ParseError<I::Item, I::Range, I::Position>,
92{
93 between('\"', '\"', many(none_of("\"".chars())))
94}
95
96fn item_literal_braces<I>() -> impl Parser<Input = I, Output = String>
97where
98 I: Stream<Item = char>,
99 I::Error: ParseError<I::Item, I::Range, I::Position>,
100{
101 between('{', '}', many(none_of("}".chars())))
102}
103
104fn item_head<I>() -> impl Parser<Input = I, Output = char>
105where
106 I: Stream<Item = char>,
107 I::Error: ParseError<I::Item, I::Range, I::Position>,
108{
109 none_of(" -{}[]\r\n\t".chars())
110}
111
112fn item_body<I>(input: &mut I) -> ParseResult<String, I>
113where
114 I: Stream<Item = char>,
115 I::Error: ParseError<I::Item, I::Range, I::Position>,
116{
117 many1(none_of(" -{}[]\r\n\t".chars()))
118 .or(combine::between(char('['), char(']'), parser(item_body)).map(|x| format!("[{}]", x)))
119 .parse_stream(input)
120}
121
122pub(crate) fn braces<I, O>(
123 parser: impl Parser<Input = I, Output = O>,
124) -> impl Parser<Input = I, Output = O>
125where
126 I: Stream<Item = char>,
127 I::Error: ParseError<I::Item, I::Range, I::Position>,
128{
129 between('{', '}', parser)
130}
131
132pub(crate) fn brackets<I, O>(
133 parser: impl Parser<Input = I, Output = O>,
134) -> impl Parser<Input = I, Output = O>
135where
136 I: Stream<Item = char>,
137 I::Error: ParseError<I::Item, I::Range, I::Position>,
138{
139 between('[', ']', parser)
140}
141
142fn between<I, O>(
143 start: char,
144 end: char,
145 parser: impl Parser<Input = I, Output = O>,
146) -> impl Parser<Input = I, Output = O>
147where
148 I: Stream<Item = char>,
149 I::Error: ParseError<I::Item, I::Range, I::Position>,
150{
151 combine::between(lex(char(start)), lex(char(end)), parser)
152}
153
154pub(crate) fn lex<I, O>(
155 parser: impl Parser<Input = I, Output = O>,
156) -> impl Parser<Input = I, Output = O>
157where
158 I: Stream<Item = char>,
159 I::Error: ParseError<I::Item, I::Range, I::Position>,
160{
161 parser
162 .and(skip_many(one_of(" \t".chars()).or(
163 char('\\').with(char('\n').or(string("\r\n").map(|_| ' '))),
164 )))
165 .map(|(x, _)| x)
166}
167
168pub(crate) fn braces_strings<I>(input: &mut I) -> ParseResult<Vec<String>, I>
169where
170 I: Stream<Item = char>,
171 I::Error: ParseError<I::Item, I::Range, I::Position>,
172{
173 choice((braces(parser(braces_strings)), many1(item()))).parse_stream(input)
174}