From 24b83c8448f26cccb48427838b9c55e4b4c8a719 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Sat, 1 Feb 2025 00:58:29 +0000 Subject: [PATCH 1/4] refactor: remove boilerplate parser --- src/main/wacc/parser.scala | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/src/main/wacc/parser.scala b/src/main/wacc/parser.scala index 370f8aa..871ade0 100644 --- a/src/main/wacc/parser.scala +++ b/src/main/wacc/parser.scala @@ -1,20 +1,8 @@ package wacc -import parsley.{Parsley, Result} -import parsley.expr.chain - -import lexer.implicits.implicitSymbol -import lexer.{integer, fully} +import parsley.Result object parser { def parse(input: String): Result[String, BigInt] = parser.parse(input) - private val parser = fully(expr) - - private val add = (x: BigInt, y: BigInt) => x + y - private val sub = (x: BigInt, y: BigInt) => x - y - - private lazy val expr: Parsley[BigInt] = - chain.left1(integer | "(" ~> expr <~ ")")( - ("+" as add) | ("-" as sub) - ) + private val parser = lexer.fully(???) } From bf310b633a95b112e781de67a26402ba8ca85884 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Sat, 1 Feb 2025 02:21:31 +0000 Subject: [PATCH 2/4] refactor: allow binPack Strings --- .scalafmt.conf | 2 ++ src/test/wacc/examples.scala | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.scalafmt.conf b/.scalafmt.conf index 2f0c08c..22c361b 100644 --- a/.scalafmt.conf +++ b/.scalafmt.conf @@ -1,2 +1,4 @@ version = 3.8.6 runner.dialect = scala3 + +binPack.literalsExclude = [] diff --git a/src/test/wacc/examples.scala b/src/test/wacc/examples.scala index ef48195..cb4db0e 100644 --- a/src/test/wacc/examples.scala +++ b/src/test/wacc/examples.scala @@ -42,6 +42,8 @@ class ParallelExamplesSpec def fileIsDissallowed(filename: String): Boolean = Seq( + // format: off + // disable formatting to avoid binPack "wacc-examples/valid/advanced", "wacc-examples/valid/array", "wacc-examples/valid/basic/exit", @@ -88,5 +90,6 @@ class ParallelExamplesSpec "wacc-examples/invalid/semanticErr/while", // invalid (whack) "wacc-examples/invalid/whack" + // format: on ).find(filename.contains).isDefined } From bf163e52fe5212bdcaeab97c0a9af1472319b622 Mon Sep 17 00:00:00 2001 From: Jonny Date: Sat, 1 Feb 2025 02:21:39 +0000 Subject: [PATCH 3/4] feat: initial lexer implementation --- src/main/wacc/lexer.scala | 51 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/src/main/wacc/lexer.scala b/src/main/wacc/lexer.scala index f633bf6..907053b 100644 --- a/src/main/wacc/lexer.scala +++ b/src/main/wacc/lexer.scala @@ -1,16 +1,61 @@ package wacc import parsley.Parsley -import parsley.token.Lexer +import parsley.token.{Basic, Lexer} import parsley.token.descriptions.* object lexer { private val desc = LexicalDesc.plain.copy( - // your configuration goes here + nameDesc = NameDesc.plain.copy( + identifierStart = Basic(c => c.isLetter || c == '_'), + identifierLetter = Basic(c => c.isLetterOrDigit || c == '_') + ), + symbolDesc = SymbolDesc.plain.copy( + hardKeywords = Set( + "begin", "end", "is", "skip", "if", "then", "else", "fi", "while", "do", + "done", "read", "free", "return", "exit", "print", "println", "true", + "false", "int", "bool", "char", "string", "pair", "newpair", "fst", + "snd", "call", "chr", "ord", "len", "null" + ), + hardOperators = Set( + "+", "-", "*", "/", "%", ">", "<", ">=", "<=", "==", "!=", "&&", "||", + "!" + ) + ), + spaceDesc = SpaceDesc.plain.copy( + lineCommentStart = "#" + ), + // TODO - See BNF 1.1 and Table 5 2.3.6 + textDesc = TextDesc.plain.copy( + graphicCharacter = + Basic(c => c >= ' ' && c != '\\' && c != '\'' && c != '"'), + escapeSequences = EscapeDesc.plain.copy( + literals = Set('\\', '"', '\''), + mapping = Map( + "0" -> '\u0000', + "b" -> '\b', + "t" -> '\t', + "n" -> '\n', + "f" -> '\f', + "r" -> '\r' + ) + ) + ) ) + private val lexer = Lexer(desc) - val integer = lexer.lexeme.integer.decimal + // Enforce 32-bit signed integer range - see 1.5 + // TODO By default leadingZerosAllowed = true in NumericDesc - Wacc doesnt specify (I think) but should reach consensus + val integer = lexer.lexeme.integer.decimal32[Int] + + // TODO Check if textDesc can handle this + val charLit = lexer.lexeme.character.ascii + + // TODO Check if textDesc can handle this + val stringLit = lexer.lexeme.string.ascii + val implicits = lexer.lexeme.symbol.implicits + def fully[A](p: Parsley[A]): Parsley[A] = lexer.fully(p) } From 4f02d7f2b0898329d7a20d89ed2e247ac269db10 Mon Sep 17 00:00:00 2001 From: Gleb Koval Date: Sat, 1 Feb 2025 02:13:55 +0000 Subject: [PATCH 4/4] fix: disallow exponents, export identifier from lexer --- src/main/wacc/lexer.scala | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/wacc/lexer.scala b/src/main/wacc/lexer.scala index 907053b..abe5cb1 100644 --- a/src/main/wacc/lexer.scala +++ b/src/main/wacc/lexer.scala @@ -25,7 +25,6 @@ object lexer { spaceDesc = SpaceDesc.plain.copy( lineCommentStart = "#" ), - // TODO - See BNF 1.1 and Table 5 2.3.6 textDesc = TextDesc.plain.copy( graphicCharacter = Basic(c => c >= ' ' && c != '\\' && c != '\'' && c != '"'), @@ -40,21 +39,17 @@ object lexer { "r" -> '\r' ) ) + ), + numericDesc = NumericDesc.plain.copy( + decimalExponentDesc = ExponentDesc.NoExponents ) ) private val lexer = Lexer(desc) - - // Enforce 32-bit signed integer range - see 1.5 - // TODO By default leadingZerosAllowed = true in NumericDesc - Wacc doesnt specify (I think) but should reach consensus + val ident = lexer.lexeme.names.identifier val integer = lexer.lexeme.integer.decimal32[Int] - - // TODO Check if textDesc can handle this val charLit = lexer.lexeme.character.ascii - - // TODO Check if textDesc can handle this val stringLit = lexer.lexeme.string.ascii - val implicits = lexer.lexeme.symbol.implicits def fully[A](p: Parsley[A]): Parsley[A] = lexer.fully(p)