toml_edit/parser/
document.rs1use std::cell::RefCell;
2
3use nom8::bytes::any;
4use nom8::bytes::one_of;
5use nom8::combinator::cut;
6use nom8::combinator::eof;
7use nom8::combinator::opt;
8use nom8::combinator::peek;
9use nom8::error::FromExternalError;
10use nom8::multi::many0_count;
11
12use crate::document::Document;
13use crate::key::Key;
14use crate::parser::inline_table::KEYVAL_SEP;
15use crate::parser::key::key;
16use crate::parser::prelude::*;
17use crate::parser::state::ParseState;
18use crate::parser::table::table;
19use crate::parser::trivia::{comment, line_ending, line_trailing, newline, ws};
20use crate::parser::value::value;
21use crate::table::TableKeyValue;
22use crate::Item;
23use crate::RawString;
24
25pub(crate) fn document(input: Input<'_>) -> IResult<Input<'_>, Document, ParserError<'_>> {
34 let state = RefCell::new(ParseState::default());
35 let state_ref = &state;
36
37 let (i, _o) = (
38 opt(b"\xEF\xBB\xBF"),
40 parse_ws(state_ref),
41 many0_count((
42 dispatch! {peek(any);
43 crate::parser::trivia::COMMENT_START_SYMBOL => cut(parse_comment(state_ref)),
44 crate::parser::table::STD_TABLE_OPEN => cut(table(state_ref)),
45 crate::parser::trivia::LF |
46 crate::parser::trivia::CR => parse_newline(state_ref),
47 _ => cut(keyval(state_ref)),
48 },
49 parse_ws(state_ref),
50 )),
51 eof,
52 )
53 .parse(input)?;
54 state
55 .into_inner()
56 .into_document()
57 .map(|document| (i, document))
58 .map_err(|err| {
59 nom8::Err::Error(ParserError::from_external_error(
60 i,
61 nom8::error::ErrorKind::MapRes,
62 err,
63 ))
64 })
65}
66
67pub(crate) fn parse_comment<'s, 'i>(
68 state: &'s RefCell<ParseState>,
69) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'_>> + 's {
70 move |i| {
71 (comment, line_ending)
72 .span()
73 .map(|span| {
74 state.borrow_mut().on_comment(span);
75 })
76 .parse(i)
77 }
78}
79
80pub(crate) fn parse_ws<'s, 'i>(
81 state: &'s RefCell<ParseState>,
82) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
83 move |i| {
84 ws.span()
85 .map(|span| state.borrow_mut().on_ws(span))
86 .parse(i)
87 }
88}
89
90pub(crate) fn parse_newline<'s, 'i>(
91 state: &'s RefCell<ParseState>,
92) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
93 move |i| {
94 newline
95 .span()
96 .map(|span| state.borrow_mut().on_ws(span))
97 .parse(i)
98 }
99}
100
101pub(crate) fn keyval<'s, 'i>(
102 state: &'s RefCell<ParseState>,
103) -> impl FnMut(Input<'i>) -> IResult<Input<'i>, (), ParserError<'i>> + 's {
104 move |i| {
105 parse_keyval
106 .map_res(|(p, kv)| state.borrow_mut().on_keyval(p, kv))
107 .parse(i)
108 }
109}
110
111pub(crate) fn parse_keyval(
113 input: Input<'_>,
114) -> IResult<Input<'_>, (Vec<Key>, TableKeyValue), ParserError<'_>> {
115 (
116 key,
117 cut((
118 one_of(KEYVAL_SEP)
119 .context(Context::Expected(ParserValue::CharLiteral('.')))
120 .context(Context::Expected(ParserValue::CharLiteral('='))),
121 (
122 ws.span(),
123 value(RecursionCheck::default()),
124 line_trailing
125 .context(Context::Expected(ParserValue::CharLiteral('\n')))
126 .context(Context::Expected(ParserValue::CharLiteral('#'))),
127 ),
128 )),
129 )
130 .map_res::<_, _, std::str::Utf8Error>(|(key, (_, v))| {
131 let mut path = key;
132 let key = path.pop().expect("grammar ensures at least 1");
133
134 let (pre, v, suf) = v;
135 let pre = RawString::with_span(pre);
136 let suf = RawString::with_span(suf);
137 let v = v.decorated(pre, suf);
138 Ok((
139 path,
140 TableKeyValue {
141 key,
142 value: Item::Value(v),
143 },
144 ))
145 })
146 .parse(input)
147}