From 4dbff0fd6973b6d1ef8ff643cb2d81ab5ad4e2f9 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 4 Nov 2023 15:14:48 +0100 Subject: [PATCH 1/4] Add test case --- full-moon/tests/roblox_cases/pass/floor_division/source.lua | 1 + 1 file changed, 1 insertion(+) create mode 100644 full-moon/tests/roblox_cases/pass/floor_division/source.lua diff --git a/full-moon/tests/roblox_cases/pass/floor_division/source.lua b/full-moon/tests/roblox_cases/pass/floor_division/source.lua new file mode 100644 index 00000000..8460eebb --- /dev/null +++ b/full-moon/tests/roblox_cases/pass/floor_division/source.lua @@ -0,0 +1 @@ +local x = 1 // 2 From 48d356787959ed2e202b7b8b392dd3ff8d97934b Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 4 Nov 2023 15:14:55 +0100 Subject: [PATCH 2/4] Support floor division --- full-moon/src/ast/mod.rs | 7 +++++-- full-moon/src/ast/parsers.rs | 8 ++++++-- full-moon/src/atom.rs | 2 +- full-moon/src/tokenizer.rs | 6 +++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/full-moon/src/ast/mod.rs b/full-moon/src/ast/mod.rs index 978b0401..151284ac 100644 --- a/full-moon/src/ast/mod.rs +++ b/full-moon/src/ast/mod.rs @@ -2028,7 +2028,7 @@ make_op!(BinOp, TwoEqual, #[cfg(feature = "lua53")] Ampersand, - #[cfg(feature = "lua53")] + #[cfg(any(feature = "roblox", feature = "lua53"))] DoubleSlash, #[cfg(feature = "lua53")] DoubleLessThan, @@ -2049,6 +2049,8 @@ impl BinOp { match *self { BinOp::Caret(_) => 8, BinOp::Star(_) | BinOp::Slash(_) | BinOp::Percent(_) => 6, + #[cfg(feature = "roblox")] + BinOp::DoubleSlash(_) => 6, BinOp::Plus(_) | BinOp::Minus(_) => 5, BinOp::TwoDots(_) => 4, BinOp::GreaterThan(_) @@ -2110,9 +2112,10 @@ impl BinOp { | BinOp::TildeEqual(token) | BinOp::TwoDots(token) | BinOp::TwoEqual(token) => token, + #[cfg(any(feature = "roblox", feature = "lua53"))] + BinOp::DoubleSlash(token) => token, #[cfg(feature = "lua53")] BinOp::Ampersand(token) - | BinOp::DoubleSlash(token) | BinOp::DoubleLessThan(token) | BinOp::Pipe(token) | BinOp::DoubleGreaterThan(token) diff --git a/full-moon/src/ast/parsers.rs b/full-moon/src/ast/parsers.rs index 24a23720..c25e38e2 100644 --- a/full-moon/src/ast/parsers.rs +++ b/full-moon/src/ast/parsers.rs @@ -2221,12 +2221,16 @@ define_parser!(ParseBinOp, BinOp, |_, state| { } else if let Ok((state, operator)) = ParseSymbol(Symbol::TwoEqual).parse(state) { Ok((state, BinOp::TwoEqual(operator))) } else { + // Luau & Lua 5.3 + #[cfg(any(feature = "roblox", feature = "lua53"))] + if let Ok((state, operator)) = ParseSymbol(Symbol::DoubleSlash).parse(state) { + return Ok((state, BinOp::DoubleSlash(operator))); + } + // Lua 5.3 #[cfg(feature = "lua53")] if let Ok((state, operator)) = ParseSymbol(Symbol::Ampersand).parse(state) { return Ok((state, BinOp::Ampersand(operator))); - } else if let Ok((state, operator)) = ParseSymbol(Symbol::DoubleSlash).parse(state) { - return Ok((state, BinOp::DoubleSlash(operator))); } else if let Ok((state, operator)) = ParseSymbol(Symbol::DoubleLessThan).parse(state) { return Ok((state, BinOp::DoubleLessThan(operator))); } else if let Ok((state, operator)) = ParseSymbol(Symbol::Pipe).parse(state) { diff --git a/full-moon/src/atom.rs b/full-moon/src/atom.rs index e2fff7b6..fdc168b6 100644 --- a/full-moon/src/atom.rs +++ b/full-moon/src/atom.rs @@ -356,7 +356,7 @@ pub(crate) enum Atom { #[token("/")] Slash, - #[cfg(feature = "lua53")] + #[cfg(any(feature = "roblox", feature = "lua53"))] #[token("//")] DoubleSlash, diff --git a/full-moon/src/tokenizer.rs b/full-moon/src/tokenizer.rs index 1664a9a6..55284aac 100644 --- a/full-moon/src/tokenizer.rs +++ b/full-moon/src/tokenizer.rs @@ -172,7 +172,7 @@ pub enum Symbol { #[cfg_attr(feature = "serde", serde(rename = "/"))] Slash, - #[cfg(feature = "lua53")] + #[cfg(any(feature = "roblox", feature = "lua53"))] #[cfg_attr(feature = "serde", serde(rename = "//"))] DoubleSlash, @@ -265,7 +265,7 @@ impl TryFrom for Symbol { Atom::RightParen => Symbol::RightParen, Atom::Semicolon => Symbol::Semicolon, Atom::Slash => Symbol::Slash, - #[cfg(feature = "lua53")] + #[cfg(any(feature = "roblox", feature = "lua53"))] Atom::DoubleSlash => Symbol::DoubleSlash, Atom::Star => Symbol::Star, #[cfg(feature = "lua53")] @@ -349,7 +349,7 @@ impl Display for Symbol { Symbol::RightParen => ")", Symbol::Semicolon => ";", Symbol::Slash => "/", - #[cfg(feature = "lua53")] + #[cfg(any(feature = "roblox", feature = "lua53"))] Symbol::DoubleSlash => "//", Symbol::Star => "*", #[cfg(feature = "lua53")] From 556090f8ed24e020e7d21a707cd1dd8a77594a83 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 4 Nov 2023 15:15:00 +0100 Subject: [PATCH 3/4] Update snapshots --- .../roblox_cases/pass/floor_division/ast.snap | 173 ++++++++++++++++++ .../pass/floor_division/tokens.snap | 147 +++++++++++++++ 2 files changed, 320 insertions(+) create mode 100644 full-moon/tests/roblox_cases/pass/floor_division/ast.snap create mode 100644 full-moon/tests/roblox_cases/pass/floor_division/tokens.snap diff --git a/full-moon/tests/roblox_cases/pass/floor_division/ast.snap b/full-moon/tests/roblox_cases/pass/floor_division/ast.snap new file mode 100644 index 00000000..31e67c65 --- /dev/null +++ b/full-moon/tests/roblox_cases/pass/floor_division/ast.snap @@ -0,0 +1,173 @@ +--- +source: full-moon/tests/pass_cases.rs +expression: ast.nodes() +--- +stmts: + - - LocalAssignment: + local_token: + leading_trivia: [] + token: + start_position: + bytes: 0 + line: 1 + character: 1 + end_position: + bytes: 5 + line: 1 + character: 6 + token_type: + type: Symbol + symbol: local + trailing_trivia: + - start_position: + bytes: 5 + line: 1 + character: 6 + end_position: + bytes: 6 + line: 1 + character: 7 + token_type: + type: Whitespace + characters: " " + name_list: + pairs: + - End: + leading_trivia: [] + token: + start_position: + bytes: 6 + line: 1 + character: 7 + end_position: + bytes: 7 + line: 1 + character: 8 + token_type: + type: Identifier + identifier: x + trailing_trivia: + - start_position: + bytes: 7 + line: 1 + character: 8 + end_position: + bytes: 8 + line: 1 + character: 9 + token_type: + type: Whitespace + characters: " " + equal_token: + leading_trivia: [] + token: + start_position: + bytes: 8 + line: 1 + character: 9 + end_position: + bytes: 9 + line: 1 + character: 10 + token_type: + type: Symbol + symbol: "=" + trailing_trivia: + - start_position: + bytes: 9 + line: 1 + character: 10 + end_position: + bytes: 10 + line: 1 + character: 11 + token_type: + type: Whitespace + characters: " " + expr_list: + pairs: + - End: + BinaryOperator: + lhs: + Number: + leading_trivia: [] + token: + start_position: + bytes: 10 + line: 1 + character: 11 + end_position: + bytes: 11 + line: 1 + character: 12 + token_type: + type: Number + text: "1" + trailing_trivia: + - start_position: + bytes: 11 + line: 1 + character: 12 + end_position: + bytes: 12 + line: 1 + character: 13 + token_type: + type: Whitespace + characters: " " + binop: + DoubleSlash: + leading_trivia: [] + token: + start_position: + bytes: 12 + line: 1 + character: 13 + end_position: + bytes: 14 + line: 1 + character: 15 + token_type: + type: Symbol + symbol: // + trailing_trivia: + - start_position: + bytes: 14 + line: 1 + character: 15 + end_position: + bytes: 15 + line: 1 + character: 16 + token_type: + type: Whitespace + characters: " " + rhs: + Number: + leading_trivia: [] + token: + start_position: + bytes: 15 + line: 1 + character: 16 + end_position: + bytes: 16 + line: 1 + character: 17 + token_type: + type: Number + text: "2" + trailing_trivia: + - start_position: + bytes: 16 + line: 1 + character: 17 + end_position: + bytes: 17 + line: 1 + character: 17 + token_type: + type: Whitespace + characters: "\n" + - ~ + diff --git a/full-moon/tests/roblox_cases/pass/floor_division/tokens.snap b/full-moon/tests/roblox_cases/pass/floor_division/tokens.snap new file mode 100644 index 00000000..ec026300 --- /dev/null +++ b/full-moon/tests/roblox_cases/pass/floor_division/tokens.snap @@ -0,0 +1,147 @@ +--- +source: full-moon/tests/pass_cases.rs +expression: tokens +--- +- start_position: + bytes: 0 + line: 1 + character: 1 + end_position: + bytes: 5 + line: 1 + character: 6 + token_type: + type: Symbol + symbol: local +- start_position: + bytes: 5 + line: 1 + character: 6 + end_position: + bytes: 6 + line: 1 + character: 7 + token_type: + type: Whitespace + characters: " " +- start_position: + bytes: 6 + line: 1 + character: 7 + end_position: + bytes: 7 + line: 1 + character: 8 + token_type: + type: Identifier + identifier: x +- start_position: + bytes: 7 + line: 1 + character: 8 + end_position: + bytes: 8 + line: 1 + character: 9 + token_type: + type: Whitespace + characters: " " +- start_position: + bytes: 8 + line: 1 + character: 9 + end_position: + bytes: 9 + line: 1 + character: 10 + token_type: + type: Symbol + symbol: "=" +- start_position: + bytes: 9 + line: 1 + character: 10 + end_position: + bytes: 10 + line: 1 + character: 11 + token_type: + type: Whitespace + characters: " " +- start_position: + bytes: 10 + line: 1 + character: 11 + end_position: + bytes: 11 + line: 1 + character: 12 + token_type: + type: Number + text: "1" +- start_position: + bytes: 11 + line: 1 + character: 12 + end_position: + bytes: 12 + line: 1 + character: 13 + token_type: + type: Whitespace + characters: " " +- start_position: + bytes: 12 + line: 1 + character: 13 + end_position: + bytes: 14 + line: 1 + character: 15 + token_type: + type: Symbol + symbol: // +- start_position: + bytes: 14 + line: 1 + character: 15 + end_position: + bytes: 15 + line: 1 + character: 16 + token_type: + type: Whitespace + characters: " " +- start_position: + bytes: 15 + line: 1 + character: 16 + end_position: + bytes: 16 + line: 1 + character: 17 + token_type: + type: Number + text: "2" +- start_position: + bytes: 16 + line: 1 + character: 17 + end_position: + bytes: 17 + line: 1 + character: 17 + token_type: + type: Whitespace + characters: "\n" +- start_position: + bytes: 17 + line: 2 + character: 1 + end_position: + bytes: 17 + line: 2 + character: 1 + token_type: + type: Eof + From b42c35078efd47dc4d6ceb58dafae4771a005fbc Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sat, 4 Nov 2023 15:15:27 +0100 Subject: [PATCH 4/4] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9dc1a1b4..4c7e9fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased +### Added +- Added support for parsing Luau's floor division `//` + ### Changed - Flattened `Expression::Value` to all be variants of `Expression` directly, as this was not used anywhere else. The extra `type_assertion` field has been moved into a new variant `Expression::TypeAssertion`. None of these variants are boxed. - The following fields/variants have been changed from `Expression` to `Box`: `Prefix::Expression`, `Var::Expression`, `IfExpression::condition`, `IfExpression::if_expression`, `IfExpression::else_expression`.