commit 2b50e3e1f688d56b96124576a4852cca396e6416 Author: LabTS Date: Sun Jan 19 23:10:54 2025 +0000 provided code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c3923f1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.metals/ +.bsp/ +.scala-build/ +.vscode/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..49f12a5 --- /dev/null +++ b/Makefile @@ -0,0 +1,21 @@ +# NOTE: PLEASE DON'T USE THIS MAKEFILE, IT IS FOR LABTS +# it is *much* more efficient to use `scala compile .` trust me, I'm watching you. +all: +# the --server=false flag helps improve performance on LabTS by avoiding +# downloading the build-server "bloop". +# the --jvm system flag helps improve performance on LabTS by preventing +# scala-cli from downloading a whole jdk distribution on the lab machine +# the --force flag ensures that any existing built compiler is overwritten +# the --power flag is needed as `package` is an experimental "power user" feature (NOTE: use this or --assembly if anything goes wrong) +# scala --power package . --server=false --jvm system --force -o wacc-compiler +# you can use --assembly to make it built a self-contained jar, +# scala --power package . --server=false --jvm system --assembly --force -o wacc-compiler +# you can use --native to make it build a native application (requiring Scala Native), +# scala --power package . --server=false --jvm system --native --force -o wacc-compiler +# or you can use --graalvm-jvm-id graalvm-java21 --native-image to build it using graalvm + scala --power package . --server=false --jvm system --graalvm-jvm-id graalvm-java21 --native-image --force -o wacc-compiler + +clean: + scala clean . && rm -f wacc-compiler + +.PHONY: all clean diff --git a/README.md b/README.md new file mode 100644 index 0000000..954e909 --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +This is the provided git repository for the WACC compilers lab. You should work +in this repository regularly committing and pushing your work back to GitLab. + +# Provided files/directories + +## src/main + +The src/main directory is where you code for your compiler should go, and just +contains a stub hello world file with a simple calculator inside. + +## src/test +The src/test directory is where you should put the code for your tests, which +can be ran via `scala-cli test .`. The suggested framework is `scalatest`, the dependency +for which has already been included. + +## project.scala +The `project.scala` is the definition of your project's build requirements. By default, +this skeleton has added the latest stable versions of both `scalatest` and `parsley` +to the build: you should check **regularly** to see if your `parsley` needs updating +during the course of WACC! + +## compile + +The compile script can be edited to change the frontend interface to your WACC +compiler. You are free to change the language used in this script, but do not +change its name. + +## Makefile + +Your Makefile should be edited so that running 'make' in the root directory +builds your WACC compiler. Currently running 'make' will call +`scala --power package . --server=false --jvm system --graalvm-jvm-id graalvm-java21 --native-image --force -o wacc-compiler`, producing a file called +`wacc-compiler` +in the root directory of the project. If this doesn't work for whatever reason, there are a few +different alternatives you can try in the makefile. **Do not use the makefile as you're working, it's for labts/CI!** diff --git a/compile b/compile new file mode 100755 index 0000000..5505e42 --- /dev/null +++ b/compile @@ -0,0 +1,9 @@ +#!/bin/bash +# Bash front-end for your compiler. +# You are free to change the language used for this script, +# but do *not* change its name. + +# feel free to adjust to suit the specific internal flags of your compiler +./wacc-compiler "$@" + +exit $? diff --git a/project.scala b/project.scala new file mode 100644 index 0000000..7cf3277 --- /dev/null +++ b/project.scala @@ -0,0 +1,25 @@ +//> using scala 3.6 +//> using platform jvm + +// dependencies +//> using dep com.github.j-mie6::parsley::5.0.0-M10 +//> using dep com.lihaoyi::os-lib::0.11.3 +//> using test.dep org.scalatest::scalatest::3.2.19 + +// these are all sensible defaults to catch annoying issues +//> using options -deprecation -unchecked -feature +//> using options -Wimplausible-patterns -Wunused:all +//> using options -Yexplicit-nulls -Wsafe-init -Xkind-projector:underscores + +// these will help ensure you have access to the latest parsley releases +// even before they land on maven proper, or snapshot versions, if necessary. +// just in case they cause problems, however, keep them turned off unless you +// specifically need them. +// using repositories sonatype-s01:releases +// using repositories sonatype-s01:snapshots + +// these are flags used by Scala native: if you aren't using scala-native, then they do nothing +// lto-thin has decent linking times, and release-fast does not too much optimisation. +// using nativeLto thin +// using nativeGc commix +// using nativeMode release-fast diff --git a/src/main/wacc/Main.scala b/src/main/wacc/Main.scala new file mode 100644 index 0000000..898b5f8 --- /dev/null +++ b/src/main/wacc/Main.scala @@ -0,0 +1,15 @@ +package wacc + +import parsley.{Success, Failure} + +def main(args: Array[String]): Unit = { + println("hello WACC!") + + args.headOption match { + case Some(expr) => parser.parse(expr) match { + case Success(x) => println(s"$expr = $x") + case Failure(msg) => println(msg) + } + case None => println("please enter an expression") + } +} diff --git a/src/main/wacc/lexer.scala b/src/main/wacc/lexer.scala new file mode 100644 index 0000000..7a1872f --- /dev/null +++ b/src/main/wacc/lexer.scala @@ -0,0 +1,16 @@ +package wacc + +import parsley.Parsley +import parsley.token.Lexer +import parsley.token.descriptions.* + +object lexer { + private val desc = LexicalDesc.plain.copy( + // your configuration goes here + ) + private val lexer = Lexer(desc) + + val integer = lexer.lexeme.integer.decimal + val implicits = lexer.lexeme.symbol.implicits + def fully[A](p: Parsley[A]): Parsley[A] = lexer.fully(p) +} diff --git a/src/main/wacc/parser.scala b/src/main/wacc/parser.scala new file mode 100644 index 0000000..083a8d0 --- /dev/null +++ b/src/main/wacc/parser.scala @@ -0,0 +1,20 @@ +package wacc + +import parsley.{Parsley, Result} +import parsley.expr.chain + +import lexer.implicits.implicitSymbol +import lexer.{integer, fully} + +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) + ) +} diff --git a/src/test/wacc/README.md b/src/test/wacc/README.md new file mode 100644 index 0000000..5c90510 --- /dev/null +++ b/src/test/wacc/README.md @@ -0,0 +1,2 @@ +This is where you may wish to develop your tests. Remember that `scala-cli` picks up any files +in a `test` sub-directory, or files ending in `.test.scala`.