sdc_parser/
util.rs

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}