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

readme now includes grammar snippets

parent 001c4984
No related branches found
No related tags found
No related merge requests found
...@@ -52,7 +52,7 @@ The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, suf ...@@ -52,7 +52,7 @@ The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, suf
Some interesting design decisions: 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 ``` Rust
Block: () = { Block: () = {
...@@ -80,12 +80,43 @@ Stmt: () = { ...@@ -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.) - 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). - `;` 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. 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.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment