1use crate::token::Span;
4use std::fmt;
5
6pub type Result<T> = std::result::Result<T, Error>;
8
9#[derive(Debug, Clone)]
11pub struct Error {
12 pub kind: ErrorKind,
13 pub span: Option<Span>,
14 pub source_line: Option<String>,
15}
16
17#[derive(Debug, Clone)]
18pub enum ErrorKind {
19 UnexpectedChar(char),
21 UnterminatedString,
22 UnterminatedComment,
23 InvalidNumber(String),
24 UnknownDirective(String),
25
26 UnexpectedToken { expected: String, got: String },
28 UnexpectedEof,
29 InvalidDType(String),
30
31 Message(String),
33}
34
35impl Error {
36 pub fn new(kind: ErrorKind, span: Span) -> Self {
37 Self {
38 kind,
39 span: Some(span),
40 source_line: None,
41 }
42 }
43
44 pub fn msg(s: impl Into<String>) -> Self {
45 Self {
46 kind: ErrorKind::Message(s.into()),
47 span: None,
48 source_line: None,
49 }
50 }
51
52 pub fn with_source_line(mut self, line: String) -> Self {
53 self.source_line = Some(line);
54 self
55 }
56}
57
58impl fmt::Display for Error {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 if let Some(span) = &self.span {
61 write!(f, "[{}:{}] ", span.line, span.col)?;
62 }
63 match &self.kind {
64 ErrorKind::UnexpectedChar(c) => write!(f, "unexpected character '{c}'"),
65 ErrorKind::UnterminatedString => write!(f, "unterminated string literal"),
66 ErrorKind::UnterminatedComment => write!(f, "unterminated block comment"),
67 ErrorKind::InvalidNumber(s) => write!(f, "invalid number '{s}'"),
68 ErrorKind::UnknownDirective(s) => write!(f, "unknown directive '@{s}'"),
69 ErrorKind::UnexpectedToken { expected, got } => {
70 write!(f, "expected {expected}, got {got}")
71 }
72 ErrorKind::UnexpectedEof => write!(f, "unexpected end of file"),
73 ErrorKind::InvalidDType(s) => write!(f, "invalid dtype '{s}'"),
74 ErrorKind::Message(s) => write!(f, "{s}"),
75 }?;
76 if let Some(line) = &self.source_line {
77 write!(f, "\n | {line}")?;
78 if let Some(span) = &self.span {
79 write!(f, "\n | {}^", " ".repeat(span.col.saturating_sub(1)))?;
80 }
81 }
82 Ok(())
83 }
84}
85
86impl std::error::Error for Error {}