prism_parser/parser/
parser_rule_body.rs

1use crate::core::cache::parser_cache_recurse;
2use crate::core::parser::Parser;
3use crate::core::presult::PResult;
4use crate::error::error_printer::ErrorLabel;
5use crate::error::ParseError;
6
7use crate::core::adaptive::{Constructor, GrammarState};
8
9use crate::core::context::ParserContext;
10use crate::core::pos::Pos;
11use crate::core::recovery::recovery_point;
12use crate::core::state::ParserState;
13use crate::grammar::action_result::ActionResult;
14use crate::grammar::{RuleAnnotation, RuleExpr};
15use crate::parser::parser_layout::parser_with_layout;
16use crate::parser::parser_rule_expr::parser_expr;
17use crate::parser::var_map::{BlockCtx, VarMap};
18
19pub fn parser_body_cache_recurse<
20    'a,
21    'arn: 'a,
22    'grm: 'arn,
23    E: ParseError<L = ErrorLabel<'grm>> + 'grm,
24>(
25    rules: &'arn GrammarState<'arn, 'grm>,
26    block_ctx: BlockCtx<'arn, 'grm>,
27) -> impl Parser<'arn, 'grm, &'arn ActionResult<'arn, 'grm>, E> + 'a {
28    move |pos: Pos, state: &mut ParserState<'arn, 'grm, E>, context: ParserContext| {
29        const RED_ZONE: usize = 1024 * 1024;
30        stacker::maybe_grow(RED_ZONE, RED_ZONE * 64, || {
31            parser_cache_recurse(
32                &parser_body_sub_blocks(rules, block_ctx),
33                block_ctx,
34                rules.unique_id(),
35            )
36            .parse(pos, state, context)
37        })
38    }
39}
40
41fn parser_body_sub_blocks<'a, 'arn: 'a, 'grm: 'arn, E: ParseError<L = ErrorLabel<'grm>> + 'grm>(
42    rules: &'arn GrammarState<'arn, 'grm>,
43    (block_state, rule_args): BlockCtx<'arn, 'grm>,
44) -> impl Parser<'arn, 'grm, &'arn ActionResult<'arn, 'grm>, E> + 'a {
45    move |pos: Pos,
46          state: &mut ParserState<'arn, 'grm, E>,
47          context: ParserContext|
48          -> PResult<&'arn ActionResult<'arn, 'grm>, E> {
49        match block_state {
50            [] => unreachable!(),
51            [b] => parser_body_sub_constructors(rules, (block_state, rule_args), b.constructors)
52                .parse(pos, state, context),
53            [b, brest @ ..] => {
54                // Parse current
55                let res =
56                    parser_body_sub_constructors(rules, (block_state, rule_args), b.constructors)
57                        .parse(pos, state, context);
58
59                // Parse next with recursion check
60                res.merge_choice_parser(
61                    &parser_body_cache_recurse(rules, (brest, rule_args)),
62                    pos,
63                    state,
64                    context,
65                )
66            }
67        }
68    }
69}
70
71fn parser_body_sub_constructors<
72    'a,
73    'arn: 'a,
74    'grm: 'arn,
75    E: ParseError<L = ErrorLabel<'grm>> + 'grm,
76>(
77    rules: &'arn GrammarState<'arn, 'grm>,
78    (block_state, rule_args): BlockCtx<'arn, 'grm>,
79    es: &'arn [Constructor<'arn, 'grm>],
80) -> impl Parser<'arn, 'grm, &'arn ActionResult<'arn, 'grm>, E> + 'a {
81    move |pos: Pos, state: &mut ParserState<'arn, 'grm, E>, context: ParserContext| match es {
82        [] => PResult::new_err(E::new(pos.span_to(pos)), pos),
83        [(crate::grammar::AnnotatedRuleExpr(annots, expr), rule_ctx), rest @ ..] => {
84            let rule_ctx = rule_ctx.iter_cloned();
85            let rule_args_iter = rule_args.iter_cloned();
86            let vars: VarMap<'arn, 'grm> =
87                VarMap::from_iter(rule_args_iter.chain(rule_ctx), state.alloc);
88
89            let res =
90                parser_body_sub_annotations(rules, (block_state, rule_args), annots, expr, vars)
91                    .parse(pos, state, context)
92                    .merge_choice_parser(
93                        &parser_body_sub_constructors(rules, (block_state, rule_args), rest),
94                        pos,
95                        state,
96                        context,
97                    );
98            res
99        }
100    }
101}
102
103fn parser_body_sub_annotations<
104    'a,
105    'arn: 'a,
106    'grm: 'arn,
107    E: ParseError<L = ErrorLabel<'grm>> + 'grm,
108>(
109    rules: &'arn GrammarState<'arn, 'grm>,
110    block_state: BlockCtx<'arn, 'grm>,
111    annots: &'arn [RuleAnnotation<'grm>],
112    expr: &'arn RuleExpr<'arn, 'grm>,
113    vars: VarMap<'arn, 'grm>,
114) -> impl Parser<'arn, 'grm, &'arn ActionResult<'arn, 'grm>, E> + 'a {
115    move |pos: Pos, state: &mut ParserState<'arn, 'grm, E>, context: ParserContext| match annots {
116        [RuleAnnotation::Error(err_label), rest @ ..] => {
117            let mut res = parser_body_sub_annotations(rules, block_state, rest, expr, vars)
118                .parse(pos, state, context);
119            res.add_label_explicit(ErrorLabel::Explicit(
120                pos.span_to(res.end_pos().next(state.input).0),
121                *err_label,
122            ));
123            res
124        }
125        [RuleAnnotation::DisableLayout, rest @ ..] => {
126            parser_with_layout(rules, vars, &move |pos: Pos,
127                                                   state: &mut ParserState<
128                'arn,
129                'grm,
130                E,
131            >,
132                                                   context: ParserContext|
133                  -> PResult<_, E> {
134                parser_body_sub_annotations(rules, block_state, rest, expr, vars).parse(
135                    pos,
136                    state,
137                    ParserContext {
138                        layout_disabled: true,
139                        ..context
140                    },
141                )
142            })
143            .parse(pos, state, context)
144        }
145        [RuleAnnotation::EnableLayout, rest @ ..] => {
146            parser_with_layout(rules, vars, &move |pos: Pos,
147                                                   state: &mut ParserState<
148                'arn,
149                'grm,
150                E,
151            >,
152                                                   context: ParserContext|
153                  -> PResult<_, E> {
154                parser_body_sub_annotations(rules, block_state, rest, expr, vars).parse(
155                    pos,
156                    state,
157                    ParserContext {
158                        layout_disabled: false,
159                        ..context
160                    },
161                )
162            })
163            .parse(pos, state, context)
164        }
165        [RuleAnnotation::DisableRecovery, rest @ ..] => recovery_point(
166            move |pos: Pos, state: &mut ParserState<'arn, 'grm, E>, context: ParserContext| {
167                parser_body_sub_annotations(rules, block_state, rest, expr, vars).parse(
168                    pos,
169                    state,
170                    ParserContext {
171                        recovery_disabled: true,
172                        ..context
173                    },
174                )
175            },
176        )
177        .parse(pos, state, context),
178        [RuleAnnotation::EnableRecovery, rest @ ..] => {
179            parser_body_sub_annotations(rules, block_state, rest, expr, vars).parse(
180                pos,
181                state,
182                ParserContext {
183                    recovery_disabled: false,
184                    ..context
185                },
186            )
187        }
188        &[] => parser_expr(rules, block_state, expr, vars)
189            .parse(pos, state, context)
190            .map(|pr| pr.rtrn),
191    }
192}