leo_errors/errors/parser/
parser_errors.rs

1// Copyright (C) 2019-2025 Provable 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    // TODO This error is unused. Remove it in a future version.
133    @backtraced
134    lexer_expected_valid_escaped_char {
135    args: (input: impl Display),
136    msg: format!("Expected a valid escape character but found `{input}`."),
137    help: None,
138    }
139
140    /// When a string is not properly closed.
141    @backtraced
142    lexer_string_not_closed {
143    args: (input: impl Display),
144    msg: format!("Expected a closed string but found `{input}`."),
145    help: None,
146    }
147
148    /// When a block comment is empty.
149    @backtraced
150    lexer_empty_block_comment {
151    args: (),
152    msg: "Empty block comment.",
153    help: None,
154    }
155
156    /// When a block comment is not closed before end of file.
157    @backtraced
158    lexer_block_comment_does_not_close_before_eof {
159    args: (input: impl Display),
160    msg: format!("Block comment does not close with content: `{input}`."),
161    help: None,
162    }
163
164    /// When the lexer could not lex some text.
165    @backtraced
166    could_not_lex {
167    args: (input: impl Display),
168    msg: format!("Could not lex the following content: `{input}`.\n"),
169    help: None,
170    }
171
172    /// When the user tries to pass an implicit value.
173    @formatted
174    implicit_values_not_allowed {
175        args: (input: impl Display),
176        msg: format!("Could not parse the implicit value: {input}."),
177        help: None,
178    }
179
180    /// When a hex number is provided.
181    // TODO This error is unused. Remove it in a future version.
182    @backtraced
183    lexer_hex_number_provided {
184        args: (input: impl Display),
185        msg: format!("A hex number `{input}..` was provided but hex is not allowed."),
186        help: None,
187    }
188
189    /// For when a user specified more than one mode on a parameter.
190    @formatted
191    inputs_multiple_variable_modes_specified {
192        args: (),
193        msg: "A parameter cannot have multiple modes.",
194        help: Some("Consider using either `constant`, `public`, `private`, or none at all.".to_string()),
195    }
196
197    /// For when the lexer encountered a bidi override character
198    @backtraced
199    lexer_bidi_override {
200        args: (),
201        msg: "Unicode bidi override code point encountered.",
202        help: None,
203    }
204
205    /// Parsed an unknown method call on the type of an expression.
206    @formatted
207    invalid_method_call {
208        args: (expr: impl Display, func: impl Display, num_args: impl Display),
209        msg: format!("The type of `{expr}` has no associated function `{func}` that takes {num_args} argument(s)."),
210        help: None,
211    }
212
213    @formatted
214    invalid_associated_access {
215        args: (name: impl Display),
216        msg: format!("Invalid associated access call to struct {name}."),
217        help: Some("Double colon `::` syntax is only supported for core functions in Leo for mainnet.".to_string()),
218    }
219
220    @formatted
221    leo_and_aleo_imports_only {
222        args: (),
223        msg: "Invalid import call to non-leo non-aleo file.",
224        help: Some("Only imports of Leo `.leo` and Aleo `.aleo` files are currently supported.".to_string()),
225    }
226
227    @formatted
228    space_in_annotation {
229        args: (),
230        msg: "Illegal spacing in the annotation declaration.",
231        help: Some("Remove whitespace between the `@` symbol and the identifier.".to_string()),
232    }
233
234    @formatted
235    circuit_is_deprecated {
236        args: (),
237        msg: "The keyword `circuit` is deprecated.",
238        help: Some("Use `struct` instead.".to_string()),
239    }
240
241    @formatted
242    only_one_program_scope_is_allowed {
243        args: (),
244        msg: "Only one program scope is allowed in a Leo file.",
245        help: None,
246    }
247
248    @formatted
249    missing_program_scope {
250        args: (),
251        msg: "Missing a program scope in a Leo file.",
252        help: Some("Add a program scope of the form: `program <name>.aleo { ... }` to the Leo file.".to_string()),
253    }
254
255    @formatted
256    invalid_network {
257        args: (),
258        msg: "Invalid network identifier. The only supported identifier is `.aleo`.",
259        help: None,
260    }
261
262    @formatted
263    tuple_must_have_at_least_two_elements {
264        args: (kind: impl Display),
265        msg: format!("A tuple {kind} must have at least two elements."),
266        help: None,
267    }
268
269    @formatted
270    async_finalize_is_deprecated {
271        args: (),
272        msg: format!("`async finalize` is deprecated."),
273        help: Some("Use `return <expr> then finalize(<args>)` instead.".to_string()),
274    }
275
276    @formatted
277    finalize_statements_are_deprecated {
278        args: (),
279        msg: format!("`finalize` statements are deprecated."),
280        help: Some("Use `return <expr> then finalize(<args>)` instead.".to_string()),
281    }
282
283    // TODO This error is unused. Remove it in a future version.
284    @formatted
285    console_statements_are_not_yet_supported {
286        args: (),
287        msg: format!("`console` statements are not yet supported."),
288        help: Some("Consider using `assert`, `assert_eq`, or `assert_neq` instead.".to_string()),
289    }
290
291    /// Enforce that tuple index must not have leading 0, or underscore in between digits
292    @formatted
293    tuple_index_must_be_whole_number {
294        args: (found: impl Display),
295        msg: format!("expected no underscores or leading zeros -- found '{found}'"),
296        help: None,
297    }
298
299    @formatted
300    array_must_have_at_least_one_element {
301        args: (kind: impl Display),
302        msg: format!("An array {kind} must have at least one element."),
303        help: None,
304    }
305
306    @formatted
307    invalid_external_type {
308        args: (),
309        msg: format!("Invalid external type."),
310        help: Some("External type should have the form `<program>.aleo/<record>`. For example `bank.aleo/loan`".to_string()),
311    }
312
313    @formatted
314    cannot_declare_external_struct {
315        args: (),
316        msg: format!("Cannot declare external struct."),
317        help: None,
318    }
319
320    @formatted
321    external_type_cannot_be_used_inside_function {
322        args: (program: impl Display, file_type: impl Display),
323        msg: format!("External types cannot be used inside function (only as input/output types) -- found exported type from '{program}.{file_type}'."),
324        help: None,
325    }
326
327    /// Enforce that cannot use import in program scope
328    @formatted
329    cannot_import_inside_program_body {
330        args: (),
331        msg: format!("Cannot use import inside program body."),
332        help: None,
333    }
334
335    @formatted
336    only_aleo_external_calls {
337        args: (),
338        msg: format!("Only external calls to `.aleo` programs are supported."),
339        help: None,
340    }
341
342    @formatted
343    cannot_define_external_record {
344        args: (),
345        msg: format!("Cannot create an external record. Records can only be created in the program that they are defined in."),
346        help: None,
347    }
348
349    /// For when the parser encountered a member declaration not followed by a comma.
350    @formatted
351    comma_expected_after_member {
352        args: (),
353        msg: "Each member declaration in a struct or record must be followed by a comma (except the last).",
354        help: None,
355    }
356
357    @formatted
358    hexbin_literal_nonintegers {
359        args: (),
360        msg: format!("Hex, octal, and binary literals may only be used for integer types."),
361        help: None,
362    }
363
364    @backtraced
365    wrong_digit_for_radix {
366        args: (digit: char, radix: u32, token: String),
367        msg: format!("Digit {digit} invalid in radix {radix} (token {token})."),
368        help: None,
369    }
370
371    @formatted
372    identifier_too_long {
373        args: (ident: impl Display, length: usize, max_length: usize),
374        msg: format!("Identifier {ident} is too long ({length} bytes; maximum is {max_length})"),
375        help: None,
376    }
377
378    @formatted
379    expected_identifier {
380        args: (),
381        msg: format!("Expected an identifier."),
382        help: None,
383    }
384);