From 87141fcca3daa8efd72bec061a747cf9098bb1f7 Mon Sep 17 00:00:00 2001 From: Greg Shuflin Date: Fri, 5 Nov 2021 12:52:41 -0700 Subject: [PATCH] for expressions --- schala-lang/language/src/ast/mod.rs | 2 +- schala-lang/language/src/parsing/new.rs | 30 ++++++++++++++++++++++-- schala-lang/language/src/parsing/test.rs | 7 +++--- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/schala-lang/language/src/ast/mod.rs b/schala-lang/language/src/ast/mod.rs index 870fa58..90dcb54 100644 --- a/schala-lang/language/src/ast/mod.rs +++ b/schala-lang/language/src/ast/mod.rs @@ -262,7 +262,7 @@ pub enum PatternLiteral { #[derive(Debug, PartialEq, Clone)] pub struct Enumerator { - pub id: Rc, + pub id: Rc, //TODO rename this field pub generator: Expression, } diff --git a/schala-lang/language/src/parsing/new.rs b/schala-lang/language/src/parsing/new.rs index 7c02a03..32bf1e4 100644 --- a/schala-lang/language/src/parsing/new.rs +++ b/schala-lang/language/src/parsing/new.rs @@ -12,7 +12,7 @@ peg::parser! { pub rule program() -> AST = n:(statement() ** delimiter() ) { AST { id: Default::default(), statements: n.into() } } - rule delimiter() = ";" / "\n" + rule delimiter() = (";" / "\n")+ rule statement() -> Statement = _ expr:expression() { Statement { @@ -24,6 +24,9 @@ peg::parser! { pub rule expression() -> Expression = _ kind:expression_kind() { Expression { id: Default::default(), type_anno: None, kind: kind } } + pub rule expression_no_struct() -> Expression = + _ kind:expression_kind_no_struct() { Expression { id: Default::default(), type_anno: None, kind: kind } } + rule expression_kind() -> ExpressionKind = precedence_expr(true) @@ -123,11 +126,34 @@ peg::parser! { rule primary(struct_ok: bool) -> ExpressionKind = - while_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / + while_expr() / for_expr() / float_literal() / nat_literal() / bool_literal() / string_literal() / paren_expr() / list_expr() / if_expr() / item:named_struct() {? if struct_ok { Ok(item) } else { Err("no-struct-allowed") } } / identifier_expr() + rule for_expr() -> ExpressionKind = + "for" _ enumerators:for_enumerators() _ body:for_body() { + ExpressionKind::ForExpression { enumerators, body } + } + + rule for_enumerators() -> Vec = + "{" _ enumerators:(enumerator() ++ ",") _ "}" { enumerators } / + enumerator:enumerator() { vec![enumerator] } + + //TODO add guards, etc. + rule enumerator() -> Enumerator = + ident:identifier() _ "<-" _ generator:expression_no_struct() { + Enumerator { id: Rc::new(ident.to_string()), generator } + } / + //TODO need to distinguish these two cases in AST + ident:identifier() _ "=" _ generator:expression_no_struct() { + Enumerator { id: Rc::new(ident.to_string()), generator } + } + + rule for_body() -> Box = + "return" _ expr:expression() { Box::new(ForBody::MonadicReturn(expr)) } / + body:block() { Box::new(ForBody::StatementBlock(body)) } + rule while_expr() -> ExpressionKind = "while" _ cond:expression_kind_no_struct()? _ body:block() { ExpressionKind::WhileExpression { diff --git a/schala-lang/language/src/parsing/test.rs b/schala-lang/language/src/parsing/test.rs index 789d9b4..8299367 100644 --- a/schala-lang/language/src/parsing/test.rs +++ b/schala-lang/language/src/parsing/test.rs @@ -379,7 +379,7 @@ fn while_expression() { fn for_expression() { use ExpressionKind::*; - assert_expr!( + assert_expr2!( "for { a <- garodzny::maybeValue } return 1", expr(ForExpression { enumerators: vec![Enumerator { id: rc("a"), generator: expr(Value(qn!(garodzny, maybeValue))) }], @@ -387,8 +387,9 @@ fn for_expression() { }) ); - assert_expr!( - "for n <- someRange { f(n); }", + assert_expr2!( + //TODO make "for n <- someRange { f(n); }" work!! + "for n <- someRange { f(n) }", expr(ForExpression { enumerators: vec![Enumerator { id: rc("n"), generator: expr(Value(qn!(someRange))) }], body: bx(ForBody::StatementBlock(