solscript_parser/
error.rs1use miette::{Diagnostic, SourceSpan};
4use thiserror::Error;
5
6#[derive(Error, Debug, Diagnostic)]
8pub enum ParseError {
9 #[error("Syntax error: {message}")]
10 #[diagnostic(code(solscript::parse::syntax))]
11 Syntax {
12 message: String,
13 #[label("here")]
14 span: SourceSpan,
15 #[source_code]
16 src: String,
17 },
18
19 #[error("Unexpected token: expected {expected}, found {found}")]
20 #[diagnostic(code(solscript::parse::unexpected_token))]
21 UnexpectedToken {
22 expected: String,
23 found: String,
24 #[label("unexpected token")]
25 span: SourceSpan,
26 #[source_code]
27 src: String,
28 },
29
30 #[error("Unexpected end of input")]
31 #[diagnostic(code(solscript::parse::unexpected_eof))]
32 UnexpectedEof {
33 #[label("end of input")]
34 span: SourceSpan,
35 #[source_code]
36 src: String,
37 },
38
39 #[error("Invalid integer literal: {message}")]
40 #[diagnostic(code(solscript::parse::invalid_int))]
41 InvalidInt {
42 message: String,
43 #[label("invalid integer")]
44 span: SourceSpan,
45 #[source_code]
46 src: String,
47 },
48
49 #[error("Invalid float literal: {message}")]
50 #[diagnostic(code(solscript::parse::invalid_float))]
51 InvalidFloat {
52 message: String,
53 #[label("invalid float")]
54 span: SourceSpan,
55 #[source_code]
56 src: String,
57 },
58
59 #[error("Invalid escape sequence")]
60 #[diagnostic(code(solscript::parse::invalid_escape))]
61 InvalidEscape {
62 #[label("invalid escape")]
63 span: SourceSpan,
64 #[source_code]
65 src: String,
66 },
67}
68
69impl ParseError {
70 pub fn syntax(message: impl Into<String>, span: (usize, usize), src: &str) -> Self {
71 Self::Syntax {
72 message: message.into(),
73 span: SourceSpan::new(span.0.into(), span.1 - span.0),
74 src: src.to_string(),
75 }
76 }
77
78 pub fn unexpected_token(
79 expected: impl Into<String>,
80 found: impl Into<String>,
81 span: (usize, usize),
82 src: &str,
83 ) -> Self {
84 Self::UnexpectedToken {
85 expected: expected.into(),
86 found: found.into(),
87 span: SourceSpan::new(span.0.into(), span.1 - span.0),
88 src: src.to_string(),
89 }
90 }
91
92 pub fn unexpected_eof(pos: usize, src: &str) -> Self {
93 Self::UnexpectedEof {
94 span: SourceSpan::new(pos.into(), 0usize),
95 src: src.to_string(),
96 }
97 }
98
99 pub fn invalid_int(message: impl Into<String>, span: (usize, usize), src: &str) -> Self {
100 Self::InvalidInt {
101 message: message.into(),
102 span: SourceSpan::new(span.0.into(), span.1 - span.0),
103 src: src.to_string(),
104 }
105 }
106}
107
108impl From<pest::error::Error<crate::Rule>> for ParseError {
110 fn from(err: pest::error::Error<crate::Rule>) -> Self {
111 let message = err.to_string();
112 let (start, end) = match err.location {
113 pest::error::InputLocation::Pos(p) => (p, p + 1),
114 pest::error::InputLocation::Span((s, e)) => (s, e),
115 };
116
117 ParseError::Syntax {
118 message,
119 span: SourceSpan::new(start.into(), end - start),
120 src: String::new(), }
122 }
123}