diff --git a/examples/if.rs b/examples/if.rs
deleted file mode 100644
index 8bda63162c5aaa6613801468a47b3a458e88956a..0000000000000000000000000000000000000000
--- a/examples/if.rs
+++ /dev/null
@@ -1,6 +0,0 @@
-fn main() {
-    let a = {
-        let b = 1;
-        b
-    };
-}
diff --git a/examples/syntax.rs b/examples/syntax.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5b2d45f2eab9e88388db36594fec92792b68d1a6
--- /dev/null
+++ b/examples/syntax.rs
@@ -0,0 +1,15 @@
+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/src/ast/README.md b/src/ast/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5416404cf277e047192ebf7d8bff8ccdbd33612c
--- /dev/null
+++ b/src/ast/README.md
@@ -0,0 +1,48 @@
+# Rust Syntax
+
+As it turns out Rust syntax is a bit tricky to parse.
+
+Consider the following program (`examples/syntax.rs`):
+
+``` Rust
+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 };
+}
+```
+
+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.
+
+- `if` statements, and
+- `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`).
+
+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
+
+The example grammar in `ast/parser.lalrpop` covers a minimal subset of Rust, sufficient to parse the given `syntax.rs` example. Each action merely produces a unit result (no AST is built).
+
+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.)
+
+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  
+
+
+
+- `;` is treated as a `stmt`, hence we allow *blocks* like `{; let a=5; let b=6;;;;;}` 
+-  "let" Id "=" Expr ";" 
+
diff --git a/src/ast/main.rs b/src/ast/main.rs
index 3e05258d76b8c6703911db9d9771e2067fa79561..7e980d3706aff5b1ca34ce5ef18edcb9ed2b881e 100644
--- a/src/ast/main.rs
+++ b/src/ast/main.rs
@@ -19,23 +19,12 @@ pub fn read(file_name: &str) -> std::io::Result<String> {
     Ok(contents)
 }
 
-// pub fn parse(file_name: &str) -> Program {
-//     let p = read(file_name).expect("File not found");
-//     ProgramParser::new().parse(&p).unwrap()
-// }
+pub fn parse(file_name: &str) {
+    let p = read(file_name).expect("File not found");
+    FunctionParser::new().parse(&p).unwrap()
+}
 
 #[test]
-fn t1() {
-    let s = "
-    {
-        let a = {
-            let b = 1 + 1;
-            ;
-            if a { }
-
-            b
-        }
-    }
-    ";
-    StmtsParser::new().parse(s).unwrap();
+fn syntax() {
+    parse("examples/syntax3.rs");
 }
diff --git a/src/ast/parser.lalrpop b/src/ast/parser.lalrpop
index 2688e4aae7b764e33bff25995c07f90a8873cc92..4d5db9b75c3a227fc29bdfa0c3a882467ff5a761 100644
--- a/src/ast/parser.lalrpop
+++ b/src/ast/parser.lalrpop
@@ -14,15 +14,60 @@ match {
     _
 }
 
-//pub Expr: () 
+pub Function: () = {
+    "fn" Id Params ("->" Type)? Stmts => (),
+}
+
+pub Params: () = {
+    "()" => (), // seems like a haxx
+    "(" ((Param ",")* Param)? ")" => (),
+}
+
+pub Param:() = {
+    Id ":" Type,
+}
+
+pub Type:() = {
+    "i32" => (),
+    "bool" => (),
+    "()" => (),
+}
+
+pub Stmts: () = {
+    "{" Stmt* "}" => (),
+}
+
+pub ExprStmt: () = {
+    "if" Expr Stmts "else" Stmts => (),
+    Stmts => (),
+}
+
+pub Stmt: () = {
+    ";" => (),
+    "let" Id "=" Expr ";" => (),
+    ExprNoBlock "=" Expr => (),
+    "if" Expr Stmts ("else" Stmts)? => (),
+    ExprNoBlock => (),
+    Stmts => (),
+}
+
 pub Expr: () = {
     ExprStmt => (),
     ExprNoBlock => (),    
 }
 
 pub ExprNoBlock: () = {
-    Expr AddSub Factor => (),
-    Factor => (),
+    ExprNoBlock Cmp Expr1 => (),
+    Expr1 => (),
+}
+
+pub Cmp: () = {
+    "<" => ()
+}
+
+pub Expr1: () = {
+    Expr1 AddSub Expr2 => (),
+    Expr2 => (),
 }
 
 pub AddSub: () = {
@@ -30,8 +75,8 @@ pub AddSub: () = {
     "-" => (),
 }
 
-pub Factor: () = {
-    Factor MulDiv Term => (),
+pub Expr2: () = {
+    Expr2 MulDiv Term => (),
     Term => (),
 }
 
@@ -43,33 +88,16 @@ pub MulDiv: () = {
 pub Term: () = {
     Id => (),
     Num => (),
+    "(" Expr ")" => (),
 }
 
 
 
 
-pub ExprStmt: () = {
-    "if" Expr Stmts "else" Stmts => (),
-    Stmts => (),
-}
-
-pub Stmts: () = {
-    "{" Stmt* "}" => (),
-}
-
-pub Stmt: () = {
-    ";" => (),
-    "let" Id "=" Expr => (),
-    "if" Expr Stmts ("else" Stmts)? => (),
-    ExprNoBlock => (),
-    Stmts => (),
-}
-
-
 pub Num: i32 = {
     r"[0-9]+" => i32::from_str(<>).unwrap(),
 };
 
 pub Id: String = {
-    r"([a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*" => String::from_str(<>).unwrap(),
+    r"(_|[a-z]|[A-Z])([a-z]|[A-Z]|[0-9]|_)*" => String::from_str(<>).unwrap(),
 };
\ No newline at end of file