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