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 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 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 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 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 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 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 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 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 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 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}