From 9ebc836b89a8b208434c2e6e830a67ff72b6a5c8 Mon Sep 17 00:00:00 2001 From: rvcas Date: Sun, 4 Dec 2022 18:49:21 -0500 Subject: [PATCH] feat: handle punning in a non-ambiguous way --- crates/lang/src/parser.rs | 82 +++++++++++++----------------- crates/lang/src/parser/lexer.rs | 1 - crates/lang/src/parser/token.rs | 2 - crates/lang/src/tests/parser.rs | 40 +++++++-------- examples/sample/validators/swap.ak | 2 +- 5 files changed, 56 insertions(+), 71 deletions(-) diff --git a/crates/lang/src/parser.rs b/crates/lang/src/parser.rs index 9a4cc547..0a30466c 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/parser.rs @@ -627,7 +627,7 @@ pub fn expr_parser( let record_parser = choice(( select! {Token::Name { name } => name} - .map_with_span(|module, span| (module, span)) + .map_with_span(|module, span: Span| (module, span)) .then_ignore(just(Token::Dot)) .or_not() .then( @@ -635,35 +635,29 @@ pub fn expr_parser( .map_with_span(|name, span| (name, span)), ) .then( - select! {Token::Name {name} => name} - .then_ignore(just(Token::Colon)) - .or_not() - .then(r.clone()) - .validate(|(label_opt, value), span, emit| { - dbg!(&label_opt); - let label = if label_opt.is_some() { - label_opt - } else if let expr::UntypedExpr::Var { name, .. } = &value { - Some(name.clone()) - } else { - emit(ParseError::expected_input_found( - value.location(), - None, - Some(error::Pattern::RecordPunning), - )); - - None - }; - - ast::CallArg { + choice(( + select! {Token::Name {name} => name} + .then_ignore(just(Token::Colon)) + .then(r.clone()) + .map_with_span(|(label, value), span| ast::CallArg { location: span, value, - label, + label: Some(label), + }), + select! {Token::Name {name} => name}.map_with_span(|name, span| { + ast::CallArg { + location: span, + value: expr::UntypedExpr::Var { + name: name.clone(), + location: span, + }, + label: Some(name), } - }) - .separated_by(just(Token::Comma)) - .allow_trailing() - .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)), + }), + )) + .separated_by(just(Token::Comma)) + .allow_trailing() + .delimited_by(just(Token::LeftBrace), just(Token::RightBrace)), ), select! {Token::Name { name } => name} .map_with_span(|module, span| (module, span)) @@ -918,29 +912,23 @@ pub fn expr_parser( ); let if_parser = just(Token::If) - .ignore_then( - r.clone() - .then_ignore(just(Token::Then)) - .then(block_parser.clone()) - .map_with_span(|(condition, body), span| ast::IfBranch { - condition, - body, - location: span, - }), - ) + .ignore_then(r.clone().then(block_parser.clone()).map_with_span( + |(condition, body), span| ast::IfBranch { + condition, + body, + location: span, + }, + )) .then( just(Token::Else) .ignore_then(just(Token::If)) - .ignore_then( - r.clone() - .then_ignore(just(Token::Then)) - .then(block_parser.clone()) - .map_with_span(|(condition, body), span| ast::IfBranch { - condition, - body, - location: span, - }), - ) + .ignore_then(r.clone().then(block_parser.clone()).map_with_span( + |(condition, body), span| ast::IfBranch { + condition, + body, + location: span, + }, + )) .repeated(), ) .then_ignore(just(Token::Else)) diff --git a/crates/lang/src/parser/lexer.rs b/crates/lang/src/parser/lexer.rs index 43b2efaf..af6aeb9f 100644 --- a/crates/lang/src/parser/lexer.rs +++ b/crates/lang/src/parser/lexer.rs @@ -69,7 +69,6 @@ pub fn lexer() -> impl Parser, Error = ParseError> { "fn" => Token::Fn, "if" => Token::If, "else" => Token::Else, - "then" => Token::Then, "is" => Token::Is, "let" => Token::Let, "opaque" => Token::Opaque, diff --git a/crates/lang/src/parser/token.rs b/crates/lang/src/parser/token.rs index 542edcae..8faaa339 100644 --- a/crates/lang/src/parser/token.rs +++ b/crates/lang/src/parser/token.rs @@ -72,7 +72,6 @@ pub enum Token { Trace, Type, When, - Then, } impl fmt::Display for Token { @@ -146,7 +145,6 @@ impl fmt::Display for Token { Token::Todo => "todo", Token::Trace => "try", Token::Type => "type", - Token::Then => "then", }; write!(f, "\"{}\"", s) } diff --git a/crates/lang/src/tests/parser.rs b/crates/lang/src/tests/parser.rs index e1ca3845..80982d3a 100644 --- a/crates/lang/src/tests/parser.rs +++ b/crates/lang/src/tests/parser.rs @@ -423,11 +423,11 @@ fn pipeline() { fn if_expression() { let code = indoc! {r#" fn ifs() { - if True then { + if True { 1 + 1 - } else if a < 4 then { + } else if a < 4 { 5 - } else if a || b then { + } else if a || b { 6 } else { 3 @@ -440,7 +440,7 @@ fn if_expression() { ast::UntypedDefinition::Fn(Function { arguments: vec![], body: expr::UntypedExpr::If { - location: Span::new((), 13..121), + location: Span::new((), 13..106), branches: vec1::vec1![ ast::IfBranch { condition: expr::UntypedExpr::Var { @@ -448,60 +448,60 @@ fn if_expression() { name: "True".to_string(), }, body: expr::UntypedExpr::BinOp { - location: Span::new((), 32..37), + location: Span::new((), 27..32), name: ast::BinOp::AddInt, left: Box::new(expr::UntypedExpr::Int { - location: Span::new((), 32..33), + location: Span::new((), 27..28), value: "1".to_string(), }), right: Box::new(expr::UntypedExpr::Int { - location: Span::new((), 36..37), + location: Span::new((), 31..32), value: "1".to_string(), }), }, - location: Span::new((), 16..41), + location: Span::new((), 16..36), }, ast::IfBranch { condition: expr::UntypedExpr::BinOp { - location: Span::new((), 50..55), + location: Span::new((), 45..50), name: ast::BinOp::LtInt, left: Box::new(expr::UntypedExpr::Var { - location: Span::new((), 50..51), + location: Span::new((), 45..46), name: "a".to_string(), }), right: Box::new(expr::UntypedExpr::Int { - location: Span::new((), 54..55), + location: Span::new((), 49..50), value: "4".to_string(), }), }, body: expr::UntypedExpr::Int { - location: Span::new((), 67..68), + location: Span::new((), 57..58), value: "5".to_string(), }, - location: Span::new((), 50..72), + location: Span::new((), 45..62), }, ast::IfBranch { condition: expr::UntypedExpr::BinOp { - location: Span::new((), 81..87), + location: Span::new((), 71..77), name: ast::BinOp::Or, left: Box::new(expr::UntypedExpr::Var { - location: Span::new((), 81..82), + location: Span::new((), 71..72), name: "a".to_string(), }), right: Box::new(expr::UntypedExpr::Var { - location: Span::new((), 86..87), + location: Span::new((), 76..77), name: "b".to_string(), }), }, body: expr::UntypedExpr::Int { - location: Span::new((), 99..100), + location: Span::new((), 84..85), value: "6".to_string(), }, - location: Span::new((), 81..104), + location: Span::new((), 71..89), }, ], final_else: Box::new(expr::UntypedExpr::Int { - location: Span::new((), 116..117), + location: Span::new((), 101..102), value: "3".to_string(), }), }, @@ -511,7 +511,7 @@ fn if_expression() { public: false, return_annotation: None, return_type: (), - end_position: 122, + end_position: 107, }), ) } diff --git a/examples/sample/validators/swap.ak b/examples/sample/validators/swap.ak index 0e7ad91e..b18bf996 100644 --- a/examples/sample/validators/swap.ak +++ b/examples/sample/validators/swap.ak @@ -32,7 +32,7 @@ pub fn final_check(z: Int) { } pub fn incrementor(counter: Int, target: Int) -> Int { - if counter == target then { + if counter == target { target } else { incrementor(counter + 1, target)