• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vcfxb / wright-lang / 14051529229

25 Mar 2025 04:13AM UTC coverage: 75.076% (+20.9%) from 54.177%
14051529229

push

github

vcfxb
coveralls gh action needed a version

994 of 1324 relevant lines covered (75.08%)

29.77 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

59.46
/wright/src/parser/error.rs
1
//! Representation and implementation relating to errors that may be encountered in parsing.
2

3
use crate::{
4
    reporting::{Diagnostic, Highlight},
5
    source_tracking::fragment::Fragment,
6
};
7
use std::borrow::Cow;
8

9
/// All the different errors that can be produced in the process of parsing.
10
/// The names of these should be self-describing, but in cases when one of these needs to appear in a diagnostic,
11
/// use [ParserErrorKind::describe].
12
#[allow(missing_docs)]
13
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14
pub enum ParserErrorKind {
15
    EncounteredUnknownToken,
16
    EncounteredUnterminatedComment,
17
    EncounteredUnterminatedString,
18
    ExpectedIdentifier,
19
    ExpectedPath,
20
    ExpectedWhitespace,
21
    ExpectedIntegerLiteral,
22
    ExpectedBooleanLiteral,
23
    ExpectedImportDeclaration,
24
    ImportMustEndWithSemicolon,
25
}
26

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

32
        match self {
1✔
33
            EncounteredUnknownToken => "encountered unknown token",
×
34
            EncounteredUnterminatedComment => {
35
                "encountered unterminated multiline comment while parsing"
×
36
            }
37
            EncounteredUnterminatedString => {
38
                "encountered unterminated string literal while parsing"
×
39
            }
40
            ExpectedIdentifier => "expected identifier",
1✔
41
            ExpectedIntegerLiteral => "expected integer literal",
×
42
            ExpectedBooleanLiteral => "expected boolean literal",
×
43
            ExpectedPath => "expected path or identifier",
×
44
            ExpectedWhitespace => "expected whitespace character(s)",
×
45
            ExpectedImportDeclaration => "expected import declaration",
×
46
            ImportMustEndWithSemicolon => "import declarations must end with a semicolon",
×
47
        }
48
    }
1✔
49

50
    /// Construct a [ParserError] by adding a location [Fragment] to this error variant.
51
    pub const fn at(self, f: Fragment) -> ParserError {
14✔
52
        ParserError {
14✔
53
            kind: self,
14✔
54
            location: f,
14✔
55
            help: None,
14✔
56
        }
14✔
57
    }
14✔
58
}
59

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

68
    /// Where this error occurred.
69
    pub location: Fragment,
70

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

75
impl ParserError {
76
    /// Builder-style method to add a help string to a [ParserError].
77
    pub fn with_help(mut self, help: impl Into<Cow<'static, str>>) -> Self {
×
78
        self.help = Some(help.into());
×
79
        self
×
80
    }
×
81

82
    /// Turn this parser error into a full blown compiler error.
83
    pub fn as_diagnostic(self) -> Diagnostic {
1✔
84
        let description = self.kind.describe();
1✔
85

86
        // Put a little clarification if the parser reached end of source and then produced an error.
87
        let message = if self.location.is_empty_at_end_of_source() {
1✔
88
            Cow::Borrowed("found end of source here")
×
89
        } else {
90
            Cow::Borrowed("")
1✔
91
        };
92

93
        let mut diagnostic = Diagnostic::error()
1✔
94
            .with_message(description)
1✔
95
            .with_highlights([Highlight::primary(self.location.clone(), message)]);
1✔
96

97
        if let Some(help) = self.help {
1✔
98
            diagnostic = diagnostic.with_notes([help]);
×
99
        }
1✔
100

101
        diagnostic
1✔
102
    }
1✔
103
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc