From c2a23e1db2365b5440c3e7a4d59bc3cdb2e65691 Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:34:19 -0700 Subject: [PATCH 1/2] Adds support for %% and its derivatives (Also operator""()) The float stuff was easy. Operator was too, just took a bit to realize how it worked Nothin much else to say, outside that I needed to roll my own operation for this one, since float remainder is kinda hard to find (and I couldn't after cursory reading) --- crates/dreammaker/src/ast.rs | 5 ++++ crates/dreammaker/src/constants.rs | 8 ++++++ crates/dreammaker/src/lexer.rs | 40 ++++++++++++++++++------------ crates/dreammaker/src/parser.rs | 12 +++++++-- 4 files changed, 47 insertions(+), 18 deletions(-) diff --git a/crates/dreammaker/src/ast.rs b/crates/dreammaker/src/ast.rs index 49d8086a..3c1cb677 100644 --- a/crates/dreammaker/src/ast.rs +++ b/crates/dreammaker/src/ast.rs @@ -113,6 +113,7 @@ pub enum BinaryOp { Div, Pow, Mod, + FloatMod, Eq, NotEq, Less, @@ -142,6 +143,7 @@ impl fmt::Display for BinaryOp { Div => "/", Pow => "**", Mod => "%", + FloatMod => "%%", Eq => "==", NotEq => "!=", Less => "<", @@ -172,6 +174,7 @@ pub enum AssignOp { MulAssign, DivAssign, ModAssign, + FloatModAssign, AssignInto, BitAndAssign, AndAssign, @@ -192,6 +195,7 @@ impl fmt::Display for AssignOp { MulAssign => "*=", DivAssign => "/=", ModAssign => "%=", + FloatModAssign => "%%=", AssignInto => ":=", BitAndAssign => "&=", AndAssign => "&&=", @@ -233,6 +237,7 @@ augmented! { Mul = MulAssign; Div = DivAssign; Mod = ModAssign; + FloatMod = FloatModAssign; BitAnd = BitAndAssign; BitOr = BitOrAssign; BitXor = BitXorAssign; diff --git a/crates/dreammaker/src/constants.rs b/crates/dreammaker/src/constants.rs index 40adc04d..c75a240c 100644 --- a/crates/dreammaker/src/constants.rs +++ b/crates/dreammaker/src/constants.rs @@ -684,6 +684,14 @@ impl<'a> ConstantFolder<'a> { numeric!(LessEq <=); numeric!(Greater >); numeric!(GreaterEq >=); + match (op, lhs, rhs) { + (BinaryOp::FloatMod, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs - ((lhs / rhs).floor() * rhs))), + (_, lhs_, rhs_) => { + lhs = lhs_; + rhs = rhs_; + } + } + match (op, lhs, rhs) { (BinaryOp::Pow, Float(lhs), Float(rhs)) => return Ok(Constant::from(lhs.powf(rhs))), (_, lhs_, rhs_) => { diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index ed4c46d2..6a5abde3 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -71,9 +71,12 @@ table! { "!", Not; "!=", NotEq; "\"", DoubleQuote; + "\"\"", EmptyQuote; "#", Hash; "##", TokenPaste; "%", Mod; + "%%", FloatMod; + "%%=", FloatModAssign; "%=", ModAssign; "&", BitAnd; "&&", And; @@ -146,22 +149,26 @@ impl fmt::Display for Punctuation { /// character in the input, blazing fast. The code to generate it is contained /// in the following test. static SPEEDY_TABLE: [(usize, usize); 127] = [ - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 10), (10, 14), (14, 15), - (15, 16), (16, 17), (17, 20), (20, 23), (23, 24), (24, 27), (27, 30), (30, 34), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (34, 37), (37, 38), (38, 43), (43, 45), (45, 49), (49, 53), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (53, 54), (0, 0), (54, 55), (55, 57), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (57, 59), (59, 63), (63, 64), (64, 67)]; + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (2, 3), (3, 5), (5, 7), + (7, 9), (0, 0), (9, 13), (13, 17), (17, 18), (18, 19), (19, 20), + (20, 23), (23, 26), (26, 27), (27, 30), (30, 33), (33, 37), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (37, 40), (40, 41), (41, 46), (46, 48), (48, 52), + (52, 56), (0, 0), (0,0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (56, 57), (0, 0), (57, 58), (58, 60), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (60, 62), (62, 66), (66, 67), + (67, 70) + ]; #[test] fn make_speedy_table() { @@ -278,6 +285,7 @@ impl Token { Eq | NotEq | Mod | + FloatMod | And | BitAndAssign | AndAssign | diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index cde62424..922ba0cc 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -150,11 +150,12 @@ oper_table! { BINARY_OPS; Pow { (BinaryOp, Pow), } - // * / % + // * / % %% Mul { (BinaryOp, Mul), // (BinaryOp, Div = Slash), // (BinaryOp, Mod), + (BinaryOp, FloatMod), } // + - Add { @@ -205,7 +206,7 @@ oper_table! { BINARY_OPS; Conditional { (TernaryOp, Conditional = QuestionMark), } - // = += -= -= *= /= %= &= |= ^= <<= >>= + // = += -= -= *= /= %= %%= &= |= ^= <<= >>= Assign { (AssignOp, Assign), (AssignOp, AddAssign), @@ -213,6 +214,7 @@ oper_table! { BINARY_OPS; (AssignOp, MulAssign), (AssignOp, DivAssign), (AssignOp, ModAssign), + (AssignOp, FloatModAssign), (AssignOp, BitAndAssign), (AssignOp, BitOrAssign), (AssignOp, BitXorAssign), @@ -887,6 +889,10 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { last_part.push('%'); } else if self.exact(Punct(ModAssign))?.is_some() { last_part.push_str("%="); + } else if self.exact(Punct(FloatMod))?.is_some() { + last_part.push_str("%%"); + } else if self.exact(Punct(FloatModAssign))?.is_some() { + last_part.push_str("%%="); } else if self.exact(Punct(BitAnd))?.is_some() { last_part.push('&'); } else if self.exact(Punct(BitAndAssign))?.is_some() { @@ -944,6 +950,8 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else { last_part.push_str("[]"); } + } else if self.exact(Punct(EmptyQuote))?.is_some() { + last_part.push_str("\"\"") } SUCCESS } From c9bbd130fb53025fc235a0bb23d3f1adda4ad08c Mon Sep 17 00:00:00 2001 From: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Date: Sun, 8 Oct 2023 10:27:51 -0700 Subject: [PATCH 2/2] uses the string token rather then making a new one --- crates/dreammaker/src/lexer.rs | 36 +++++++++++++++------------------ crates/dreammaker/src/parser.rs | 2 +- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/crates/dreammaker/src/lexer.rs b/crates/dreammaker/src/lexer.rs index 6a5abde3..72c418a0 100644 --- a/crates/dreammaker/src/lexer.rs +++ b/crates/dreammaker/src/lexer.rs @@ -71,7 +71,6 @@ table! { "!", Not; "!=", NotEq; "\"", DoubleQuote; - "\"\"", EmptyQuote; "#", Hash; "##", TokenPaste; "%", Mod; @@ -149,25 +148,22 @@ impl fmt::Display for Punctuation { /// character in the input, blazing fast. The code to generate it is contained /// in the following test. static SPEEDY_TABLE: [(usize, usize); 127] = [ - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (2, 3), (3, 5), (5, 7), - (7, 9), (0, 0), (9, 13), (13, 17), (17, 18), (18, 19), (19, 20), - (20, 23), (23, 26), (26, 27), (27, 30), (30, 33), (33, 37), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (37, 40), (40, 41), (41, 46), (46, 48), (48, 52), - (52, 56), (0, 0), (0,0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (56, 57), (0, 0), (57, 58), (58, 60), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), - (0, 0), (0, 0), (0, 0), (0, 0), (60, 62), (62, 66), (66, 67), - (67, 70) + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 1), (1, 2), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (2, 3), (3, 5), (5, 6), (6, 8), (0, 0), (8, 12), (12, 16), (16, 17), + (17, 18), (18, 19), (19, 22), (22, 25), (25, 26), (26, 29), (29, 32), (32, 36), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (36, 39), (39, 40), (40, 45), (45, 47), (47, 51), (51, 55), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (55, 56), (0, 0), (56, 57), (57,59), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), (0, 0), + (0, 0), (0, 0), (0, 0), (59, 61), (61, 65), (65, 66), (66, 69), ]; #[test] diff --git a/crates/dreammaker/src/parser.rs b/crates/dreammaker/src/parser.rs index 922ba0cc..f9e40bbb 100644 --- a/crates/dreammaker/src/parser.rs +++ b/crates/dreammaker/src/parser.rs @@ -950,7 +950,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else { last_part.push_str("[]"); } - } else if self.exact(Punct(EmptyQuote))?.is_some() { + } else if self.exact(Token::String("".to_string()))?.is_some() { last_part.push_str("\"\"") } SUCCESS