Skip to content
Snippets Groups Projects
Commit 4596e47a authored by Per Lindgren's avatar Per Lindgren
Browse files

added mut and updated text

parent 7ed8e17f
No related branches found
No related tags found
No related merge requests found
...@@ -22,14 +22,16 @@ fn main() { ...@@ -22,14 +22,16 @@ fn main() {
} }
``` ```
At the top level, we have a *block* (sequence of statements). We also see, that the `let` statement accepts a *block* of statements as part of an assignment. Inside a *block*, statements are typically separated by `;`, with the following exceptions. At the top level, we have 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.
Inside a *block*, statements are typically separated by `;`, with the following exceptions.
- `if` statements, and - `if` statements, and
- `while` statements may omit the trailing `;`. - `while` statements may omit the trailing `;`.
Additionally Rust allows for additional `;` in between statements (but extra `;` are considered non-idiomatic and thus removed by `rustfmt`). Additionally Rust allows for additional `;` in between statements (but extra `;` are considered non-idiomatic and thus removed by `rustfmt`).
Omitting trailing `;` for the last statement in a block renders an implicit return. This is allowed by the Rust compiler in case the statement can be interpreted as an expression. Omitting trailing `;` for the last statement in a *block* renders an implicit return. This is allowed by the Rust compiler in case the statement can be interpreted as an expression.
## An example grammar ## An example grammar
...@@ -37,12 +39,14 @@ The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, suf ...@@ -37,12 +39,14 @@ The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, suf
Some interesting design decisions: Some interesting design decisions:
- We treat statements that may be considered as expressions by a special rule `ExprStmt`, where we accept either `if then else` or a `block`. (This is where we likely add `match` and similar statements later.) - 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.)
Recall that a statement can be a return value, thus must somehow accept an expression. A `if then else` statement is one such possible expression. Now, here is the crux, without the Recall that a statement can be a return value, thus must somehow accept an expression. Now, here is the crux, since we want `if then else` and `blocks` (statements) to be treated as expression for assignments, it would cause ambiguities between statements as part of an expression or inside a *block*. We can resolve this by the adopting `ExprNoBlock`, inside of `stmt`. `ExprNoBlock` accepts expression besides those that are matched by `ExprBlock` (`if then else` and `block`).
- `;` is treated as a `stmt`, hence we accept *blocks* like `{; let a = 5;;;;; let b = 6;;; c}`. Notice, `;` carries no meaning besides for the optional trailing `;` of a *block* (determining the return type).
- `"let" ExprNoBlock "=" Expr ";"`, forces a trailing `;` to each assignment (along the lines of the behavior of the Rust compiler).
## Reflection
- `;` is treated as a `stmt`, hence we allow *blocks* like `{; let a=5; let b=6;;;;;}` The Rust syntax seems somewhat arbitrarily chosen. The requirement that `let` statements must be trailed by `;`, is to my best understanding not required for soundness (the `let` could have been given a `Unit` type, similar to an assignment). This leads me to believe that the trailing `;` is rather an enforcement of style.
- "let" Id "=" Expr ";"
...@@ -15,7 +15,7 @@ match { ...@@ -15,7 +15,7 @@ match {
} }
pub Function: () = { pub Function: () = {
"fn" Id Params ("->" Type)? Stmts => (), "fn" Id Params ("->" Type)? Block => (),
} }
pub Params: () = { pub Params: () = {
...@@ -33,29 +33,30 @@ pub Type:() = { ...@@ -33,29 +33,30 @@ pub Type:() = {
"()" => (), "()" => (),
} }
pub Stmts: () = { pub Block: () = {
"{" Stmt* "}" => (), "{" Stmt* "}" => (),
} }
pub ExprStmt: () = {
"if" Expr Stmts "else" Stmts => (),
Stmts => (),
}
pub Stmt: () = { pub Stmt: () = {
";" => (), ";" => (),
"let" Id "=" Expr ";" => (), "let" "mut"? Id "=" Expr ";" => (),
ExprNoBlock "=" Expr => (), ExprNoBlock "=" Expr => (),
"if" Expr Stmts ("else" Stmts)? => (), "while" Expr Block => (),
"if" Expr Block ("else" Block)? => (),
ExprNoBlock => (), ExprNoBlock => (),
Stmts => (), Block => (),
} }
pub Expr: () = { pub Expr: () = {
ExprStmt => (), ExprBlock => (),
ExprNoBlock => (), ExprNoBlock => (),
} }
pub ExprBlock: () = {
"if" Expr Block "else" Block => (),
Block => (),
}
pub ExprNoBlock: () = { pub ExprNoBlock: () = {
ExprNoBlock Cmp Expr1 => (), ExprNoBlock Cmp Expr1 => (),
Expr1 => (), Expr1 => (),
...@@ -91,9 +92,6 @@ pub Term: () = { ...@@ -91,9 +92,6 @@ pub Term: () = {
"(" Expr ")" => (), "(" Expr ")" => (),
} }
pub Num: i32 = { pub Num: i32 = {
r"[0-9]+" => i32::from_str(<>).unwrap(), r"[0-9]+" => i32::from_str(<>).unwrap(),
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment