Actually just three programming languages in a trenchcoat
1use crate::Spanned;
2use source_span::Span;
3use std::fmt::{self, Display};
4
5#[derive(Clone, Debug)]
6pub enum ErrorKind {
7 Unknown(String),
8 KwNotInExpression,
9 RuleRightArrow,
10 MatchStatementExpressionCase,
11 TripleDot { dot: Span },
12 IfStatementRestriction,
13 IfExpressionRestriction,
14 MatchExpressionRestriction,
15}
16
17impl ErrorKind {
18 pub(crate) fn at(self, span: Span) -> SyntaxError {
19 SyntaxError { span, kind: self }
20 }
21}
22
23#[derive(Clone, Debug)]
24pub struct SyntaxError {
25 span: Span,
26 kind: ErrorKind,
27}
28
29impl Spanned for SyntaxError {
30 fn span(&self) -> Span {
31 self.span
32 }
33}
34
35impl SyntaxError {
36 pub(crate) fn new(span: Span, message: impl std::fmt::Display) -> Self {
37 Self {
38 span,
39 kind: ErrorKind::Unknown(message.to_string()),
40 }
41 }
42
43 pub(crate) fn new_spanless(message: impl std::fmt::Display) -> Self {
44 Self {
45 span: Span::default(),
46 kind: ErrorKind::Unknown(message.to_string()),
47 }
48 }
49
50 pub fn kind(&self) -> &ErrorKind {
51 &self.kind
52 }
53}
54
55impl std::error::Error for SyntaxError {}
56
57impl Display for SyntaxError {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 write!(f, "syntax error ({}): ", self.span)?;
60 match &self.kind {
61 ErrorKind::Unknown(message) => write!(f, "{message}")?,
62 ErrorKind::KwNotInExpression => {
63 write!(f, "keyword `not` cannot be used in an expression")?
64 }
65 ErrorKind::RuleRightArrow => {
66 write!(f, "right arrow following rule should be a left arrow")?
67 }
68 ErrorKind::MatchStatementExpressionCase => {
69 write!(f, "case in match statement should be a block")?
70 }
71 ErrorKind::TripleDot { .. } => write!(f, "triple `...` should be `..`")?,
72 ErrorKind::IfStatementRestriction => write!(
73 f,
74 "an `if` statement must be in strict statement form, or be a valid `if` expression"
75 )?,
76 ErrorKind::IfExpressionRestriction => {
77 write!(f, "an `if` expression must have an `else` clause")?
78 }
79 ErrorKind::MatchExpressionRestriction => {
80 write!(f, "a `match` expression must have an `else` case")?
81 }
82 }
83
84 Ok(())
85 }
86}
87
88pub type SyntaxResult<T> = Result<T, SyntaxError>;