From eac86b5e0b3f05128e7fe87a8d59cc308281b66f Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 18 Apr 2022 20:34:08 +0200 Subject: [PATCH] Changed variable declaration / assignment and equals syntax: - `dim [value];` is now used for declaration - ` =: ` is used for assignments - As token `=` doesn't cause any ambiguity now, it can be used for equals operation --- ablescript/src/ast.rs | 4 +- ablescript/src/interpret.rs | 10 ++--- ablescript/src/lexer.rs | 27 +++++++------ ablescript/src/parser.rs | 72 +++++++++++++++++++++++---------- examples/by-arity-chain.able | 10 ++--- examples/carts.able | 4 +- examples/hello-world.able | 2 +- examples/iotest.able | 2 +- examples/melo-hello.able | 2 +- examples/pass-by-reference.able | 14 +++---- 10 files changed, 88 insertions(+), 59 deletions(-) diff --git a/ablescript/src/ast.rs b/ablescript/src/ast.rs index 4a32589..346021e 100644 --- a/ablescript/src/ast.rs +++ b/ablescript/src/ast.rs @@ -113,7 +113,7 @@ pub enum Stmt { Break, HopBack, - Var { + Dim { ident: Spanned, init: Option>, }, @@ -186,7 +186,7 @@ impl BinOpKind { Token::FwdSlash => Ok(Self::Divide), Token::GreaterThan => Ok(Self::Greater), Token::LessThan => Ok(Self::Less), - Token::EqualEqual => Ok(Self::Equal), + Token::Equals => Ok(Self::Equal), Token::Aint => Ok(Self::NotEqual), t => Err(crate::error::ErrorKind::UnexpectedToken(t)), } diff --git a/ablescript/src/interpret.rs b/ablescript/src/interpret.rs index 41c1133..6bc5306 100644 --- a/ablescript/src/interpret.rs +++ b/ablescript/src/interpret.rs @@ -209,7 +209,7 @@ impl ExecEnv { Stmt::Print(expr) => { println!("{}", self.eval_expr(expr)?); } - Stmt::Var { ident, init } => { + Stmt::Dim { ident, init } => { let init = match init { Some(e) => self.eval_expr(e)?, None => Value::Nul, @@ -719,7 +719,7 @@ mod tests { let mut env = ExecEnv::new(); // Declaring and reading from a variable. - eval(&mut env, "var foo = 32; var bar = foo + 1;").unwrap(); + eval(&mut env, "dim foo 32; dim bar foo + 1;").unwrap(); assert_eq!( env.get_var(&Spanned { item: "bar".to_owned(), @@ -730,7 +730,7 @@ mod tests { ); // Assigning an existing variable. - eval(&mut env, "foo = /*hi*/;").unwrap(); + eval(&mut env, "/*hi*/ =: foo;").unwrap(); assert_eq!( env.get_var(&Spanned { item: "foo".to_owned(), @@ -742,7 +742,7 @@ mod tests { // But variable assignment should be illegal when the variable // hasn't been declared in advance. - eval(&mut env, "invalid = bar + 1;").unwrap_err(); + eval(&mut env, "bar + 1 =: invalid;").unwrap_err(); } #[test] @@ -753,7 +753,7 @@ mod tests { let mut env = ExecEnv::new(); eval( &mut env, - "var foo = 1; foo = 2; if (always) { var foo = 3; foo = 4; }", + "dim foo 1; 2 =: foo; if (always) { dim foo 3; 4 =: foo; }", ) .unwrap(); diff --git a/ablescript/src/lexer.rs b/ablescript/src/lexer.rs index 9c7d49b..7754ebb 100644 --- a/ablescript/src/lexer.rs +++ b/ablescript/src/lexer.rs @@ -40,8 +40,8 @@ pub enum Token { #[token("/")] FwdSlash, - #[token("=")] - Equal, + #[token("=:")] + Assign, #[token("<=")] Arrow, @@ -53,8 +53,8 @@ pub enum Token { #[token(">")] GreaterThan, - #[token("==")] - EqualEqual, + #[token("=")] + Equals, #[token("ain't")] Aint, @@ -68,8 +68,8 @@ pub enum Token { Bff, /// Variable bro - #[token("var")] - Var, + #[token("dim")] + Dim, /// Prints the preceding things #[token("print")] @@ -152,24 +152,25 @@ mod tests { #[test] fn simple_fn() { - let code = "functio test() { var a = 3; if a == 3 { a print } }"; + let code = "functio test() { dim var 3; if (var = 3) { var print } }"; let expected = &[ Functio, Identifier("test".to_owned()), LeftParen, RightParen, LeftCurly, - Var, - Identifier("a".to_owned()), - Equal, + Dim, + Identifier("var".to_owned()), Integer(3), Semicolon, If, - Identifier("a".to_owned()), - EqualEqual, + LeftParen, + Identifier("var".to_owned()), + Equals, Integer(3), + RightParen, LeftCurly, - Identifier("a".to_owned()), + Identifier("var".to_owned()), Print, RightCurly, RightCurly, diff --git a/ablescript/src/parser.rs b/ablescript/src/parser.rs index ca2ac84..40b7b20 100644 --- a/ablescript/src/parser.rs +++ b/ablescript/src/parser.rs @@ -73,7 +73,7 @@ impl<'source> Parser<'source> { start..self.lexer.span().end, )), Token::Bff => Ok(Spanned::new(self.bff_flow()?, start..self.lexer.span().end)), - Token::Var => Ok(Spanned::new(self.var_flow()?, start..self.lexer.span().end)), + Token::Dim => Ok(Spanned::new(self.dim_flow()?, start..self.lexer.span().end)), Token::Melo => Ok(Spanned::new( self.melo_flow()?, start..self.lexer.span().end, @@ -209,7 +209,7 @@ impl<'source> Parser<'source> { | Token::Minus | Token::Star | Token::FwdSlash - | Token::EqualEqual + | Token::Equals | Token::LessThan | Token::GreaterThan | Token::Aint => Ok(Spanned::new( @@ -382,17 +382,13 @@ impl<'source> Parser<'source> { } // Variable Assignment - Token::Equal => { - if let Some(Ok(assignable)) = buf.take().map(Assignable::from_expr) { - break Stmt::Assign { - assignable, - value: self.expr_flow(Token::Semicolon)?, - }; - } else { - return Err(Error::new( - ErrorKind::UnexpectedToken(Token::Equal), + Token::Assign => { + return match buf.take() { + Some(expr) => self.assignment_flow(expr), + None => Err(Error::new( + ErrorKind::UnexpectedToken(Token::Assign), self.lexer.span(), - )); + )), } } @@ -546,15 +542,47 @@ impl<'source> Parser<'source> { } /// Parse variable declaration - fn var_flow(&mut self) -> Result { + fn dim_flow(&mut self) -> Result { let ident = self.get_ident()?; - let init = match self.checked_next()? { - Token::Equal => Some(self.expr_flow(Token::Semicolon)?), - Token::Semicolon => None, + let mut init = None; + loop { + match self.checked_next()? { + Token::Semicolon => break, + t => init = Some(self.parse_expr(t, &mut init)?), + } + } + + Ok(Stmt::Dim { ident, init }) + } + + /// Parse assignment to assignable + fn assignment_flow(&mut self, value: Spanned) -> Result { + let ident = self.get_ident()?; + let kind = match self.checked_next()? { + Token::Semicolon => AssignableKind::Variable, + Token::LeftBracket => { + let mut indices = vec![]; + loop { + indices.push(self.expr_flow(Token::RightBracket)?); + match self.checked_next()? { + Token::Semicolon => break AssignableKind::Index { indices }, + Token::LeftBracket => (), + t => { + return Err(Error::new( + ErrorKind::UnexpectedToken(t), + self.lexer.span(), + )) + } + } + } + } t => return Err(Error::new(ErrorKind::UnexpectedToken(t), self.lexer.span())), }; - Ok(Stmt::Var { ident, init }) + Ok(Stmt::Assign { + assignable: Assignable { ident, kind }, + value, + }) } /// Parse Melo flow @@ -624,9 +652,9 @@ mod tests { #[test] fn variable_declaration() { - let code = "var a = 42;"; + let code = "dim a 42;"; let expected = &[Spanned { - item: Stmt::Var { + item: Stmt::Dim { ident: Spanned { item: "a".to_owned(), span: 4..5, @@ -645,7 +673,7 @@ mod tests { #[test] fn if_flow() { - let code = "if (a == always) { /*Buy Able products!*/ print; }"; + let code = "if (a = always) { /*Buy Able products!*/ print; }"; let expected = &[Spanned { item: Stmt::If { cond: Spanned { @@ -679,9 +707,9 @@ mod tests { #[test] fn tdark() { - let code = "T-Dark { var lang = /*lang*/ + lang; }"; + let code = "T-Dark { dim lang /*lang*/ + lang; }"; let expected = &[Spanned { - item: Stmt::Var { + item: Stmt::Dim { ident: Spanned { item: "script".to_owned(), span: 13..17, diff --git a/examples/by-arity-chain.able b/examples/by-arity-chain.able index 8e1665b..f34b6ca 100644 --- a/examples/by-arity-chain.able +++ b/examples/by-arity-chain.able @@ -25,20 +25,20 @@ owo arity_1(/*foo*/); owo arity_2(/*foo*/, /*bar*/); owo arity_3(/*foo*/, /*bar*/, /*baz*/); -var i1 = arity_0 * arity_1; +dim i1 arity_0 * arity_1; i1(/*second*/); /*----*/ print; -var i2 = arity_1 * arity_0; +dim i2 arity_1 * arity_0; i2(/*first*/); /*----*/ print; -var ifancy = arity_3 * arity_3; +dim ifancy arity_3 * arity_3; ifancy(/*left1*/, /*right1*/, /*left2*/, /*right2*/, /*left3*/, /*right3*/); -/*---*/" print; +/*---*/ print; -var another = arity_0 * arity_3; +dim another arity_0 * arity_3; another(/*right1*/, /*right2*/, /*right3*/); diff --git a/examples/carts.able b/examples/carts.able index 94f102d..1188ddb 100644 --- a/examples/carts.able +++ b/examples/carts.able @@ -1,8 +1,8 @@ functio helloable() { - "ยด/*Hello, Able!*/ print; + /*Hello, Able!*/ print; } -var cart = [/*able*/ <= 42, helloable <= /*hello*/]; +dim cart [/*able*/ <= 42, helloable <= /*hello*/]; cart[42] print; cart[/*hello*/](); diff --git a/examples/hello-world.able b/examples/hello-world.able index cf2fc47..11778b4 100644 --- a/examples/hello-world.able +++ b/examples/hello-world.able @@ -1,2 +1,2 @@ -var hello = /*world*/; +dim hello /*world*/; hello print; diff --git a/examples/iotest.able b/examples/iotest.able index 3795d6c..ca312e1 100644 --- a/examples/iotest.able +++ b/examples/iotest.able @@ -1,4 +1,4 @@ -var data; +dim data; loop { data read; data print; diff --git a/examples/melo-hello.able b/examples/melo-hello.able index 2e6279d..b50b808 100644 --- a/examples/melo-hello.able +++ b/examples/melo-hello.able @@ -1,3 +1,3 @@ -var hi = /*wonk*/; +dim hi /*wonk*/; melo hi; hi print; owo Should error out diff --git a/examples/pass-by-reference.able b/examples/pass-by-reference.able index cf51edb..8beefe3 100644 --- a/examples/pass-by-reference.able +++ b/examples/pass-by-reference.able @@ -2,22 +2,22 @@ owo Pass-by-reference test owo Swap two variables. functio swap(left, right) { - var tmp = left; - left = right; - right = tmp; + dim tmp left; + right =: left; + tmp =: right; } -var foo = /*hello*/; -var bar = /*world*/; +dim foo /*hello*/; +dim bar /*world*/; swap(foo, bar); -if (foo != /*world*/) { +if (foo ain't /*world*/) { /*FAILED*/ print; /*foo should be 'world', is actually:*/ print; foo print; } -if (foo == /*world*/) { +if (foo = /*world*/) { /*OK*/ print; }