From eabfc31bfbb7ce761909c7815a087b5fc10bfc99 Mon Sep 17 00:00:00 2001
From: Per Lindgren <per.lindgren@ltu.se>
Date: Tue, 15 Sep 2020 00:22:45 +0200
Subject: [PATCH] epic fail

---
 src/ast/ast.rs         |  26 --------
 src/ast/main.rs        | 137 ++---------------------------------------
 src/ast/parser.lalrpop |  39 ++++++++++--
 3 files changed, 40 insertions(+), 162 deletions(-)

diff --git a/src/ast/ast.rs b/src/ast/ast.rs
index 9daa62a..b750a43 100644
--- a/src/ast/ast.rs
+++ b/src/ast/ast.rs
@@ -3,29 +3,3 @@ use std::fmt;
 // ast
 
 pub type Id = String;
-
-// println!("{:?}", ..)
-#[derive(Debug, Clone)]
-pub enum NumOrId {
-    Num(i32),
-    Id(Id),
-}
-
-// println!("{}", ..)
-impl fmt::Display for NumOrId {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self {
-            NumOrId::Num(i) => write!(f, "{}", i)?,
-            NumOrId::Id(s) => write!(f, "{}", s)?,
-        };
-        Ok(())
-    }
-}
-
-pub type Stmts = Vec<Stmt>;
-
-#[derive(Debug, Clone)]
-pub enum Stmt {
-    Let(Id, NumOrId),
-    If(Id, Stmts, Option<Stmts>),
-}
diff --git a/src/ast/main.rs b/src/ast/main.rs
index 08deadd..0eb05e3 100644
--- a/src/ast/main.rs
+++ b/src/ast/main.rs
@@ -8,137 +8,12 @@ pub mod ast;
 use ast::*;
 
 fn main() {
-    println!("minimal");
-    println!("{:?}", NumOrIdParser::new().parse("123"));
-    println!("{:?}", NumOrIdParser::new().parse("a1_a"));
-
-    println!("{}", NumOrIdParser::new().parse("123").unwrap());
-    println!("{}", NumOrIdParser::new().parse("a1_a").unwrap());
-}
-
-#[test]
-fn parse_num_or_id() {
-    assert_eq!(
-        format!("{}", NumOrIdParser::new().parse("123").unwrap()),
-        "123"
-    );
-    assert_eq!(
-        format!("{}", NumOrIdParser::new().parse("a1_a").unwrap()),
-        "a1_a"
-    );
-}
-
-type Error = String;
-
-fn type_check(stmts: &Stmts) -> Result<Id, Error> {
-    let mut last_id = "".to_string();
-    let mut err: Option<Stmt> = None;
-    stmts.iter().for_each(|stmt| match stmt {
-        Stmt::Let(id, _) => {
-            println!("let {} ...", id);
-            last_id = id.to_string();
-        }
-        Stmt::If(_, _, __) => {
-            println!("if has an error");
-            err = Some(stmt.clone());
-        }
-    });
-    println!("here we can do something before returning");
-    match err {
-        Some(stmt) => Err(format!("error found in statement {:?}", stmt)),
-        None => Ok(last_id),
-    }
-}
-// the above is not ideal, since we have to do a lot of book keeping,
-// also we cannot easily "abort", and thus we cont. even after spotting the error we want to return
-
-fn type_check2(stmts: &Stmts) -> Result<Id, Error> {
-    let mut last_id = "".to_string();
-    let res: Result<Id, Error> = stmts
-        .iter()
-        .try_for_each(|stmt| match stmt {
-            Stmt::Let(id, _) => {
-                println!("let {} ...", id);
-                last_id = id.to_string();
-                Ok(())
-            }
-            Stmt::If(_, _, __) => {
-                println!("if has an error");
-                Err(format!("error found in statement {:?}", stmt))
-            }
-        })
-        .map(|_| Ok(last_id))?;
-    println!("here we can do something before returning");
-    res
-}
-// this is quite good, we can get rid of some book keeping, and we iterate only up to the point where an error occurs.
-// we have to convert the Ok(()) into the last Id (using Result::map)
-// IMHO Result::map should have been named map_ok, since that is what is does, and symmetric to map_err.
-
-fn type_check3(stmts: &Stmts) -> Result<Id, Error> {
-    let res = stmts.iter().try_fold("".to_string(), |_, stmt| match stmt {
-        Stmt::Let(id, _) => {
-            println!("let {} ...", id);
-            Ok(id.to_string())
-        }
-        Stmt::If(_, _, __) => {
-            println!("if has an error");
-            Err(format!("error found in statement {:?}", stmt))
+    let s = "
+        {
+            let ;
+            ;
         }
-    });
-
-    println!("here we can do something before returning");
-    res
-}
-// this is likely as good as it gets using Rust.
-// the `try_fold`, aborts on an error directly.
-// we need to give an initial value for the accumulator ("".to_string())
-// in this case we don't accumulate, so the first closure parameter is discarded (`_`)
-// instead we just overwrite the accumatore with the latest seen identifier.
-
-fn type_check4(stmts: &Stmts) -> Result<Id, Error> {
-    let res = stmts
-        .iter()
-        .try_fold("".to_string(), |_, stmt| match stmt {
-            Stmt::Let(id, _) => {
-                println!("let {} ...", id);
-                Ok(id.to_string())
-            }
-            Stmt::If(_, _, __) => {
-                println!("if has an error");
-                Err(format!("error found in statement {:?}", stmt))
-            }
-        })?;
-
-    println!("here we can do something before returning");
-    Ok(res)
-}
-// A slight alternation av type_check3, here we make an early return
-// Notice that the type of `res` has changed.
-
-#[test]
-fn test_stmts() {
-    let stmts = vec![
-        Stmt::Let("a".to_string(), NumOrId::Num(1)),
-        Stmt::Let("b".to_string(), NumOrId::Num(2)),
-        Stmt::If("b".to_string(), Stmts::new(), None),
-        Stmt::Let("c".to_string(), NumOrId::Num(3)),
-    ];
-    println!("type_check {:?}", type_check(&stmts));
-    println!("type_check2 {:?}", type_check2(&stmts));
-    println!("type_check3 {:?}", type_check3(&stmts));
-    println!("type_check4 {:?}", type_check4(&stmts));
-}
+    ";
 
-#[test]
-fn test_stmts_without_error() {
-    let stmts = vec![
-        Stmt::Let("a".to_string(), NumOrId::Num(1)),
-        Stmt::Let("b".to_string(), NumOrId::Num(2)),
-        Stmt::Let("c".to_string(), NumOrId::Num(3)),
-    ];
-    println!("type_check {:?}", type_check(&stmts));
-    println!("type_check2 {:?}", type_check2(&stmts));
-    println!("type_check3 {:?}", type_check3(&stmts));
-    println!("type_check4 {:?}", type_check4(&stmts));
+    println!("{:?}", BlockExpressionParser::new().parse(s));
 }
diff --git a/src/ast/parser.lalrpop b/src/ast/parser.lalrpop
index 3405c21..95085a6 100644
--- a/src/ast/parser.lalrpop
+++ b/src/ast/parser.lalrpop
@@ -4,15 +4,44 @@ use crate::ast::*;
 
 grammar;
 
-pub NumOrId: NumOrId = {
-    Num => NumOrId::Num(<>),
-    Id => NumOrId::Id(<>),
+pub ExpressionWithoutBlock: () = {
+    LiteralExpression => ()
 }
- 
+
+pub LiteralExpression = {
+    Num
+    Id
+}
+
+ExpressionWithBlock: () = {
+    BlockExpression => ()
+}
+
+pub BlockExpression: ()= {
+    "{" Statements? "}" => ()
+}
+
+pub Statements: () = {
+    Statement+ => (),
+    Statement+ ExpressionWithoutBlock => (),
+    ExpressionWithBlock => ()
+}
+
+pub Statement: () = {
+    ";" => (),
+    "let" ";" => (),
+    ExpressionStatement => ()
+}
+
+pub ExpressionStatement: () = {
+    ExpressionWithoutBlock ";" => (),
+    ExpressionWithBlock ";"? => ()
+}
+
 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(),
-};
+};
\ No newline at end of file
-- 
GitLab