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