prism_parser/parser/
parser_instance.rs1use crate::core::adaptive::{AdaptError, GrammarState};
2use crate::core::cache::Allocs;
3use crate::core::context::ParserContext;
4use crate::core::pos::Pos;
5use crate::core::recovery::parse_with_recovery;
6use crate::core::state::ParserState;
7use crate::error::aggregate_error::AggregatedParseError;
8use crate::error::error_printer::ErrorLabel;
9use crate::error::ParseError;
10use crate::grammar::action_result::ActionResult;
11use crate::grammar::GrammarFile;
12use crate::parser::parser_layout::full_input_layout;
13use crate::parser::parser_rule;
14use crate::parser::var_map::VarMap;
15use crate::META_GRAMMAR;
16use bumpalo::Bump;
17
18pub struct ParserInstance<'arn, 'grm: 'arn, E: ParseError<L = ErrorLabel<'grm>>> {
19 context: ParserContext,
20 state: ParserState<'arn, 'grm, E>,
21
22 grammar_state: GrammarState<'arn, 'grm>,
23 rules: VarMap<'arn, 'grm>,
24}
25
26impl<'arn, 'grm: 'arn, E: ParseError<L = ErrorLabel<'grm>>> ParserInstance<'arn, 'grm, E> {
27 pub fn new(
28 input: &'grm str,
29 bump: Allocs<'arn>,
30 from: &'arn GrammarFile<'arn, 'grm>,
31 ) -> Result<Self, AdaptError<'grm>> {
32 let context = ParserContext::new();
33 let state = ParserState::new(input, bump);
34
35 let (grammar_state, meta_vars) = GrammarState::new_with(&META_GRAMMAR, bump);
36 let visible_rules = VarMap::from_iter(
37 [
38 (
39 "grammar",
40 *meta_vars
41 .get("grammar")
42 .expect("Meta grammar contains 'grammar' rule"),
43 ),
44 (
45 "prule_action",
46 *meta_vars
47 .get("prule_action")
48 .expect("Meta grammar contains 'prule_action' rule"),
49 ),
50 ],
51 bump,
52 );
53
54 let (grammar_state, rules) =
55 grammar_state.adapt_with(from, visible_rules, None, state.alloc)?;
56
57 Ok(Self {
58 context,
59 state,
60 grammar_state,
61 rules,
62 })
63 }
64}
65
66impl<'arn, 'grm: 'arn, E: ParseError<L = ErrorLabel<'grm>> + 'grm> ParserInstance<'arn, 'grm, E> {
67 pub fn run(
68 &'arn mut self,
69 rule: &'grm str,
70 ) -> Result<&'arn ActionResult<'arn, 'grm>, AggregatedParseError<'grm, E>> {
71 let rule = self
72 .rules
73 .get(rule)
74 .expect("Rule exists")
75 .as_rule_id()
76 .expect("Rule is a rule");
77 let result = parse_with_recovery(
78 &full_input_layout(
79 &self.grammar_state,
80 self.rules,
81 &parser_rule::parser_rule(&self.grammar_state, rule, &[]),
82 ),
83 Pos::start(),
84 &mut self.state,
85 self.context,
86 );
87 result.map_err(|errors| AggregatedParseError {
88 input: self.state.input,
89 errors,
90 })
91 }
92}
93
94pub fn run_parser_rule<'arn, 'grm, E: ParseError<L = ErrorLabel<'grm>> + 'grm, T>(
95 rules: &'arn GrammarFile<'arn, 'grm>,
96 rule: &'grm str,
97 input: &'grm str,
98 ar_map: impl for<'c> FnOnce(&'c ActionResult<'c, 'grm>, Allocs<'c>) -> T,
99) -> Result<T, AggregatedParseError<'grm, E>> {
100 let bump = Bump::new();
101 let allocs: Allocs<'_> = Allocs::new(&bump);
102 let mut instance = ParserInstance::new(input, allocs, rules).unwrap();
103 instance.run(rule).map(|ar| ar_map(ar, allocs))
104}
105
106#[macro_export]
107macro_rules! run_parser_rule_here {
108 ($id: ident = $rules: expr, $rule: expr, $error: ty, $input: expr) => {
109 let bump = ::bumpalo::Bump::new();
110 let alloc = $crate::core::cache::Allocs::new(&bump);
111 let mut instance =
112 $crate::parser::parser_instance::ParserInstance::<$error>::new($input, alloc, $rules)
113 .unwrap();
114 let $id = instance.run($rule);
115 };
116}