leo_errors/errors/parser/
parser_errors.rs

1// Copyright (C) 2019-2024 Aleo Systems Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17use crate::create_messages;
18
19use std::fmt::{Debug, Display};
20
21create_messages!(
22    /// ParserError enum that represents all the errors for the `leo-parser` crate.
23    ParserError,
24    code_mask: 0000i32,
25    code_prefix: "PAR",
26
27    /// For when the parser encountered an unexpected token.
28    @formatted
29    unexpected_token {
30        args: (message: impl Display),
31        msg: message,
32        help: None,
33    }
34
35    /// For when the parser encountered an invalid address literal.
36    @formatted
37    invalid_address_lit {
38        args: (token: impl Display),
39        msg: format!("invalid address literal: '{token}'"),
40        help: None,
41    }
42
43    /// For when the parser encountered an empty import list.
44    @formatted
45    invalid_import_list {
46        args: (),
47        msg: "Cannot import empty list",
48        help: None,
49    }
50
51    /// For when the parser encountered an unexpected End of File.
52    @formatted
53    unexpected_eof {
54        args: (),
55        msg: "unexpected EOF",
56        help: None,
57    }
58
59    /// For when the parser encountered an unexpected whitespace.
60    @formatted
61    unexpected_whitespace {
62        args: (left: impl Display, right: impl Display),
63        msg: format!("Unexpected white space between terms {left} and {right}"),
64        help: None,
65    }
66
67    /// For when the parser encountered an unexpected list of tokens.
68    @formatted
69    unexpected {
70        args: (found: impl Display, expected: impl Display),
71        msg: format!("expected {expected} -- found '{found}'"),
72        help: None,
73    }
74
75    /// For when the parser encountered a mix of commas and semi-colons in struct member variables.
76    // TODO This error is unused. Remove it in a future version.
77    @formatted
78    mixed_commas_and_semicolons {
79        args: (),
80        msg: "Cannot mix use of commas and semi-colons for struct member variable declarations.",
81        help: None,
82    }
83
84    /// For when the parser encountered an unexpected identifier.
85    @formatted
86    unexpected_ident {
87        args: (found: impl Display, expected: &[impl Display]),
88        msg: format!(
89            "unexpected identifier: expected {} -- found '{found}'",
90            expected
91                .iter()
92                .map(|x| format!("'{x}'"))
93                .collect::<Vec<_>>()
94                .join(", "),
95        ),
96        help: None,
97    }
98
99    /// For when the parser encountered an unexpected statement.
100    @formatted
101    unexpected_statement {
102        args: (found: impl Display, expected: impl Display),
103        msg: format!("unexpected statement: expected '{expected}', found '{found}'"),
104        help: None,
105    }
106
107    /// For when the parser encountered an unexpected string.
108    @formatted
109    unexpected_str {
110        args: (found: impl Display, expected: impl Display),
111        msg: format!("unexpected string: expected '{expected}', found '{found}'"),
112        help: None,
113    }
114
115    /// For when the parser encountered an unexpected spread in an array init expression.
116    @formatted
117    spread_in_array_init {
118        args: (),
119        msg: "illegal spread in array initializer",
120        help: None,
121    }
122
123    /// When more input was expected but not found.
124    @backtraced
125    lexer_empty_input {
126        args: (),
127        msg: "Expected more characters to lex but found none.",
128        help: None,
129    }
130
131    /// When an integer is started with a leading zero.
132    @backtraced
133    lexer_expected_valid_escaped_char {
134    args: (input: impl Display),
135    msg: format!("Expected a valid escape character but found `{input}`."),
136    help: None,
137    }
138
139    /// When a string is not properly closed.
140    @backtraced
141    lexer_string_not_closed {
142    args: (input: impl Display),
143    msg: format!("Expected a closed string but found `{input}`."),
144    help: None,
145    }
146
147    /// When a block comment is empty.
148    @backtraced
149    lexer_empty_block_comment {
150    args: (),
151    msg: "Empty block comment.",
152    help: None,
153    }
154
155    /// When a block comment is not closed before end of file.
156    @backtraced
157    lexer_block_comment_does_not_close_before_eof {
158    args: (input: impl Display),
159    msg: format!("Block comment does not close with content: `{input}`."),
160    help: None,
161    }
162
163    /// When the lexer could not lex some text.
164    @backtraced
165    could_not_lex {
166    args: (input: impl Display),
167    msg: format!("Could not lex the following content: `{input}`.\n"),
168    help: None,
169    }
170
171    /// When the user tries to pass an implicit value.
172    @formatted
173    implicit_values_not_allowed {
174        args: (input: impl Display),
175        msg: format!("Could not parse the implicit value: {input}."),
176        help: None,
177    }
178
179    /// When a hex number is provided.
180    // TODO This error is unused. Remove it in a future version.
181    @backtraced
182    lexer_hex_number_provided {
183        args: (input: impl Display),
184        msg: format!("A hex number `{input}..` was provided but hex is not allowed."),
185        help: None,
186    }
187
188    /// For when a user specified more than one mode on a parameter.
189    @formatted
190    inputs_multiple_variable_modes_specified {
191        args: (),
192        msg: "A parameter cannot have multiple modes.",
193        help: Some("Consider using either `constant`, `public`, `private`, or none at all.".to_string()),
194    }
195
196    /// For when the lexer encountered a bidi override character
197    @backtraced
198    lexer_bidi_override {
199        args: (),
200        msg: "Unicode bidi override code point encountered.",
201        help: None,
202    }
203
204    /// Parsed an unknown method call on the type of an expression.
205    @formatted
206    invalid_method_call {
207        args: (expr: impl Display, func: impl Display, num_args: impl Display),
208        msg: format!("The type of `{expr}` has no associated function `{func}` that takes {num_args} argument(s)."),
209        help: None,
210    }
211
212    @formatted
213    invalid_associated_access {
214        args: (name: impl Display),
215        msg: format!("Invalid associated access call to struct {name}."),
216        help: Some("Double colon `::` syntax is only supported for core functions in Leo for mainnet.".to_string()),
217    }
218
219    @formatted
220    leo_and_aleo_imports_only {
221        args: (),
222        msg: "Invalid import call to non-leo non-aleo file.",
223        help: Some("Only imports of Leo `.leo` and Aleo `.aleo` files are currently supported.".to_string()),
224    }
225
226    @formatted
227    space_in_annotation {
228        args: (),
229        msg: "Illegal spacing in the annotation declaration.",
230        help: Some("Remove whitespace between the `@` symbol and the identifier.".to_string()),
231    }
232
233    @formatted
234    circuit_is_deprecated {
235        args: (),
236        msg: "The keyword `circuit` is deprecated.",
237        help: Some("Use `struct` instead.".to_string()),
238    }
239
240    @formatted
241    only_one_program_scope_is_allowed {
242        args: (),
243        msg: "Only one program scope is allowed in a Leo file.",
244        help: None,
245    }
246
247    @formatted
248    missing_program_scope {
249        args: (),
250        msg: "Missing a program scope in a Leo file.",
251        help: Some("Add a program scope of the form: `program <name>.aleo { ... }` to the Leo file.".to_string()),
252    }
253
254    @formatted
255    invalid_network {
256        args: (),
257        msg: "Invalid network identifier. The only supported identifier is `.aleo`.",
258        help: None,
259    }
260
261    @formatted
262    tuple_must_have_at_least_two_elements {
263        args: (kind: impl Display),
264        msg: format!("A tuple {kind} must have at least two elements."),
265        help: None,
266    }
267
268    @formatted
269    async_finalize_is_deprecated {
270        args: (),
271        msg: format!("`async finalize` is deprecated."),
272        help: Some("Use `return <expr> then finalize(<args>)` instead.".to_string()),
273    }
274
275    @formatted
276    finalize_statements_are_deprecated {
277        args: (),
278        msg: format!("`finalize` statements are deprecated."),
279        help: Some("Use `return <expr> then finalize(<args>)` instead.".to_string()),
280    }
281
282    @formatted
283    console_statements_are_not_yet_supported {
284        args: (),
285        msg: format!("`console` statements are not yet supported."),
286        help: Some("Consider using `assert`, `assert_eq`, or `assert_neq` instead.".to_string()),
287    }
288
289    /// Enforce that tuple index must not have leading 0, or underscore in between digits
290    @formatted
291    tuple_index_must_be_whole_number {
292        args: (found: impl Display),
293        msg: format!("expected no underscores or leading zeros -- found '{found}'"),
294        help: None,
295    }
296
297    @formatted
298    array_must_have_at_least_one_element {
299        args: (kind: impl Display),
300        msg: format!("An array {kind} must have at least one element."),
301        help: None,
302    }
303
304    @formatted
305    invalid_external_type {
306        args: (),
307        msg: format!("Invalid external type."),
308        help: Some("External type should have the form `<program>.aleo/<record>`. For example `bank.aleo/loan`".to_string()),
309    }
310
311    @formatted
312    cannot_declare_external_struct {
313        args: (),
314        msg: format!("Cannot declare external struct."),
315        help: None,
316    }
317
318    @formatted
319    external_type_cannot_be_used_inside_function {
320        args: (program: impl Display, file_type: impl Display),
321        msg: format!("External types cannot be used inside function (only as input/output types) -- found exported type from '{program}.{file_type}'."),
322        help: None,
323    }
324
325    /// Enforce that cannot use import in program scope
326    @formatted
327    cannot_import_inside_program_body {
328        args: (),
329        msg: format!("Cannot use import inside program body."),
330        help: None,
331    }
332
333    @formatted
334    only_aleo_external_calls {
335        args: (),
336        msg: format!("Only external calls to `.aleo` programs are supported."),
337        help: None,
338    }
339
340    @formatted
341    cannot_define_external_record {
342        args: (),
343        msg: format!("Cannot create an external record. Records can only be created in the program that they are defined in."),
344        help: None,
345    }
346
347    /// For when the parser encountered a member declaration not followed by a comma.
348    @formatted
349    comma_expected_after_member {
350        args: (),
351        msg: "Each member declaration in a struct or record must be followed by a comma (except the last).",
352        help: None,
353    }
354
355    @formatted
356    hexbin_literal_nonintegers {
357        args: (),
358        msg: format!("Hex, octal, and binary literals may only be used for integer types."),
359        help: None,
360    }
361
362    @backtraced
363    wrong_digit_for_radix {
364        args: (digit: char, radix: u32, token: String),
365        msg: format!("Digit {digit} invalid in radix {radix} (token {token})."),
366        help: None,
367    }
368
369    @formatted
370    identifier_too_long {
371        args: (ident: impl Display, length: usize, max_length: usize),
372        msg: format!("Identifier {ident} is too long ({length} bytes; maximum is {max_length})"),
373        help: None,
374    }
375);