• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::cell::RefCell;
2 
3 use winnow::combinator::cut_err;
4 use winnow::combinator::eof;
5 use winnow::combinator::opt;
6 use winnow::combinator::peek;
7 use winnow::combinator::repeat;
8 use winnow::combinator::trace;
9 use winnow::token::any;
10 use winnow::token::one_of;
11 
12 use crate::key::Key;
13 use crate::parser::inline_table::KEYVAL_SEP;
14 use crate::parser::key::key;
15 use crate::parser::prelude::*;
16 use crate::parser::state::ParseState;
17 use crate::parser::table::table;
18 use crate::parser::trivia::{comment, line_ending, line_trailing, newline, ws};
19 use crate::parser::value::value;
20 use crate::table::TableKeyValue;
21 use crate::Item;
22 use crate::RawString;
23 
24 // ;; TOML
25 
26 // toml = expression *( newline expression )
27 
28 // expression = ( ( ws comment ) /
29 //                ( ws keyval ws [ comment ] ) /
30 //                ( ws table ws [ comment ] ) /
31 //                  ws )
document<'s, 'i>( state_ref: &'s RefCell<ParseState>, ) -> impl Parser<Input<'i>, (), ContextError> + 's32 pub(crate) fn document<'s, 'i>(
33     state_ref: &'s RefCell<ParseState>,
34 ) -> impl Parser<Input<'i>, (), ContextError> + 's {
35     move |i: &mut Input<'i>| {
36         (
37             // Remove BOM if present
38             opt(b"\xEF\xBB\xBF"),
39             parse_ws(state_ref),
40             repeat(0.., (
41                 dispatch! {peek(any);
42                     crate::parser::trivia::COMMENT_START_SYMBOL => cut_err(parse_comment(state_ref)),
43                     crate::parser::table::STD_TABLE_OPEN => cut_err(table(state_ref)),
44                     crate::parser::trivia::LF |
45                     crate::parser::trivia::CR => parse_newline(state_ref),
46                     _ => cut_err(keyval(state_ref)),
47                 },
48                 parse_ws(state_ref),
49             ))
50             .map(|()| ()),
51             eof,
52         ).void().parse_next(i)
53     }
54 }
55 
parse_comment<'s, 'i>( state: &'s RefCell<ParseState>, ) -> impl Parser<Input<'i>, (), ContextError> + 's56 pub(crate) fn parse_comment<'s, 'i>(
57     state: &'s RefCell<ParseState>,
58 ) -> impl Parser<Input<'i>, (), ContextError> + 's {
59     move |i: &mut Input<'i>| {
60         (comment, line_ending)
61             .span()
62             .map(|span| {
63                 state.borrow_mut().on_comment(span);
64             })
65             .parse_next(i)
66     }
67 }
68 
parse_ws<'s, 'i>( state: &'s RefCell<ParseState>, ) -> impl Parser<Input<'i>, (), ContextError> + 's69 pub(crate) fn parse_ws<'s, 'i>(
70     state: &'s RefCell<ParseState>,
71 ) -> impl Parser<Input<'i>, (), ContextError> + 's {
72     move |i: &mut Input<'i>| {
73         ws.span()
74             .map(|span| state.borrow_mut().on_ws(span))
75             .parse_next(i)
76     }
77 }
78 
parse_newline<'s, 'i>( state: &'s RefCell<ParseState>, ) -> impl Parser<Input<'i>, (), ContextError> + 's79 pub(crate) fn parse_newline<'s, 'i>(
80     state: &'s RefCell<ParseState>,
81 ) -> impl Parser<Input<'i>, (), ContextError> + 's {
82     move |i: &mut Input<'i>| {
83         newline
84             .span()
85             .map(|span| state.borrow_mut().on_ws(span))
86             .parse_next(i)
87     }
88 }
89 
keyval<'s, 'i>( state: &'s RefCell<ParseState>, ) -> impl Parser<Input<'i>, (), ContextError> + 's90 pub(crate) fn keyval<'s, 'i>(
91     state: &'s RefCell<ParseState>,
92 ) -> impl Parser<Input<'i>, (), ContextError> + 's {
93     move |i: &mut Input<'i>| {
94         parse_keyval
95             .try_map(|(p, kv)| state.borrow_mut().on_keyval(p, kv))
96             .parse_next(i)
97     }
98 }
99 
100 // keyval = key keyval-sep val
parse_keyval(input: &mut Input<'_>) -> PResult<(Vec<Key>, TableKeyValue)>101 pub(crate) fn parse_keyval(input: &mut Input<'_>) -> PResult<(Vec<Key>, TableKeyValue)> {
102     trace(
103         "keyval",
104         (
105             key,
106             cut_err((
107                 one_of(KEYVAL_SEP)
108                     .context(StrContext::Expected(StrContextValue::CharLiteral('.')))
109                     .context(StrContext::Expected(StrContextValue::CharLiteral('='))),
110                 (
111                     ws.span(),
112                     value,
113                     line_trailing
114                         .context(StrContext::Expected(StrContextValue::CharLiteral('\n')))
115                         .context(StrContext::Expected(StrContextValue::CharLiteral('#'))),
116                 ),
117             )),
118         )
119             .try_map::<_, _, std::str::Utf8Error>(|(key, (_, v))| {
120                 let mut path = key;
121                 let key = path.pop().expect("grammar ensures at least 1");
122 
123                 let (pre, v, suf) = v;
124                 let pre = RawString::with_span(pre);
125                 let suf = RawString::with_span(suf);
126                 let v = v.decorated(pre, suf);
127                 Ok((
128                     path,
129                     TableKeyValue {
130                         key,
131                         value: Item::Value(v),
132                     },
133                 ))
134             }),
135     )
136     .parse_next(input)
137 }
138