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 ) |
32 | 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(input:i) |
53 | } |
54 | } |
55 | |
56 | 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(input:i) |
66 | } |
67 | } |
68 | |
69 | 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(input:i) |
76 | } |
77 | } |
78 | |
79 | 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(input:i) |
87 | } |
88 | } |
89 | |
90 | 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(input:i) |
97 | } |
98 | } |
99 | |
100 | // keyval = key keyval-sep val |
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(RecursionCheck::default()), |
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 | |