document all parser errors

This commit is contained in:
Mazdak Farrokhzad 2022-02-22 16:33:47 +01:00
parent 266a14db13
commit d98f08c179
24 changed files with 956 additions and 0 deletions

View File

@ -0,0 +1,52 @@
# An empty string `""`
## Example
This error occurs when an empty string literal was specified.
Erroneous code example:
```js
function main() {
let empty_string = "";
}
```
The compiler will reject this code with:
```java
Error: --> main.leo:2:24
|
2 | let empty_string = "";
| ^^
|
= Cannot constrcut an empty string: it has the type of [char; 0] which is not possible.
```
As the error indicates, the type of `""`, the empty string, would be `[char; 0]`.
The type is not, as one might expect in languages like Rust or Java,
a `String` or `str`, where the size is statically unknown.
Rather, string literals in Leo are arrays of `char`s.
So given that `""` is an array type with size `0`,
the Leo compiler will reject the program, as it would have done with e.g...:
```js
function main() {
let empty: [u8; 0] = [];
}
```
## Solutions
You will not be able to use `""`, but all is not lost.
Depending on what you want to achieve in your program, there may be solutions.
For example, if you want to select between two strings,
you can pad the other strings with whitespace to represent emptiness.
```js
function main() {
let condition = false;
let a_or_empty = condition ? "a" : " ";
}
```
Here, `" "` represents the empty string but is of the same type as `"a"`.

View File

@ -0,0 +1,51 @@
# Empty array dimensions
## Example
This error occurs when specifying an empty tuple as the dimensions of an array.
Erroneous code example:
```js
function main() {
let foo = [42; ()];
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370023]: Array dimensions specified as a tuple cannot be empty.
--> test.leo:2:20
|
2 | let foo = [42; ()];
| ^^
```
## Solution
If you wanted a single dimensional array, you can achieve that by specifying the length like so:
```js
function main() {
let foo = [42; 4];
}
```
This will give you the array `[42, 42, 42, 42]`.
If instead you wanted a multi-dimensional array, e.g., a 2 x 3 matrix, you can achieve that with:
```js
function main() {
let foo = [42; (2, 3)];
}
```
Alternatively, you can use the simple syntax all the way instead:
```js
function main() {
let foo = [[42; 2]; 3];
}
```

View File

@ -0,0 +1,35 @@
# `@context function` is deprecated
## Example
This error occurs when a function is prefixed with `@context`.
Erroneous code example:
```js
@context()
function foo() {
// logic...
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370017]: "@context(...)" is deprecated. Did you mean @test annotation?
--> test.leo:1:2
|
1 | @context()
| ^^^^^^^
```
## Solution
The `@context function` syntax is deprecated, but you can use `@test function` instead:
```js
@test
function foo() {
// logic...
}
```

View File

