Initial commit

This commit is contained in:
2025-04-09 07:49:30 -04:00
commit 22ee24e8ae
16 changed files with 384 additions and 0 deletions

View File

@@ -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<Token> 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;
}
}

View File

@@ -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<Token> tokens = new ArrayList<>();
private int start = 0;
private int current = 0;
private int line = 1;
public Scanner(String source) {
this.source = source;
}
List<Token> 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);
}
}

View File

@@ -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 + "]";
}
}

View File

@@ -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
}

View File

@@ -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);
}
}