1use crate::{
2 ast::{Ast, AstAlloc, typ::Type},
3 error::{ParseError, ParseErrors},
4 files::FileId,
5 identifier::LocIdent,
6 position::RawSpan,
7};
8
9use lalrpop_util::lalrpop_mod;
10
11lalrpop_mod!(
12 #[allow(clippy::all)]
13 #[allow(unused_parens)]
14 #[allow(unused_imports)]
15 pub grammar, "/grammar.rs");
16
17use grammar::__ToTriple;
18
19pub mod ast;
20pub mod combine;
21pub mod environment;
22pub mod error;
23pub mod files;
24pub mod identifier;
25pub mod lexer;
26pub mod metrics;
27pub mod position;
28pub mod traverse;
29pub mod typ;
30pub(crate) mod uniterm;
31pub mod utils;
32
33#[cfg(test)]
34mod tests;
35
36pub enum ExtendedTerm<T> {
47 Term(T),
48 ToplevelLet(LocIdent, T),
49}
50
51trait LalrpopParser<'ast, T> {
60 fn parse<'input, 'err, 'wcard, __TOKEN, __TOKENS>(
61 &self,
62 alloc: &'ast AstAlloc,
63 src_id: FileId,
64 errors: &'err mut Vec<
65 lalrpop_util::ErrorRecovery<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
66 >,
67 next_wildcard_id: &'wcard mut usize,
68 __tokens0: __TOKENS,
69 ) -> Result<
70 T,
71 lalrpop_util::ParseError<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
72 >
73 where
74 __TOKEN: __ToTriple<'input, 'ast, 'err, 'wcard>,
75 __TOKENS: IntoIterator<Item = __TOKEN>;
76}
77
78macro_rules! generate_lalrpop_parser_impl {
81 ($parser:ty, $output:ty) => {
82 impl<'ast> LalrpopParser<'ast, $output> for $parser {
83 fn parse<'input, 'err, 'wcard, __TOKEN, __TOKENS>(
84 &self,
85 alloc: &'ast AstAlloc,
86 src_id: FileId,
87 errors: &'err mut Vec<
88 lalrpop_util::ErrorRecovery<
89 usize,
90 lexer::Token<'input>,
91 self::error::ParseOrLexError,
92 >,
93 >,
94 next_wildcard_id: &'wcard mut usize,
95 __tokens0: __TOKENS,
96 ) -> Result<
97 $output,
98 lalrpop_util::ParseError<usize, lexer::Token<'input>, self::error::ParseOrLexError>,
99 >
100 where
101 __TOKEN: __ToTriple<'input, 'ast, 'err, 'wcard>,
102 __TOKENS: IntoIterator<Item = __TOKEN>,
103 {
104 Self::parse(self, alloc, src_id, errors, next_wildcard_id, __tokens0)
105 }
106 }
107 };
108}
109
110generate_lalrpop_parser_impl!(grammar::ExtendedTermParser, ExtendedTerm<Ast<'ast>>);
111generate_lalrpop_parser_impl!(grammar::TermParser, Ast<'ast>);
112generate_lalrpop_parser_impl!(grammar::FixedTypeParser, Type<'ast>);
113generate_lalrpop_parser_impl!(grammar::StaticFieldPathParser, Vec<LocIdent>);
114generate_lalrpop_parser_impl!(
115 grammar::CliFieldAssignmentParser,
116 (Vec<LocIdent>, Ast<'ast>, RawSpan)
117);
118
119pub trait ErrorTolerantParser<'ast, T> {
123 fn parse_tolerant<'input>(
126 &self,
127 alloc: &'ast AstAlloc,
128 file_id: FileId,
129 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
130 ) -> Result<(T, ParseErrors), ParseError>;
131
132 fn parse_strict<'input>(
135 &self,
136 alloc: &'ast AstAlloc,
137 file_id: FileId,
138 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
139 ) -> Result<T, ParseErrors>;
140}
141
142impl<'ast, T, P> ErrorTolerantParser<'ast, T> for P
143where
144 P: LalrpopParser<'ast, T>,
145{
146 fn parse_tolerant<'input>(
147 &self,
148 alloc: &'ast AstAlloc,
149 file_id: FileId,
150 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
151 ) -> Result<(T, ParseErrors), ParseError> {
152 let mut parse_errors = Vec::new();
153 let mut next_wildcard_id = 0;
154 let result = self
155 .parse(
156 alloc,
157 file_id,
158 &mut parse_errors,
159 &mut next_wildcard_id,
160 lexer.map(|x| x.map_err(error::ParseOrLexError::from)),
161 )
162 .map_err(|err| ParseError::from_lalrpop(err, file_id));
163
164 let parse_errors = ParseErrors::from_recoverable(parse_errors, file_id);
165 match result {
166 Ok(t) => Ok((t, parse_errors)),
167 Err(e) => Err(e),
168 }
169 }
170
171 fn parse_strict<'input>(
172 &self,
173 alloc: &'ast AstAlloc,
174 file_id: FileId,
175 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
176 ) -> Result<T, ParseErrors> {
177 match self.parse_tolerant(alloc, file_id, lexer) {
178 Ok((t, e)) if e.no_errors() => Ok(t),
179 Ok((_, e)) => Err(e),
180 Err(e) => Err(e.into()),
181 }
182 }
183}
184
185pub trait FullyErrorTolerantParser<'ast, T> {
198 fn parse_fully_tolerant<'input>(
204 &self,
205 alloc: &'ast AstAlloc,
206 file_id: FileId,
207 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
208 full_span: RawSpan,
209 ) -> (T, ParseErrors);
210}
211
212impl<'ast, P> FullyErrorTolerantParser<'ast, Ast<'ast>> for P
213where
214 P: ErrorTolerantParser<'ast, Ast<'ast>>,
215{
216 fn parse_fully_tolerant<'input>(
217 &self,
218 alloc: &'ast AstAlloc,
219 file_id: FileId,
220 lexer: impl Iterator<Item = Result<lexer::SpannedToken<'input>, error::LexicalError>>,
221 full_span: RawSpan,
222 ) -> (Ast<'ast>, ParseErrors) {
223 match self.parse_tolerant(alloc, file_id, lexer) {
224 Ok((ast, e)) => (ast, e),
225 Err(e) => {
226 let ast = alloc.parse_error(e.clone()).spanned(full_span.into());
227 (ast, e.into())
228 }
229 }
230 }
231}