1#![allow(unused_assignments)]
5
6use atoxide_lexer::{Span, TokenKind};
7use miette::{Diagnostic, SourceSpan};
8use thiserror::Error;
9
10#[derive(Debug, Clone, Error, Diagnostic)]
12pub enum ParseError {
13 #[error("unexpected token")]
14 #[diagnostic(code(ato::parse::unexpected_token))]
15 UnexpectedToken {
16 expected: String,
17 found: TokenKind,
18 #[label("found {found:?} here")]
19 span: SourceSpan,
20 },
21
22 #[error("unexpected end of file")]
23 #[diagnostic(code(ato::parse::unexpected_eof))]
24 UnexpectedEof {
25 expected: String,
26 #[label("expected {expected}")]
27 span: SourceSpan,
28 },
29
30 #[error("expected {expected}")]
31 #[diagnostic(code(ato::parse::expected))]
32 Expected {
33 expected: String,
34 #[label("expected {expected} here")]
35 span: SourceSpan,
36 },
37
38 #[error("invalid number literal")]
39 #[diagnostic(code(ato::parse::invalid_number))]
40 InvalidNumber {
41 #[label("invalid number")]
42 span: SourceSpan,
43 },
44
45 #[error("invalid indentation")]
46 #[diagnostic(code(ato::parse::invalid_indentation))]
47 InvalidIndentation {
48 #[label("expected indented block")]
49 span: SourceSpan,
50 },
51
52 #[error("mixed connection operators")]
53 #[diagnostic(
54 code(ato::parse::mixed_connection),
55 help("use either ~> or <~ consistently, not both")
56 )]
57 MixedConnectionOperators {
58 #[label("mixed operators in connection chain")]
59 span: SourceSpan,
60 },
61
62 #[error("empty block")]
63 #[diagnostic(
64 code(ato::parse::empty_block),
65 help("add a 'pass' statement if the block should be empty")
66 )]
67 EmptyBlock {
68 #[label("block has no statements")]
69 span: SourceSpan,
70 },
71
72 #[error("lexer error: {message}")]
73 #[diagnostic(code(ato::lexer::error))]
74 LexerError {
75 message: String,
76 #[label("{message}")]
77 span: SourceSpan,
78 },
79}
80
81impl ParseError {
82 pub fn unexpected_token(expected: impl Into<String>, found: TokenKind, span: Span) -> Self {
84 ParseError::UnexpectedToken {
85 expected: expected.into(),
86 found,
87 span: span_to_source_span(span),
88 }
89 }
90
91 pub fn unexpected_eof(expected: impl Into<String>, span: Span) -> Self {
93 ParseError::UnexpectedEof {
94 expected: expected.into(),
95 span: span_to_source_span(span),
96 }
97 }
98
99 pub fn expected(expected: impl Into<String>, span: Span) -> Self {
101 ParseError::Expected {
102 expected: expected.into(),
103 span: span_to_source_span(span),
104 }
105 }
106
107 pub fn invalid_number(span: Span) -> Self {
109 ParseError::InvalidNumber {
110 span: span_to_source_span(span),
111 }
112 }
113
114 pub fn invalid_indentation(span: Span) -> Self {
116 ParseError::InvalidIndentation {
117 span: span_to_source_span(span),
118 }
119 }
120
121 pub fn mixed_connection_operators(span: Span) -> Self {
123 ParseError::MixedConnectionOperators {
124 span: span_to_source_span(span),
125 }
126 }
127
128 pub fn empty_block(span: Span) -> Self {
130 ParseError::EmptyBlock {
131 span: span_to_source_span(span),
132 }
133 }
134
135 pub fn lexer_error(message: impl Into<String>, span: Span) -> Self {
137 ParseError::LexerError {
138 message: message.into(),
139 span: span_to_source_span(span),
140 }
141 }
142}
143
144fn span_to_source_span(span: Span) -> SourceSpan {
146 SourceSpan::new(span.start.into(), span.end - span.start)
147}
148
149pub type ParseResult<T> = Result<T, ParseError>;