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