prism_parser/parser/
parser_rule_expr.rs

1use crate::core::adaptive::GrammarState;
2use crate::core::context::{ParserContext, PR};
3use crate::core::parser::{map_parser, Parser};
4use crate::core::pos::Pos;
5use crate::core::presult::PResult;
6use crate::core::primitives::{negative_lookahead, positive_lookahead, repeat_delim, single};
7use crate::core::recovery::recovery_point;
8use crate::core::state::ParserState;
9use crate::error::error_printer::ErrorLabel;
10use crate::error::ParseError;
11use crate::grammar::action_result::ActionResult;
12use crate::grammar::apply_action::apply_action;
13use crate::grammar::escaped_string::EscapedString;
14use crate::grammar::from_action_result::parse_grammarfile;
15use crate::grammar::rule_action::RuleAction;
16use crate::grammar::{GrammarFile, RuleExpr};
17use crate::parser::parser_layout::parser_with_layout;
18use crate::parser::parser_rule::parser_rule;
19use crate::parser::parser_rule_body::parser_body_cache_recurse;
20use crate::parser::var_map::{BlockCtx, CapturedExpr, VarMap, VarMapValue};
21
22pub fn parser_expr<'a, 'arn: 'a, 'grm: 'arn, E: ParseError<L = ErrorLabel<'grm>> + 'grm>(
23    rules: &'arn GrammarState<'arn, 'grm>,
24    block_ctx: BlockCtx<'arn, 'grm>,
25    expr: &'arn RuleExpr<'arn, 'grm>,
26    vars: VarMap<'arn, 'grm>,
27) -> impl Parser<'arn, 'grm, PR<'arn, 'grm>, E> + 'a {
28    move |pos: Pos,
29          state: &mut ParserState<'arn, 'grm, E>,
30          context: ParserContext|
31          -> PResult<PR<'arn, 'grm>, E> {
32        match expr {
33            RuleExpr::RunVar(mut rule_str, args) => {
34                let mut result_args = vec![];
35                let mut args = args;
36                let mut block_ctx = block_ctx;
37                let mut vars = vars;
38
39                loop {
40                    // Figure out which rule the variable `rule` refers to
41                    let Some(rule) = vars.get(rule_str) else {
42                        panic!(
43                            "Tried to run variable `{rule_str}` as a rule, but it was not defined."
44                        );
45                    };
46
47                    result_args.splice(
48                        0..0,
49                        args.iter().map(|arg| {
50                            VarMapValue::Expr(CapturedExpr {
51                                expr: arg,
52                                block_ctx,
53                                vars,
54                            })
55                        }),
56                    );
57
58                    return match rule {
59                        VarMapValue::Expr(captured) => {
60                            // If the `Expr` we call is a rule, we might be using it as a higher-order rule
61                            // We process this rule in a loop, using the context of the captured expression
62                            if let RuleExpr::RunVar(sub_rule, sub_args) = captured.expr {
63                                rule_str = sub_rule;
64                                args = sub_args;
65                                block_ctx = captured.block_ctx;
66                                vars = captured.vars;
67                                continue;
68                            } else {
69                                assert_eq!(
70                                    result_args.len(),
71                                    0,
72                                    "Tried to apply an argument to a non-rule expr"
73                                );
74                                parser_expr(rules, captured.block_ctx, captured.expr, captured.vars)
75                                    .parse(pos, state, context)
76                            }
77                        }
78                        VarMapValue::Value(value) => {
79                            if let ActionResult::RuleId(rule) = value {
80                                parser_rule(rules, *rule, &result_args)
81                                    .parse(pos, state, context)
82                                    .map(PR::with_rtrn)
83                            } else {
84                                //TODO remove this code and replace with $value expressions
85                                PResult::new_empty(PR::with_rtrn(value), pos)
86                            }
87                        }
88                    };
89                }
90            }
91            RuleExpr::CharClass(cc) => {
92                let p = single(|c| cc.contains(*c));
93                let alloc = state.alloc;
94                let map = |(span, _)| &*alloc.alloc(ActionResult::Value(span));
95                let p = map_parser(p, &map);
96                let p = recovery_point(p);
97                let p = parser_with_layout(rules, vars, &p);
98                p.parse(pos, state, context).map(PR::with_rtrn)
99            }
100            RuleExpr::Literal(literal) => {
101                //First construct the literal parser
102                let p = move |pos: Pos,
103                              state: &mut ParserState<'arn, 'grm, E>,
104                              context: ParserContext| {
105                    let mut res = PResult::new_empty((), pos);
106                    for char in literal.chars() {
107                        res = res
108                            .merge_seq_parser(&single(|c| *c == char), state, context)
109                            .map(|_| ());
110                    }
111                    let mut res =
112                        res.map_with_span(|_, span| &*state.alloc.alloc(ActionResult::Value(span)));
113                    res.add_label_implicit(ErrorLabel::Literal(
114                        pos.span_to(res.end_pos().next(state.input).0),
115                        *literal,
116                    ));
117                    res
118                };
119                let p = recovery_point(p);
120                let p = parser_with_layout(rules, vars, &p);
121                p.parse(pos, state, context).map(PR::with_rtrn)
122            }
123            RuleExpr::Repeat {
124                expr,
125                min,
126                max,
127                delim,
128            } => {
129                //TODO this allocates :c
130                let res = repeat_delim(
131                    parser_expr(rules, block_ctx, expr, vars),
132                    parser_expr(rules, block_ctx, delim, vars),
133                    *min as usize,
134                    max.map(|max| max as usize),
135                )
136                .parse(pos, state, context);
137
138                res.map_with_span(|rtrn, span| {
139                    PR::with_rtrn(rtrn.iter().rfold(
140                        state.alloc.alloc(ActionResult::Construct(span, "Nil", &[])),
141                        |rest, next| {
142                            state.alloc.alloc(ActionResult::Construct(
143                                span,
144                                "Cons",
145                                state.alloc.alloc_extend([*next.rtrn, *rest]),
146                            ))
147                        },
148                    ))
149                })
150            }
151            RuleExpr::Sequence(subs) => {
152                let mut res = PResult::new_empty(VarMap::default(), pos);
153                //TODO can we do better than tracking res_vars by cloning?
154                let mut res_vars: VarMap = vars;
155                for sub in *subs {
156                    res = res
157                        .merge_seq_parser(
158                            &parser_expr(rules, block_ctx, sub, res_vars),
159                            state,
160                            context,
161                        )
162                        .map(|(l, r)| l.extend(r.free.iter_cloned(), state.alloc));
163                    match &res.ok_ref() {
164                        None => break,
165                        Some(o) => {
166                            res_vars = res_vars.extend(o.iter_cloned(), state.alloc);
167                        }
168                    }
169                }
170                res.map(|map| PR {
171                    free: map,
172                    rtrn: ActionResult::VOID,
173                })
174            }
175            RuleExpr::Choice(subs) => {
176                let mut res: PResult<PR, E> = PResult::PErr(E::new(pos.span_to(pos)), pos);
177                for sub in *subs {
178                    res = res.merge_choice_parser(
179                        &parser_expr(rules, block_ctx, sub, vars),
180                        pos,
181                        state,
182                        context,
183                    );
184                    if res.is_ok() {
185                        break;
186                    }
187                }
188                res
189            }
190            RuleExpr::NameBind(name, sub) => {
191                let res = parser_expr(rules, block_ctx, sub, vars).parse(pos, state, context);
192                res.map(|res| PR {
193                    free: res
194                        .free
195                        .insert(name, VarMapValue::Value(res.rtrn), state.alloc),
196                    rtrn: ActionResult::VOID,
197                })
198            }
199            RuleExpr::Action(sub, action) => {
200                let res = parser_expr(rules, block_ctx, sub, vars).parse(pos, state, context);
201                res.map_with_span(|res, span| {
202                    let rtrn = apply_action(
203                        action,
204                        span,
205                        res.free.extend(vars.iter_cloned(), state.alloc),
206                        &state.alloc,
207                    );
208
209                    PR {
210                        free: res.free,
211                        rtrn: state.alloc.alloc(rtrn),
212                    }
213                })
214            }
215            RuleExpr::SliceInput(sub) => {
216                let res = parser_expr(rules, block_ctx, sub, vars).parse(pos, state, context);
217                res.map_with_span(|_, span| {
218                    PR::with_rtrn(state.alloc.alloc(ActionResult::Value(span)))
219                })
220            }
221            RuleExpr::This => parser_body_cache_recurse(rules, block_ctx)
222                .parse(pos, state, context)
223                .map(PR::with_rtrn),
224            RuleExpr::Next => parser_body_cache_recurse(rules, (&block_ctx.0[1..], block_ctx.1))
225                .parse(pos, state, context)
226                .map(PR::with_rtrn),
227            RuleExpr::PosLookahead(sub) => {
228                positive_lookahead(&parser_expr(rules, block_ctx, sub, vars))
229                    .parse(pos, state, context)
230            }
231            RuleExpr::NegLookahead(sub) => {
232                negative_lookahead(&parser_expr(rules, block_ctx, sub, vars))
233                    .parse(pos, state, context)
234                    .map(|_| PR::with_rtrn(ActionResult::VOID))
235            }
236            RuleExpr::AtAdapt(ga, adapt_rule) => {
237                // First, get the grammar actionresult
238                let gr = if let Some(ar) = vars.get(ga) {
239                    if let VarMapValue::Value(v) = ar {
240                        v
241                    } else {
242                        panic!("")
243                    }
244                } else {
245                    panic!("Name '{ga}' not in context")
246                };
247
248                // Parse it into a grammar
249                //TODO performance: We should have a cache for grammar files
250                //TODO and grammar state + new grammar -> grammar state
251                let g = match parse_grammarfile(gr, state.input, state.alloc, |ar, _| {
252                    Some(RuleAction::ActionResult(ar))
253                }) {
254                    Some(g) => g,
255                    None => {
256                        let mut e = E::new(pos.span_to(pos));
257                        e.add_label_implicit(ErrorLabel::Explicit(
258                            pos.span_to(pos),
259                            EscapedString::from_escaped(
260                                "language grammar to be correct, but adaptation AST was malformed.",
261                            ),
262                        ));
263                        return PResult::new_err(e, pos);
264                    }
265                };
266                let g: &'arn GrammarFile<'arn, 'grm> = state.alloc.alloc(g);
267
268                // Create new grammarstate
269                let (rules, _) = match rules.adapt_with(g, vars, Some(pos), state.alloc) {
270                    Ok(rules) => rules,
271                    Err(_) => {
272                        let mut e = E::new(pos.span_to(pos));
273                        e.add_label_implicit(ErrorLabel::Explicit(
274                            pos.span_to(pos),
275                            EscapedString::from_escaped(
276                                "language grammar to be correct, but adaptation created cycle in block order.",
277                            ),
278                        ));
279                        return PResult::new_err(e, pos);
280                    }
281                };
282                let rules: &'arn GrammarState = state.alloc.alloc(rules);
283
284                let rule = vars
285                    .get(adapt_rule)
286                    .or_else(|| vars.get(adapt_rule))
287                    .unwrap()
288                    .as_rule_id()
289                    .expect("Adaptation rule exists");
290
291                // Parse body
292                let mut res = parser_rule(rules, rule, &[])
293                    .parse(pos, state, context)
294                    .map(PR::with_rtrn);
295                res.add_label_implicit(ErrorLabel::Debug(pos.span_to(pos), "adaptation"));
296                res
297            }
298            RuleExpr::Guid => {
299                let guid = state.guid_counter;
300                state.guid_counter += 1;
301                PResult::new_empty(
302                    PR::with_rtrn(state.alloc.alloc(ActionResult::Guid(guid))),
303                    pos,
304                )
305            }
306        }
307    }
308}