prism_parser/parser/
parser_layout.rs

1use crate::core::adaptive::GrammarState;
2use crate::core::context::ParserContext;
3use crate::core::parser::Parser;
4use crate::core::pos::Pos;
5use crate::core::presult::PResult;
6use crate::core::presult::PResult::{PErr, POk};
7use crate::core::primitives::end;
8use crate::core::state::ParserState;
9use crate::error::error_printer::ErrorLabel;
10use crate::error::ParseError;
11use crate::parser::parser_rule::parser_rule;
12use crate::parser::var_map::VarMap;
13
14pub fn parser_with_layout<
15    'a,
16    'arn: 'a,
17    'grm: 'arn,
18    O,
19    E: ParseError<L = ErrorLabel<'grm>> + 'grm,
20>(
21    rules: &'arn GrammarState<'arn, 'grm>,
22    vars: VarMap<'arn, 'grm>,
23    sub: &'a impl Parser<'arn, 'grm, O, E>,
24) -> impl Parser<'arn, 'grm, O, E> + 'a {
25    move |pos: Pos,
26          state: &mut ParserState<'arn, 'grm, E>,
27          context: ParserContext|
28          -> PResult<O, E> {
29        if context.layout_disabled || vars.get("layout").is_none() {
30            return sub.parse(pos, state, context);
31        }
32        let layout = vars
33            .get("layout")
34            .expect("Layout exists")
35            .as_rule_id()
36            .expect("Layout is an expr");
37
38        //Start attemping to parse layout
39        let mut res = PResult::new_empty((), pos);
40        loop {
41            let sub_res = sub.parse(res.end_pos(), state, context);
42            if sub_res.is_ok() {
43                return sub_res;
44            }
45
46            let pos_before_layout = sub_res.end_pos();
47            // Add in optional error information from sub_res, then require another layout token
48            let new_res = res.merge_seq_opt(sub_res).merge_seq_parser(
49                &parser_rule(rules, layout, &[]),
50                state,
51                ParserContext {
52                    layout_disabled: true,
53                    ..context
54                },
55            );
56            match new_res {
57                // We have parsed more layout, we can try again
58                POk(_, _, new_end_pos, new_err) if pos_before_layout < new_res.end_pos() => {
59                    res = POk((), new_end_pos, new_end_pos, new_err);
60                }
61                // We have not parsed more layout ...
62                // ... because layout parser did not parse more characters
63                POk(_, _, _, err) => {
64                    let (e, pos) = err.unwrap();
65                    return PErr(e, pos);
66                }
67                // ... because layout parser failed
68                PErr(e, pos) => return PErr(e, pos),
69            }
70        }
71    }
72}
73
74pub fn full_input_layout<
75    'a,
76    'arn: 'a,
77    'grm: 'arn,
78    O,
79    E: ParseError<L = ErrorLabel<'grm>> + 'grm,
80>(
81    rules: &'arn GrammarState<'arn, 'grm>,
82    vars: VarMap<'arn, 'grm>,
83    sub: &'a impl Parser<'arn, 'grm, O, E>,
84) -> impl Parser<'arn, 'grm, O, E> + 'a {
85    move |pos: Pos,
86          state: &mut ParserState<'arn, 'grm, E>,
87          context: ParserContext|
88          -> PResult<O, E> {
89        let res = sub.parse(pos, state, context);
90        res.merge_seq_parser(&parser_with_layout(rules, vars, &end()), state, context)
91            .map(|(o, _)| o)
92    }
93}