wright/parser/
error.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Representation and implementation relating to errors that may be encountered in parsing.

use crate::{
    reporting::{Diagnostic, Highlight},
    source_tracking::fragment::Fragment,
};
use std::borrow::Cow;

/// All the different errors that can be produced in the process of parsing.
/// The names of these should be self-describing, but in cases when one of these needs to appear in a diagnostic,
/// use [ParserErrorKind::describe].
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ParserErrorKind {
    EncounteredUnknownToken,
    EncounteredUnterminatedComment,
    EncounteredUnterminatedString,
    ExpectedIdentifier,
    ExpectedPath,
    ExpectedWhitespace,
    ExpectedIntegerLiteral,
}

impl ParserErrorKind {
    /// Get a short description of this kind of error.
    pub const fn describe(self) -> &'static str {
        use ParserErrorKind::*;

        match self {
            EncounteredUnknownToken => "encountered unknown token",
            EncounteredUnterminatedComment => {
                "encountered unterminated multiline comment while parsing"
            }
            EncounteredUnterminatedString => {
                "encountered unterminated string literal while parsing"
            }
            ExpectedIdentifier => "expected identifier",
            ExpectedIntegerLiteral => "expected integer literal",
            ExpectedPath => "expected path or identifier",
            ExpectedWhitespace => "expected whitespace character(s)",
        }
    }
}

/// An error that occurred while parsing.
/// This error structure is pretty simple compared to what can be represented using a diagnostic. That's fine,
/// since most of the more complex errors arise when typechecking, rather than checking syntax.
#[derive(Debug)]
pub struct ParserError {
    /// What type/cause there is for this error.
    pub kind: ParserErrorKind,

    /// Where this error occurred.
    pub location: Fragment,

    /// Optionally, a help string that can be printed with this error.
    pub help: Option<Cow<'static, str>>,
}

impl ParserError {
    /// Turn this parser error into a full blown compiler error.
    pub fn as_diagnostic(self) -> Diagnostic {
        let description = self.kind.describe();

        let mut diagnostic = Diagnostic::error()
            .with_message(description)
            .with_highlights([Highlight::primary(self.location, "")]);

        if let Some(help) = self.help {
            diagnostic = diagnostic.with_notes([help]);
        }

        diagnostic
    }
}