Changed variable declaration / assignment and equals syntax:

- `dim <ident> [value];` is now used for declaration
- `<value> =: <assignable>` is used for assignments
- As token `=` doesn't cause any ambiguity now, it can be used for equals operation
pull/7/head
ondra05 2022-04-18 20:34:08 +02:00
parent a4e3b98c6a
commit 0ef7177a03
10 changed files with 88 additions and 59 deletions

View File

@ -113,7 +113,7 @@ pub enum Stmt {
Break,
HopBack,
Var {
Dim {
ident: Spanned<String>,
init: Option<Spanned<Expr>>,
},
@ -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)),
}

View File

@ -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();

View File

@ -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,

View File

@ -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<Stmt, Error> {
fn dim_flow(&mut self) -> Result<Stmt, Error> {
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<Expr>) -> Result<Stmt, Error> {
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,

View File

@ -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*/);

View File

@ -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*/]();

View File

@ -1,2 +1,2 @@
var hello = /*world*/;
dim hello /*world*/;
hello print;

View File

@ -1,4 +1,4 @@
var data;
dim data;
loop {
data read;
data print;

View File

@ -1,3 +1,3 @@
var hi = /*wonk*/;
dim hi /*wonk*/;
melo hi;
hi print; owo Should error out

View File

@ -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;
}