commit 22ee24e8aea10a976e680a2da8947d4528411b01 Author: Michael Thomson Date: Wed Apr 9 07:49:30 2025 -0400 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3485e81 --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +.direnv/ diff --git a/jlox/.envrc b/jlox/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/jlox/.envrc @@ -0,0 +1 @@ +use flake diff --git a/jlox/.mvn/jvm.config b/jlox/.mvn/jvm.config new file mode 100644 index 0000000..e69de29 diff --git a/jlox/.mvn/maven.config b/jlox/.mvn/maven.config new file mode 100644 index 0000000..e69de29 diff --git a/jlox/.settings/org.eclipse.core.resources.prefs b/jlox/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..f9fe345 --- /dev/null +++ b/jlox/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,4 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/test/java=UTF-8 +encoding/=UTF-8 diff --git a/jlox/.settings/org.eclipse.jdt.apt.core.prefs b/jlox/.settings/org.eclipse.jdt.apt.core.prefs new file mode 100644 index 0000000..d4313d4 --- /dev/null +++ b/jlox/.settings/org.eclipse.jdt.apt.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.apt.aptEnabled=false diff --git a/jlox/.settings/org.eclipse.jdt.core.prefs b/jlox/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..a4e59d9 --- /dev/null +++ b/jlox/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,9 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 +org.eclipse.jdt.core.compiler.compliance=17 +org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore +org.eclipse.jdt.core.compiler.processAnnotations=disabled +org.eclipse.jdt.core.compiler.release=enabled +org.eclipse.jdt.core.compiler.source=17 diff --git a/jlox/.settings/org.eclipse.m2e.core.prefs b/jlox/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/jlox/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/jlox/flake.lock b/jlox/flake.lock new file mode 100644 index 0000000..1d0fc86 --- /dev/null +++ b/jlox/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1739736696, + "narHash": "sha256-zON2GNBkzsIyALlOCFiEBcIjI4w38GYOb+P+R4S8Jsw=", + "rev": "d74a2335ac9c133d6bbec9fc98d91a77f1604c1f", + "revCount": 754461, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.754461%2Brev-d74a2335ac9c133d6bbec9fc98d91a77f1604c1f/01951426-5a87-7b75-8413-1a0d9ec5ff04/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1.%2A.tar.gz" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/jlox/flake.nix b/jlox/flake.nix new file mode 100644 index 0000000..d6897e3 --- /dev/null +++ b/jlox/flake.nix @@ -0,0 +1,51 @@ +{ + description = "A Nix-flake-based Java development environment"; + + inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1.*.tar.gz"; + + outputs = { self, nixpkgs }: + let + javaVersion = 23; # Change this value to update the whole stack + + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f { + pkgs = import nixpkgs { inherit system; overlays = [ self.overlays.default ]; }; + }); + in + { + overlays.default = + final: prev: + let + jdk = prev."jdk${toString javaVersion}"; + in + { + inherit jdk; + maven = prev.maven.override { jdk_headless = jdk; }; + gradle = prev.gradle.override { java = jdk; }; + lombok = prev.lombok.override { inherit jdk; }; + }; + + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell { + packages = with pkgs; [ + gcc + gradle + jdk + maven + ncurses + patchelf + zlib + ]; + + shellHook = + let + loadLombok = "-javaagent:${pkgs.lombok}/share/java/lombok.jar"; + prev = "\${JAVA_TOOL_OPTIONS:+ $JAVA_TOOL_OPTIONS}"; + in + '' + export JAVA_TOOL_OPTIONS="${loadLombok}${prev}" + ''; + }; + }); + }; +} diff --git a/jlox/pom.xml b/jlox/pom.xml new file mode 100644 index 0000000..c42328b --- /dev/null +++ b/jlox/pom.xml @@ -0,0 +1,90 @@ + + + 4.0.0 + + com.craftinginterpreters.lox + lox + 1.0-SNAPSHOT + + lox + + http://www.example.com + + + UTF-8 + 17 + + + + + + org.junit + junit-bom + 5.11.0 + pom + import + + + + + + + org.junit.jupiter + junit-jupiter-api + test + + + + org.junit.jupiter + junit-jupiter-params + test + + + + + + + + + maven-clean-plugin + 3.4.0 + + + + maven-resources-plugin + 3.3.1 + + + maven-compiler-plugin + 3.13.0 + + + maven-surefire-plugin + 3.3.0 + + + maven-jar-plugin + 3.4.2 + + + maven-install-plugin + 3.1.2 + + + maven-deploy-plugin + 3.1.2 + + + + maven-site-plugin + 3.12.1 + + + maven-project-info-reports-plugin + 3.6.1 + + + + + diff --git a/jlox/src/main/java/com/craftinginterpreters/lox/Lox.java b/jlox/src/main/java/com/craftinginterpreters/lox/Lox.java new file mode 100644 index 0000000..f7505be --- /dev/null +++ b/jlox/src/main/java/com/craftinginterpreters/lox/Lox.java @@ -0,0 +1,64 @@ +package com.craftinginterpreters.lox; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; + +public class Lox { + static boolean hadError = false; + + public static void main(String[] args) throws IOException { + if (args.length > 1) { + System.out.println("Usage: jlox [script]"); + System.exit(64); + } else if (args.length == 1) { + runFile(args[0]); + } else { + runPrompt(); + } + } + + private static void runFile(String path) throws IOException { + byte[] bytes = Files.readAllBytes(Paths.get(path)); + run(new String(bytes, Charset.defaultCharset())); + + if (hadError) { + System.exit(65); + } + } + + private static void runPrompt() throws IOException { + InputStreamReader input = new InputStreamReader(System.in); + BufferedReader reader = new BufferedReader(input); + + for (;;) { + System.out.println("> "); + String line = reader.readLine(); + if (line == null) break; + run(line); + hadError = false; + } + } + + private static void run(String source) { + Scanner scanner = new Scanner(source); + List tokens = scanner.scanTokens(); + + for (Token token : tokens) { + System.out.println(token); + } + } + + static void error(int line, String message) { + report(line, "", message); + } + + private static void report(int line, String where, String message) { + System.err.println("[line " + line + "] Error" + where + ": " + message);); + hadError = true; + } +} diff --git a/jlox/src/main/java/com/craftinginterpreters/lox/Scanner.java b/jlox/src/main/java/com/craftinginterpreters/lox/Scanner.java new file mode 100644 index 0000000..3bdbf54 --- /dev/null +++ b/jlox/src/main/java/com/craftinginterpreters/lox/Scanner.java @@ -0,0 +1,54 @@ +package com.craftinginterpreters.lox; + +import java.util.ArrayList; +import java.util.List; + +class Scanner { + private final String source; + private final List tokens = new ArrayList<>(); + private int start = 0; + private int current = 0; + private int line = 1; + + public Scanner(String source) { + this.source = source; + } + + List scanTokens() { + while (!isAtEnd()) { + start = current; + scanToken(); + } + + tokens.add(new Token(TokenType.EOF, "", null, line)); + return tokens; + } + + private void scanToken() { + char c = advance(); + switch (c) { + case '(': addToken(TokenType.LEFT_PAREN); break; + case ')': addToken(TokenType.RIGHT_PAREN); break; + case '{': addToken(TokenType.LEFT_BRACE); break; + case '}': addToken(TokenType.RIGHT_BRACE); break; + case ',': addToken(TokenType.COMMA); break; + case '.': addToken(TokenType.DOT); break; + case '-': addToken(TokenType.MINUS); break; + case '+': addToken(TokenType.PLUS); break; + case ';': addToken(TokenType.SEMICOLON); break; + case '*': addToken(TokenType.STAR); break; + } + } + + private boolean isAtEnd() { + return current >= source.length(); + } + + private char advance() { + return source.charAt(current++); + } + + private void addToken(TokenType type) { + addToken(type, null); + } +} diff --git a/jlox/src/main/java/com/craftinginterpreters/lox/Token.java b/jlox/src/main/java/com/craftinginterpreters/lox/Token.java new file mode 100644 index 0000000..fa6d2d4 --- /dev/null +++ b/jlox/src/main/java/com/craftinginterpreters/lox/Token.java @@ -0,0 +1,20 @@ +package com.craftinginterpreters.lox; + +class Token { + final TokenType type; + final String lexeme; + final Object literal; + final int line; + + public Token(TokenType type, String lexeme, Object literal, int line) { + this.type = type; + this.lexeme = lexeme; + this.literal = literal; + this.line = line; + } + + @Override + public String toString() { + return "Token [type=" + type + ", lexeme=" + lexeme + ", literal=" + literal + "]"; + } +} diff --git a/jlox/src/main/java/com/craftinginterpreters/lox/TokenType.java b/jlox/src/main/java/com/craftinginterpreters/lox/TokenType.java new file mode 100644 index 0000000..c5967be --- /dev/null +++ b/jlox/src/main/java/com/craftinginterpreters/lox/TokenType.java @@ -0,0 +1,22 @@ +package com.craftinginterpreters.lox; + +enum TokenType { + // Single-character tokens. + LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE, + COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR, + + // One or two character tokens. + BANG, BANG_EQUAL, + EQUAL, EQUAL_EQUAL, + GREATER, GREATER_EQUAL, + LESS, LESS_EQUAL, + + // Literals. + IDENTIFIER, STRING, NUMBER, + + // Keywords. + AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR, + PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE, + + EOF +} diff --git a/jlox/src/test/java/com/craftinginterpreters/lox/AppTest.java b/jlox/src/test/java/com/craftinginterpreters/lox/AppTest.java new file mode 100644 index 0000000..f117719 --- /dev/null +++ b/jlox/src/test/java/com/craftinginterpreters/lox/AppTest.java @@ -0,0 +1,19 @@ +package com.craftinginterpreters.lox; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +/** + * Unit test for simple App. + */ +public class AppTest { + + /** + * Rigorous Test :-) + */ + @Test + public void shouldAnswerWithTrue() { + assertTrue(true); + } +}