From e3ef4fda97f51095b89175e616a325bea32d83d9 Mon Sep 17 00:00:00 2001 From: Per Lindgren <per.lindgren@ltu.se> Date: Sun, 20 Sep 2020 20:08:01 +0200 Subject: [PATCH] some readme updates --- examples/syntax.rs | 17 ++++++++++++++++- examples/syntax4.rs | 7 +++++++ src/ast/README.md | 7 +++++-- src/ast/main.rs | 5 +++++ src/ast/parser.lalrpop | 5 +---- 5 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 examples/syntax4.rs diff --git a/examples/syntax.rs b/examples/syntax.rs index f328e4d..7aa9378 100644 --- a/examples/syntax.rs +++ b/examples/syntax.rs @@ -1 +1,16 @@ -fn main() {} +fn main() { + let a = false; + + let a = { + let b = 1 + 1; + // extra `;` are allowed + if a {} // no trialing `;` + b // return value + }; + + while false { + // do something here + } + + let _b = if a < 5 { 1 } else { 2 }; +} diff --git a/examples/syntax4.rs b/examples/syntax4.rs new file mode 100644 index 0000000..938345d --- /dev/null +++ b/examples/syntax4.rs @@ -0,0 +1,7 @@ +fn a(a: i32, mut b: bool) { + let a = 5; + + while b {} +} + +fn main() {} diff --git a/src/ast/README.md b/src/ast/README.md index 7820fae..0796d86 100644 --- a/src/ast/README.md +++ b/src/ast/README.md @@ -22,12 +22,13 @@ 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. Notice, Rust allows allow assignment to refer to the result of an `if then else` construct. +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. Inside a *block*, statements are typically separated by `;`, with the following exceptions. - `if` statements, and -- `while` statements may omit the trailing `;`. +- `while` statements may omit the trailing `;`, and +- `{ ... }` inner blocks. Additionally Rust allows for additional `;` in between statements (but extra `;` are considered non-idiomatic and thus removed by `rustfmt`). @@ -39,6 +40,8 @@ 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. + - 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. 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`). diff --git a/src/ast/main.rs b/src/ast/main.rs index c5c7a4a..cd28e11 100644 --- a/src/ast/main.rs +++ b/src/ast/main.rs @@ -37,3 +37,8 @@ fn syntax2() { fn syntax3() { parse("examples/syntax3.rs"); } + +#[test] +fn syntax4() { + parse("examples/syntax4.rs"); +} diff --git a/src/ast/parser.lalrpop b/src/ast/parser.lalrpop index d011793..cdbf819 100644 --- a/src/ast/parser.lalrpop +++ b/src/ast/parser.lalrpop @@ -54,8 +54,7 @@ Type:() = { } Block: () = { - "{" StmtSeq* "}", - "{" StmtSeq* Stmt "}", + "{" StmtSeq* Stmt? "}", } StmtSeq: () = { @@ -131,8 +130,6 @@ UnaryOp: () = { "&" "mut", } - - Num: i32 = { r"[0-9]+" => i32::from_str(<>).unwrap(), }; -- GitLab