@@ -6,29 +6,41 @@ Consider the following program (`examples/syntax.rs`):
``` Rust
fn main() {
let a = false;
let a = false; // trailing `;`
// extra `;` are allowed in between statements
// (1)
let a = {
let b = 1 + 1;
// extra `;` are allowed
// (2)
if a {} // no trialing `;`
b // return value
b // no trialing `;`, return value
};
// (3)
while false {
// do something here
} // no trailing `;`
// (4)
{
// local block/scope
}
// (5)
let _b = if a < 5 { 1 } else { 2 };
}
```
The *body* of a function is a *block* (sequence of statements). We also see, that the `let` statement accepts a *block* of statements as part of an assignment. Notice, Rust allows allow assignment to refer to the result of an `if then else` construct. As shown in the at the end.
The *body* of a function is a *block* (sequence of statements). The `let` statement accepts a *block* of statements as part of an assignment (1). Rust allows *blocks* to introduce local scopes (4). Rust allows allow assignment to refer to the result of an `if then else` construct (5).
Inside a *block*, statements are typically separated by `;`, with the following exceptions.
-`if` statements, and
-`while` statements may omit the trailing `;`, and
-`{ ... }` inner blocks.
-`if` statements (2),
-`while` statements (3), and
-`{ ... }` inner blocks (4).
Additionally Rust allows for additional `;` in between statements (but extra `;` are considered non-idiomatic and thus removed by `rustfmt`).
...
...
@@ -40,7 +52,31 @@ The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, suf
Some interesting design decisions:
- A *block* of statements is sequence of `;` separated statements followed by an optional trailing statement.
- A *block* of statements is sequence of `;` separated statements followed by an optional trailing statement. `Block` accepts a sequence of statements `StmtSeq*` followed by an optional trailing `Stmt`. `StmtSeq` is either a `Stmt``;`, or a `StmtBlock`, where the latter cover the case of `while`, `if` and `Block` (nesting/scopes) (without requiring `;` delimiting). We also see that `Stmt` accepts additional `;`. `Stmt` also accepts `ExprNoBlock`.
``` Rust
Block: () = {
"{" StmtSeq* Stmt? "}",
}
StmtSeq: () = {
Stmt ";",
StmtBlock,
}
StmtBlock: () = {
"while" Expr Block,
"if" Expr Block ("else" Block)?,
Block,
}
Stmt: () = {
";",
"let" "mut"? Id (":" Type)? "=" Expr,
ExprNoBlock "=" Expr,
ExprNoBlock,
}
```
- We treat statements that may be considered as expressions by a special rule `ExprBlock`, where we accept either `if then else` or a `block` (statments). (This is where we likely add `match` and similar statements later.)