cl_parser/
error.rs

1use super::*;
2
3use cl_ast::{Expr, Sym};
4use cl_lexer::error::{Error as LexError, Reason};
5use std::fmt::Display;
6pub type PResult<T> = Result<T, Error>;
7
8/// Contains information about [Parser] errors
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct Error {
11    pub in_file: Sym,
12    pub reason: ErrorKind,
13    pub while_parsing: Parsing,
14    pub loc: Loc,
15}
16impl std::error::Error for Error {}
17
18/// Represents the reason for parse failure
19#[derive(Clone, Debug, PartialEq, Eq)]
20pub enum ErrorKind {
21    Lexical(LexError),
22    EndOfInput,
23    UnmatchedParentheses,
24    UnmatchedCurlyBraces,
25    UnmatchedSquareBrackets,
26    Unexpected(TokenKind),
27    ExpectedToken {
28        want: TokenKind,
29        got: TokenKind,
30    },
31    ExpectedParsing {
32        want: Parsing,
33    },
34    InvalidPattern(Box<Expr>),
35    /// Indicates unfinished code
36    Todo(&'static str),
37}
38impl From<LexError> for ErrorKind {
39    fn from(value: LexError) -> Self {
40        match value.reason() {
41            Reason::EndOfFile => Self::EndOfInput,
42            _ => Self::Lexical(value),
43        }
44    }
45}
46
47/// Compactly represents the stage of parsing an [Error] originated in
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub enum Parsing {
50    Mutability,
51    Visibility,
52    Identifier,
53    Literal,
54
55    File,
56
57    Attrs,
58    Meta,
59    MetaKind,
60
61    Item,
62    ItemKind,
63    Generics,
64    Alias,
65    Const,
66    Static,
67    Module,
68    ModuleKind,
69    Function,
70    Param,
71    Struct,
72    StructKind,
73    StructMember,
74    Enum,
75    EnumKind,
76    Variant,
77    VariantKind,
78    Impl,
79    ImplKind,
80    Use,
81    UseTree,
82
83    Ty,
84    TyKind,
85    TySlice,
86    TyArray,
87    TyTuple,
88    TyRef,
89    TyFn,
90
91    Path,
92    PathPart,
93
94    Stmt,
95    StmtKind,
96    Let,
97
98    Expr,
99    ExprKind,
100    Closure,
101    Assign,
102    AssignKind,
103    Binary,
104    BinaryKind,
105    Unary,
106    UnaryKind,
107    Cast,
108    Index,
109    Structor,
110    Fielder,
111    Call,
112    Member,
113    Array,
114    ArrayRep,
115    AddrOf,
116    Block,
117    Group,
118    Tuple,
119    Loop,
120    While,
121    If,
122    For,
123    Else,
124    Break,
125    Return,
126    Continue,
127
128    Pattern,
129    Match,
130    MatchArm,
131}
132
133impl Display for Error {
134    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
135        let Self { in_file, reason, while_parsing, loc } = self;
136        match reason {
137            // TODO entries are debug-printed
138            ErrorKind::Todo(_) => write!(f, "{in_file}:{loc} {reason} {while_parsing:?}"),
139            // lexical errors print their own higher-resolution loc info
140            ErrorKind::Lexical(e) => write!(f, "{e} (while parsing {while_parsing})"),
141            _ => {
142                if !in_file.is_empty() {
143                    write!(f, "{in_file}:")?
144                }
145                write!(f, "{loc}: {reason} while parsing {while_parsing}")
146            }
147        }
148    }
149}
150impl Display for ErrorKind {
151    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152        match self {
153            ErrorKind::Lexical(e) => e.fmt(f),
154            ErrorKind::EndOfInput => write!(f, "End of input"),
155            ErrorKind::UnmatchedParentheses => write!(f, "Unmatched parentheses"),
156            ErrorKind::UnmatchedCurlyBraces => write!(f, "Unmatched curly braces"),
157            ErrorKind::UnmatchedSquareBrackets => write!(f, "Unmatched square brackets"),
158            ErrorKind::Unexpected(t) => write!(f, "Encountered unexpected token `{t}`"),
159            ErrorKind::ExpectedToken { want: e, got: g } => write!(f, "Expected `{e}`, got `{g}`"),
160            ErrorKind::ExpectedParsing { want } => write!(f, "Expected {want}"),
161            ErrorKind::InvalidPattern(got) => write!(f, "Got invalid `{got}`"),
162            ErrorKind::Todo(unfinished) => write!(f, "TODO: {unfinished}"),
163        }
164    }
165}
166impl Display for Parsing {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        match self {
169            Parsing::Visibility => "a visibility qualifier",
170            Parsing::Mutability => "a mutability qualifier",
171            Parsing::Identifier => "an identifier",
172            Parsing::Literal => "a literal",
173
174            Parsing::File => "a file",
175
176            Parsing::Attrs => "an attribute-set",
177            Parsing::Meta => "an attribute",
178            Parsing::MetaKind => "an attribute's arguments",
179            Parsing::Item => "an item",
180            Parsing::ItemKind => "an item",
181            Parsing::Generics => "a list of type arguments",
182            Parsing::Alias => "a type alias",
183            Parsing::Const => "a const item",
184            Parsing::Static => "a static variable",
185            Parsing::Module => "a module",
186            Parsing::ModuleKind => "a module",
187            Parsing::Function => "a function",
188            Parsing::Param => "a function parameter",
189            Parsing::Struct => "a struct",
190            Parsing::StructKind => "a struct",
191            Parsing::StructMember => "a struct member",
192            Parsing::Enum => "an enum",
193            Parsing::EnumKind => "an enum",
194            Parsing::Variant => "an enum variant",
195            Parsing::VariantKind => "an enum variant",
196            Parsing::Impl => "an impl block",
197            Parsing::ImplKind => "the target of an impl block",
198            Parsing::Use => "a use item",
199            Parsing::UseTree => "a use-tree",
200
201            Parsing::Ty => "a type",
202            Parsing::TyKind => "a type",
203            Parsing::TySlice => "a slice type",
204            Parsing::TyArray => "an array type",
205            Parsing::TyTuple => "a tuple of types",
206            Parsing::TyRef => "a reference type",
207            Parsing::TyFn => "a function pointer type",
208
209            Parsing::Path => "a path",
210            Parsing::PathPart => "a path component",
211
212            Parsing::Stmt => "a statement",
213            Parsing::StmtKind => "a statement",
214            Parsing::Let => "a local variable declaration",
215
216            Parsing::Expr => "an expression",
217            Parsing::ExprKind => "an expression",
218            Parsing::Closure => "an anonymous function",
219            Parsing::Assign => "an assignment",
220            Parsing::AssignKind => "an assignment operator",
221            Parsing::Binary => "a binary expression",
222            Parsing::BinaryKind => "a binary operator",
223            Parsing::Unary => "a unary expression",
224            Parsing::UnaryKind => "a unary operator",
225            Parsing::Cast => "an `as`-casting expression",
226            Parsing::Index => "an indexing expression",
227            Parsing::Structor => "a struct constructor expression",
228            Parsing::Fielder => "a struct field expression",
229            Parsing::Call => "a call expression",
230            Parsing::Member => "a member access expression",
231            Parsing::Array => "an array",
232            Parsing::ArrayRep => "an array of form [k;N]",
233            Parsing::AddrOf => "a borrow op",
234            Parsing::Block => "a block",
235            Parsing::Group => "a grouped expression",
236            Parsing::Tuple => "a tuple",
237            Parsing::Loop => "an unconditional loop expression",
238            Parsing::While => "a while expression",
239            Parsing::If => "an if expression",
240            Parsing::For => "a for expression",
241            Parsing::Else => "an else block",
242            Parsing::Break => "a break expression",
243            Parsing::Return => "a return expression",
244            Parsing::Continue => "a continue expression",
245
246            Parsing::Pattern => "a pattern",
247            Parsing::Match => "a match expression",
248            Parsing::MatchArm => "a match arm",
249        }
250        .fmt(f)
251    }
252}