From cd6055e145b7f909aac565decf62d8f0768a1769 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Mon, 21 Sep 2020 13:33:04 +0200
Subject: [PATCH] readme now includes grammar snippets

---
 src/ast/README.md | 39 +++++++++++++++++++++++++++++++++++----
 1 file changed, 35 insertions(+), 4 deletions(-)

diff --git a/src/ast/README.md b/src/ast/README.md
index c2504b0..b0cbc61 100644
--- a/src/ast/README.md
+++ b/src/ast/README.md
@@ -52,7 +52,7 @@ 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. `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`.
+- 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` (which is essentially plain expressions, free of block constructs as further discussed below.)
 
 ``` Rust
 Block: () = {
@@ -80,12 +80,43 @@ Stmt: () = {
 
 - 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`).
+  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 `block` (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
+``` Rust
+Expr: () = {
+    ExprBlock,
+    ExprNoBlock,    
+}
+
+ExprBlock: () = {
+    "if" ExprNoBlock Block "else" Block,
+    Block,
+}
+
+// Lowest Precedence
+ExprNoBlock = Tier2<AndOrOp, AndOr>; 
+AndOr = Tier2<ComparisonOp, AddSub>;
+AddSub = Tier2<AddSubOp, MulDiv>;
+MulDiv = Tier2<MulDivOp, Unary>;
+Unary = Tier1<UnaryOp, Term>;
+
+// Highest Precedence
+Term: () = {
+    Id,
+    Num,
+    Id "(" CommaNoTrail<Expr> ")",    
+    "(" Expr ")",
+}
+...
+```
+
+- `Expr` accepts both `ExprBlock` (statements with return value), and plain plain expressions (`ExprNoBlock`).
+
+- Precedences go from low to high, with `Term` having the highest precedence (matched first in a bottom up (LR) parser).
+
+## Reflection on the Rust syntax
 
 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.
 
-- 
GitLab