@ -0,0 +1,44 @@
# Invalid address literal
## Example
This error occurs when a syntactically invalid address is specified.
Erroneous code example:
```js
function main() {
let addr = aleo1Qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370001]: invalid address literal: 'aleo1Qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9'
--> test.leo:2:16
|
2 | let addr = aleo1Qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
A valid address literal must start with `aleo1`,
followed by 58 characters any of which can be either a lowercase letter,
or an ASCII digit (`0` to `9`).
In the example above, the problem is `Q`, an uppercase letter,
and the second character after `aleo1`.
## Solution
To fix the issue, we can write...:
```js
function main() {
let addr = aleo1qnr4dkkvkgfqph0vzc3y6z2eu975wnpz2925ntjccd5cfqxtyu8s7pyjh9;
}
```
...and the compiler will accept it.
Note however that the compiler does not check whether the address is valid on-chain, but merely that the written program follows the rules of the language grammar.

View File

@ -0,0 +1,32 @@
# Invalid assignment target
## Example
This error currently occurs when a `static const` member or a member function
is used as the target of an assignment statement.
Erroneous code example:
```js
circuit Foo {
static const static_const: u8 = 0;
}
function main() {
Foo::static_const = 0;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370011]: invalid assignment target
--> test.leo:6:5
|
6 | Foo::static_const = 0;
| ^^^^^^^^^^^^^^^^^
```
It's not possible to assign to `static const` members or member functions,
so this is not allowed syntax.
The solution is likely to rethink your approach to the problem you are solving.

View File

@ -0,0 +1,53 @@
# An empty `import` list
## Example
This error occurs when no sub-packages
or items were specified in an import list.
Erroneous code example:
```js
import gardening.();
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370002]: Cannot import empty list
--> test.leo:1:18
|
1 | import gardening.();
| ^^
```
...as the compiler does not know what to import in `gardening`.
## Solutions
There are different solutions to this problems.
Here are 2 of them to consider.
### Comment out the `import`
If don't know yet what to import from `gardening`,
comment out the `import` like so:
```js
// import gardening.();
```
Later, you can come back and specify what to import like below.
You can also remove the `import` line entirely,
which will have the same effect.
### Specify items to `import`
If you know that you'd like to import, for example,
the functions `water_flowers` and `prune`,
you can specify them in the import list like so:
```js
import gardening.(water_flowers, prune);
```

View File

@ -0,0 +1,28 @@
# Invalid package name
## Example
This error occurs when a package name in an `import` contains invalid characters.
Erroneous code example:
```js
import FOO.bar;
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370012]: package names must be lowercase alphanumeric ascii with underscores
--> test.leo:1:8
|
1 | import FOO.bar;
| ^^^
```
In this specific case, you probably meant `foo.bar` instead.
If so, so you can solve the problem with:
```js
import foo.bar;
```

View File

@ -0,0 +1,33 @@
# `let mut` is deprecated
## Example
This error occurs when a variable declaration is marked with `mut`.
Erroneous code example:
```js
function main() {
let mut x = 0;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370015]: let mut = ... is deprecated. `let` keyword implies mutabality by default.
--> test.leo:2:5
|
2 | let mut x = 0;
| ^^^^^^^
```
## Solution
As the `mut` modifier is implicitly assumed, the solution is to remove the `mut` modifier:
```js
function main() {
let x = 0;
}
```

View File

@ -0,0 +1,37 @@
# `static const` after circuit functions
## Example
This error occurs when `static const` circuit members occur after circuit member functions.
Erroneous code example:
```js
circuit Foo {
function bar() {}
static const baz: bool = true;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370021]: Member functions must come after member consts.
--> test.leo:4:18
|
4 | static const baz: bool = true;
| ^^^^^^^^^^^^^^^^
```
## Solution
The issue can be solved by moving all `static const` members before circuit member functions...:
```js
circuit Foo {
static const baz: bool = true;
function bar() {}
}
```

View File

@ -0,0 +1,37 @@
# `static const` after normal variables
## Example
This error occurs when `static const` circuit members occur after normal member variables.
Erroneous code example:
```js
circuit Foo {
bar: u8,
static const baz: bool = true;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370020]: Member variables must come after member consts.
--> test.leo:4:18
|
4 | static const baz: bool = true;
| ^^^^^^^^^^^^^^^^
```
## Solution
The issue can be solved by moving all `static const` members before normal member variables...:
```js
circuit Foo {
static const baz: bool = true;
bar: u8,
}
```

View File

@ -0,0 +1,37 @@
# Member variables after after circuit functions
## Example
This error occurs when circuit member variables occur after circuit member functions.
Erroneous code example:
```js
circuit Foo {
function bar() {}
baz: bool;
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370022]: Member functions must come after member variables.
--> test.leo:4:5
|
4 | baz: bool;
| ^^^
```
## Solution
The issue can be solved by moving all member variables before any circuit member functions...:
```js
circuit Foo {
baz: bool;
function bar() {}
}
```

View File

@ -0,0 +1,48 @@
# Mixed commas and semicolons in circuit definitions
## Example
This error occurs when mixing semicolons, `;`,
and commas, `,` together in the list of member variables in a circuit definition.
Erroneous code example:
```js
circuit A {
foo: u8,
bar: u16;
}
```
The compiler will reject this code with:
```js
Error [EPAR0370006]: Cannot mix use of commas and semi-colons for circuit member variable declarations.
--> test.leo:3:13
|
3 | bar: u16;
| ^
```
## Solutions
The solution is simply to consistently use `;` or `,` after each member variable,
and avoid mixing `;` and `,` together. So we could write either...:
```js
circuit A {
foo: u8,
bar: u16,
}
```
...or write...:
```js
circuit A {
foo: u8;
bar: u16;
}
```
...and the compiler would accept it.

View File

@ -0,0 +1,37 @@
# Deprecated `mut` parameter
## Example
This error occurs when a function parameter is marked as `mut`.
Erroneous code example:
```js
circuit Foo {
function bar(mut x: u8) {
x = 0;
}
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370014]: function func(mut a: u32) { ... } is deprecated. Passed variables are mutable by default.
--> test.leo:2:18
|
2 | function bar(mut x: u8) {
| ^^^^^
```
## Solution
As the `mut` modifier is implicitly assumed, the solution is to remove the `mut` modifier:
```js
circuit Foo {
function bar(x: u8) {
x = 0;
}
}
```

View File

@ -0,0 +1,41 @@
# Deprecated `mut` parameter
## Example
This error occurs when a function parameter is marked as `mut`.
Erroneous code example:
```js
circuit Foo {
bar: u8,
function bar(mut self) {
self.bar = 0;
}
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370019]: `mut self` is no longer accepted. Use `&self` if you would like to pass in a mutable reference to `self`
--> test.leo:4:18
|
4 | function bar(mut self) {
| ^^^^^^^^
```
## Solution
As the `mut` modifier is implicitly assumed, the solution is to remove the `mut` modifier from `self`:
```js
circuit Foo {
bar: u8,
function bar(self) {
self.bar = 0;
}
}
```

View File

@ -0,0 +1,43 @@
# Illegal spread expression in array initializer
## Example
This error occurs when a spread expression, e.g., `...foo` occurs in an array initializer.
Erroneous code example:
```js
function main() {
let foo = [0, 1];
let array = [...foo; 3];
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370010]: illegal spread in array initializer
--> test.leo:3:17
|
3 | let array = [...foo; 3];
| ^^^^^^^
```
## Solution
The Leo language does not allow `...foo` as the element to repeat
in an array repeat expression like the one above.
This is because `foo` is not an element but rather a full array.
One could imagine that the expression above means `[...foo, ...foo, ...foo]`.
That is, `...foo` repeated as many times as was specified in the array size.
However, that is ambiguous with `[element; 3]` resulting in an array with size `3`.
To solve the issue, disambiguate your intention.
Most likely, you really wanted `[...foo, ...foo, ...foo]`, so the solution is to write that out...:
```js
function main() {
let foo = [0, 1];
let array = [...foo, ...foo, ...foo];
}
```

View File

@ -0,0 +1,34 @@
# `test function` is deprecated
## Example
This error occurs when a function is prefixed with `test`.
Erroneous code example:
```js
test function foo() {
// logic...
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370016]: "test function..." is deprecated. Did you mean @test annotation?
--> test.leo:1:1
|
1 | test function foo() {
| ^^^^
```
## Solution
The `test function` syntax is deprecated, but you can achieve the same result with `@test function`:
```js
@test
function foo() {
// logic...
}
```

View File

@ -0,0 +1,34 @@
# Unable to parse array dimensions
## Example
This error occurs when there is a syntax error in the array dimensions of an array initializer.
Erroneous code example:
```js
function main() {
let x = [1; +];
}
```
The compiler will reject this code with, for example...:
```js
Error [EPAR0370018]: unable to parse array dimensions
--> test.leo:2:13
|
2 | let x = [1; +];
| ^
```
## Solution
In the case above, the error occurs due to the `+`.
The issue can be resolved by specifying the number of elements desired, e.g., `5`...:
```js
function main() {
let x = [1; 5];
}
```

View File

@ -0,0 +1,37 @@
# Expected "x" -- got "y"
## Example
This error occurs when a specific token, e.g., `class` was encountered but a different one,
e.g., `circuit` was expected instead.
Erroneous code example:
```js
class A {}
```
The compiler will reject this code with:
```js
Error: --> main.leo:1:1
|
1 | class A {}
| ^^^^^
|
= expected 'import', 'circuit', 'function', 'test', '@' -- got 'class'
```
## Solutions
The error message above says that `class` cannot be used at that location,
and also lists a few tokens that are valid. Note that this is context specific,
and depends on what tokens preceded the current token.
Using the list of tokens that are valid, and knowing that `circuit A {}` is valid syntax,
we replace `class` with `circuit`...:
```js
circuit A {}
```
...and the error is now resolved.

View File

@ -0,0 +1,49 @@
# An unexpected end of file
## Example
This error occurs when the Leo compiler tries to parse your program
and unexpectedly reaches the end of a `.leo` file.
Erroneous code example:
```js
function main() {
```
The compiler will reject this code with:
```js
Error [EPAR0370003]: unexpected EOF
--> test.leo:1:17
|
1 | function main() {
| ^
```
## Solutions
The problem typically occurs when there are unbalanced delimiters,
which we have an instance of above.
More specifically, in the example,
the issue is that there is no `}` to close the opening brace `{`.
An even simpler variant of this is:
```js
function main(
```
The solution here is to close the opening delimiter, in this case `(`.
## The general issue
To illustrate the heart of the problem, consider this invalid file:
```js
// ↳ main.leo
function
```
When parsing the file, the compiler expects something, in this case,
the function's name, but instead, the parser reaches the end of the file.

View File

@ -0,0 +1,42 @@
# Unexpected identifier: expected "x" -- got "y"
## Example
This error occurs when a specific *identifier*, e.g., `error` was expected but a different one,
e.g., `fail` was encountered instead.
Erroneous code example:
```js
function main() {
console.fail("Huston we have a problem!");
}
```
The compiler will reject this code with:
```js
Error [EPAR0370007]: unexpected identifier: expected 'assert', 'error', 'log' -- got 'fail'
--> test.leo:2:11
|
2 | console.fail("Huston we have a problem!");
| ^^^^
```
## Solutions
The error message above says that `fail` cannot be used at that location,
and also lists a few identifiers that are valid. Note that this is context specific,
and depends on what preceded the valid tokens in the location.
The error message lists identifiers that are valid, e.g., `error`.
Here, since we used `.fail(...)`, we most likely wanted to trigger a compile error,
which `.error(...)` will achieve, so we use that instead...:
```js
function main() {
console.error("Huston we have a problem!");
}
```
Note that this error currently only occurs when using `console`.

View File

@ -0,0 +1,42 @@
# Unexpected statement: expected "x" -- got "y"
## Example
This error occurs when a statement, which isn't `if`, follows `else` directly.
Erroneous code example:
```js
function main () {
if true {
console.log("It was true.");
} else
console.log("It was false.");
}
```
The compiler will reject this code with:
```js
Error [EPAR0370008]: unexpected statement: expected 'Block or Conditional', got 'console.log("It was false.", );'
--> test.leo:5:9
|
5 | console.log("It was false.");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
```
## Solutions
To fix the problem, wrap the statement in a block, so by turning the snippet above into...:
```js
function main () {
if true {
console.log("It was true.");
} else {
console.log("It was false.");
}
}
```
...the error is fixed.

View File

@ -0,0 +1,36 @@
# Expected string "x" -- got "y"
## Example
This error occurs when a specific "string" (in reality a token),
was expected but a different one was expected instead.
Erroneous code example:
```js
function main () {
let x: [u8; (!)] = [0];
}
```
The compiler will reject this code with:
```js
Error [EPAR0370009]: unexpected string: expected 'int', got '!'
--> test.leo:2:18
|
2 | let x: [u8; (!)] = [0];
| ^
```
## Solutions
The error message "unexpected string" depends on the context.
In the example above, we need to replace `!` with `1`...:
```js
function main () {
let x: [u8; 1] = [0];
}
```

View File

@ -0,0 +1,40 @@
# An unexpected token
## Example
This error occurs when the Leo compiler tries to parse your program.
More specifically, during a phase called 'lexing'.
In this phase, the compiler first takes your code,
consisting of characters, and interprets it as a list of tokens.
These tokens are a sort of *alphabet* internal to Leo.
Consider the English language. It only has 26 letters in its alphabet.
So there are some letters, e.g., `Γ` from the greek alphabet,
which would not fit if we tried to "tokenize" English.
Leo, while being a programming language, is similar here.
There are characters or sequences of characters,
that Leo does not understand and cannot lex into tokens.
Since this error occured, that is what has happened.
Erroneous code example:
```js
~
```
The compiler will reject this code with:
```js
Error [EPAR0370000]: ~
--> test.leo:1:1
|
1 | ~
| ^
```
## Solutions
What the solution to an unexpected token is depends on what you wanted to achieve.
Most likely, you made a typo somewhere.
For a more complete overview of valid Leo tokens, consult the Leo grammar.

View File

@ -0,0 +1,34 @@
# Unexpected whitespace
## Example
This error occurs when there was unexpected white space when in your program.
Typically, the white space occurs in a literal with a typed suffix.
Erroneous code example:
```js
function main() {
let x = 1 u8;
}
```
The compiler will reject this code with:
```js
Error [EPAR0370004]: Unexpected white space between terms 1 and u8
--> test.leo:2:13
|
2 | let x = 1 u8;
| ^
```
## Solutions
The problem is solved by removing the white space between the literal and its suffix. So given the example above, we can fix it by writing:
```js
function main() {
let x = 1u8;
}
```