1use log;
2use core::fmt;
3use std::error::Error;
4use crate::utils;
5use crate::lexer::{TokenMeta, LexerError};
6use crate::debug::SourceError;
7use crate::debug::symbol::DebugSymbol;
8
9
10pub type ParseResult<T> = Result<T, ParserError>;
11
12#[derive(Debug)]
13pub enum ErrorKind {
14 LexerError,
15 EndofTokenStream,
16 SyntaxError(String),
17}
18
19impl<S> From<S> for ErrorKind where S: ToString {
20 fn from(message: S) -> Self {
21 ErrorKind::SyntaxError(message.to_string())
22 }
23}
24
25#[derive(Debug, Clone, Copy)]
27pub enum ContextTag {
28 Token, TopLevel,
30 Sync,
31 StmtMeta,
32 StmtList,
33 ControlFlow,
34 Loop,
35 WhileLoop,
36 ForLoop,
37 ExprMeta,
38 ExprList,
39 Expr,
40 BlockExpr,
41 IfExpr,
42 FunDefExpr,
43 FunParam,
44 AssignmentExpr,
45 BinaryOpExpr,
46 UnaryOpExpr,
47 PrimaryExpr,
48 MemberAccess,
49 IndexAccess,
50 Invocation,
51 ObjectCtor,
52 TupleCtor,
53 Atom,
54 Group,
55 LValue,
56 Label,
57}
58
59impl From<ErrorKind> for ParserError {
60 fn from(kind: ErrorKind) -> Self {
61 Self {
62 kind, context: None, symbol: None, cause: None,
63 }
64 }
65}
66
67impl From<&str> for ParserError {
68 fn from(message: &str) -> Self {
69 Self {
70 kind: message.into(),
71 context: None, symbol: None, cause: None,
72 }
73 }
74}
75
76impl From<LexerError> for ParserError {
77 fn from(error: LexerError) -> Self {
78 Self {
79 kind: ErrorKind::LexerError,
80 context: None,
81 symbol: Some(*error.debug_symbol()),
82 cause: Some(Box::new(error)),
83 }
84 }
85}
86
87#[derive(Debug)]
88pub struct ParserError {
89 kind: ErrorKind,
90 context: Option<ContextTag>,
91 symbol: Option<DebugSymbol>,
92 cause: Option<Box<dyn Error>>,
93}
94
95impl ParserError {
96 pub fn with_context_tag(mut self, context: ContextTag) -> Self {
97 self.context.get_or_insert(context); self
98 }
99
100 pub fn with_symbol(mut self, symbol: DebugSymbol) -> Self {
101 self.symbol.get_or_insert(symbol); self
102 }
103
104 pub fn with_symbol_from_ctx(mut self, ctx: &ErrorContext) -> Self {
105 if let Some(symbol) = ctx.frame().as_debug_symbol() {
106 self.symbol.replace(symbol);
107 }
108 self
109 }
110
111 pub fn with_cause(mut self, error: impl Error + 'static) -> Self {
112 self.cause.replace(Box::new(error)); self
113 }
114
115 pub fn with_error_context(mut self, context: ErrorContext) -> Self {
117 if self.context.is_none() {
118 self.context.replace(context.frame().context());
119 }
120 if self.symbol.is_none() {
121 self.symbol.replace(context.take_debug_symbol());
122 }
123 self
124 }
125
126 pub fn kind(&self) -> &ErrorKind { &self.kind }
127 pub fn context(&self) -> Option<&ContextTag> { self.context.as_ref() }
128}
129
130
131impl Error for ParserError {
132 fn source(&self) -> Option<&(dyn Error + 'static)> {
133 self.cause.as_ref().map(|o| o.as_ref())
134 }
135}
136
137impl SourceError for ParserError {
138 fn debug_symbol(&self) -> Option<&DebugSymbol> { self.symbol.as_ref() }
139}
140
141impl fmt::Display for ParserError {
142 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
143
144 let message = match self.kind() {
145 ErrorKind::LexerError => "",
146 ErrorKind::EndofTokenStream => "unexpected end of token stream",
147 ErrorKind::SyntaxError(message) => message,
148 };
149
150 utils::format_error(fmt, "Syntax error", Some(message), self.source())
151 }
152}
153#[derive(Debug)]
158pub struct ErrorContext {
159 stack: Vec<ContextFrame>,
160}
161
162impl<'m> ErrorContext {
163 pub fn new(base: ContextTag) -> Self {
164 ErrorContext {
165 stack: vec![ ContextFrame::new(base) ],
166 }
167 }
168
169 pub fn frame(&self) -> &ContextFrame {
170 self.stack.last().unwrap()
171 }
172
173 pub fn frame_mut(&mut self) -> &mut ContextFrame {
174 self.stack.last_mut().unwrap()
175 }
176
177 pub fn push(&mut self, tag: ContextTag) {
178 log::debug!("Push frame: {:0>3} {:?}", self.stack.len()+1, tag);
179 self.stack.push(ContextFrame::new(tag))
180 }
181
182 pub fn push_continuation(&mut self, tag: ContextTag, frame: Option<ContextFrame>) {
184 let frame = frame.unwrap_or_else(|| self.frame().clone());
186 self.push(tag);
187 self.frame_mut().extend(frame);
188 }
189
190 pub fn pop(&mut self) -> ContextFrame {
191 log::debug!("Pop frame: {:0>3} {:?}", self.stack.len(), self.frame().context());
192 assert!(self.stack.len() > 1);
193 self.stack.pop().unwrap()
194 }
195
196 pub fn pop_extend(&mut self) {
197 let inner_frame = self.pop();
198 self.frame_mut().extend(inner_frame);
199 }
200
201 pub fn take(mut self) -> ContextFrame {
202 assert!(!self.stack.is_empty());
203 self.stack.pop().unwrap()
204 }
205
206 pub fn context(&self) -> ContextTag { self.frame().context() }
208 pub fn set_start(&mut self, token: &TokenMeta) { self.frame_mut().set_start(token) }
209 pub fn set_end(&mut self, token: &TokenMeta) { self.frame_mut().set_end(token) }
210
211 pub fn take_debug_symbol(mut self) -> DebugSymbol {
212 let mut symbol = self.frame().as_debug_symbol();
213 while symbol.is_none() {
214 if self.stack.len() <= 1 {
215 symbol = self.take().as_debug_symbol();
216 break;
217 }
218
219 self.pop();
220 symbol = self.frame().as_debug_symbol();
221 }
222
223 symbol.expect("could not take debug symbol")
224 }
225}
226
227#[derive(Debug, Clone)]
228pub struct ContextFrame {
229 tag: ContextTag,
230 start: Option<DebugSymbol>,
231 end: Option<DebugSymbol>,
232}
233
234
235impl ContextFrame {
236 pub fn new(tag: ContextTag) -> Self { ContextFrame { tag, start: None, end: None } }
237
238 pub fn context(&self) -> ContextTag { self.tag }
239 pub fn start(&self) -> Option<&DebugSymbol> { self.start.as_ref() }
240 pub fn end(&self) -> Option<&DebugSymbol> { self.end.as_ref() }
241
242 pub fn set_start(&mut self, token: &TokenMeta) {
243 self.start.replace(token.symbol);
244 }
245
246 pub fn set_end(&mut self, token: &TokenMeta) {
247 self.end.replace(token.symbol);
248 }
249
250 pub fn set_span(&mut self, start: Option<DebugSymbol>, end: Option<DebugSymbol>) {
251 self.start = start;
252 self.end = end;
253 }
254
255 pub fn extend(&mut self, other: ContextFrame) {
256 let spans = [self.start, other.start, self.end, other.end];
257 let start = spans.iter().filter_map(|s| s.as_ref())
258 .min_by(|a, b| a.start().cmp(&b.start()));
259
260 let end = spans.iter().filter_map(|s| s.as_ref())
261 .max_by(|a, b| a.end().cmp(&b.end()));
262
263 self.start = start.copied();
264 self.end = end.copied();
265 }
266
267 pub fn as_debug_symbol(&self) -> Option<DebugSymbol> {
268 match (self.start, self.end) {
269
270 (Some(start), Some(end)) => {
271 (start.start(), end.end()).try_into().ok()
272 },
273
274 (Some(symbol), None) | (None, Some(symbol)) => {
275 Some(symbol)
276 },
277
278 (None, None) => None,
279 }
280 }
281}
282
283