prism_parser/parser/
parser_layout.rs1use 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 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 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 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 POk(_, _, _, err) => {
64 let (e, pos) = err.unwrap();
65 return PErr(e, pos);
66 }
67 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}