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 let res =
56 parser_body_sub_constructors(rules, (block_state, rule_args), b.constructors)
57 .parse(pos, state, context);
58
59 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}