Actually just three programming languages in a trenchcoat
at main 97 lines 2.9 kB view raw
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 IfExpressionRestriction, 13 TaggedTemplateMissingIdentifier, 14 TaggedTemplateNotIdentifier, 15 DoMissingParameterList, 16 DoUnnecessaryBangOParen, 17} 18 19impl ErrorKind { 20 pub(crate) fn at(self, span: Span) -> SyntaxError { 21 SyntaxError { span, kind: self } 22 } 23} 24 25#[derive(Clone, Debug)] 26pub struct SyntaxError { 27 span: Span, 28 kind: ErrorKind, 29} 30 31impl Spanned for SyntaxError { 32 fn span(&self) -> Span { 33 self.span 34 } 35} 36 37impl SyntaxError { 38 pub(crate) fn new(span: Span, message: impl std::fmt::Display) -> Self { 39 Self { 40 span, 41 kind: ErrorKind::Unknown(message.to_string()), 42 } 43 } 44 45 pub(crate) fn new_spanless(message: impl std::fmt::Display) -> Self { 46 Self { 47 span: Span::default(), 48 kind: ErrorKind::Unknown(message.to_string()), 49 } 50 } 51 52 pub fn kind(&self) -> &ErrorKind { 53 &self.kind 54 } 55} 56 57impl std::error::Error for SyntaxError {} 58 59impl Display for SyntaxError { 60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 61 write!(f, "syntax error ({}): ", self.span)?; 62 match &self.kind { 63 ErrorKind::Unknown(message) => write!(f, "{message}")?, 64 ErrorKind::KwNotInExpression => { 65 write!(f, "keyword `not` cannot be used in an expression")? 66 } 67 ErrorKind::RuleRightArrow => { 68 write!(f, "right arrow following rule should be a left arrow")? 69 } 70 ErrorKind::MatchStatementExpressionCase => { 71 write!(f, "case in match statement should be a block")? 72 } 73 ErrorKind::TripleDot { .. } => write!(f, "triple `...` should be `..`")?, 74 ErrorKind::IfExpressionRestriction => { 75 write!(f, "an `if` expression must have an `else` clause")? 76 } 77 ErrorKind::TaggedTemplateMissingIdentifier => write!( 78 f, 79 "the $ operator prefixing a tagged template requires a tag identifier" 80 )?, 81 ErrorKind::TaggedTemplateNotIdentifier => write!( 82 f, 83 "the $ operator prefixing a tagged template requires a tag identifier" 84 )?, 85 ErrorKind::DoMissingParameterList => { 86 write!(f, "a `do` closure requires a parameter list, even if empty")? 87 } 88 ErrorKind::DoUnnecessaryBangOParen => { 89 write!(f, "a `do` closure definition does not use `!`")? 90 } 91 } 92 93 Ok(()) 94 } 95} 96 97pub type SyntaxResult<T> = Result<T, SyntaxError>;