1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#![forbid(unsafe_code)]
use super::span::Span;
/// Errors produced by the lexer.
#[derive(Debug, Clone, PartialEq)]
pub enum LexError {
/// An unexpected character was encountered.
UnexpectedChar { ch: char, span: Span },
/// A string literal was not closed before end-of-input.
UnterminatedString { span: Span },
/// A block comment was not closed before end-of-input.
UnterminatedBlockComment { span: Span },
/// An unrecognised escape sequence inside a string literal.
InvalidEscape { ch: char, span: Span },
/// An integer literal exceeded `u64::MAX`.
IntOverflow { span: Span },
/// A floating-point literal could not be parsed.
FloatParseError { span: Span },
/// A `\xHH` hex escape had fewer than 2 valid hex digits.
InvalidHexEscape { span: Span },
/// A `\uXXXX` or `\UXXXXXXXX` codepoint was out of range or malformed.
InvalidUnicodeEscape { span: Span },
}
impl std::fmt::Display for LexError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
LexError::UnexpectedChar { ch, span } => {
write!(
f,
"unexpected character {:?} at byte offset {}",
ch, span.start
)
}
LexError::UnterminatedString { span } => {
write!(
f,
"unterminated string literal starting at byte {}",
span.start
)
}
LexError::UnterminatedBlockComment { span } => {
write!(
f,
"unterminated block comment starting at byte {}",
span.start
)
}
LexError::InvalidEscape { ch, span } => {
write!(
f,
"invalid escape sequence \\{:?} at byte offset {}",
ch, span.start
)
}
LexError::IntOverflow { span } => {
write!(f, "integer literal overflow at byte offset {}", span.start)
}
LexError::FloatParseError { span } => {
write!(
f,
"cannot parse float literal at byte offset {}",
span.start
)
}
LexError::InvalidHexEscape { span } => {
write!(f, "invalid \\xHH hex escape at byte offset {}", span.start)
}
LexError::InvalidUnicodeEscape { span } => {
write!(f, "invalid unicode escape at byte offset {}", span.start)
}
}
}
}
impl std::error::Error for LexError {}
/// Errors produced by the outline parser.
#[derive(Debug, Clone, PartialEq)]
pub enum ParseError {
/// A lexer error was encountered while parsing.
Lex(LexError),
/// An unexpected token was encountered; carries what was expected and found.
UnexpectedToken {
expected: String,
found: String,
span: Span,
},
/// The token stream ended before the parse was complete.
UnexpectedEof,
/// A `{` was opened but never closed.
UnbalancedBraces { span: Span },
/// The `syntax` statement contained an unrecognised value.
UnknownSyntax(String),
/// The `edition` statement contained an unrecognised or unsupported value.
///
/// Currently only `"2023"` is accepted; any other edition string triggers
/// this error.
UnsupportedEdition(String),
/// Both `syntax` and `edition` were specified in the same file.
SyntaxAndEditionConflict,
/// A proto2 `group` field name does not start with an uppercase letter.
MalformedGroupName { name: String, span: Span },
}
impl std::fmt::Display for ParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ParseError::Lex(e) => write!(f, "lex error: {e}"),
ParseError::UnexpectedToken {
expected,
found,
span,
} => {
write!(
f,
"expected {expected} but found {found} at byte offset {}",
span.start
)
}
ParseError::UnexpectedEof => write!(f, "unexpected end of file"),
ParseError::UnbalancedBraces { span } => {
write!(
f,
"unbalanced braces: unclosed '{{' at byte offset {}",
span.start
)
}
ParseError::UnknownSyntax(s) => {
write!(
f,
"unknown syntax value: expected \"proto2\" or \"proto3\", found {:?}",
s
)
}
ParseError::UnsupportedEdition(s) => {
write!(f, "unsupported edition: expected \"2023\", found {:?}", s)
}
ParseError::SyntaxAndEditionConflict => {
write!(
f,
"a .proto file cannot specify both 'syntax' and 'edition'"
)
}
ParseError::MalformedGroupName { name, span } => {
write!(
f,
"proto2 group name must start with an uppercase letter: {:?} at byte offset {}",
name, span.start
)
}
}
}
}
impl std::error::Error for ParseError {}
impl From<LexError> for ParseError {
fn from(e: LexError) -> Self {
ParseError::Lex(e)
}
}