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 ) |
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 | |
60 | 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(input:i) |
70 | } |
71 | } |
72 | |
73 | 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(input:i) |
80 | } |
81 | } |
82 | |
83 | 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(input:i) |
91 | } |
92 | } |
93 | |
94 | 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(input:i) |
101 | } |
102 | } |
103 | |
104 | // keyval = key keyval-sep val |
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 | |