From 238f661bbe56dbe295520989e3324e4826a70b70 Mon Sep 17 00:00:00 2001 From: issy Date: Sun, 17 Nov 2024 15:30:32 +0000 Subject: [PATCH] WIP --- src/main/java/com/issy/Walker.java | 23 +++++++++++++ src/main/java/com/issy/compiler/Lexer.java | 34 ++++++++++++++----- .../java/com/issy/compiler/TokenContext.java | 11 +++++- .../java/com/issy/compiler/CompilerTest.java | 16 ++++----- 4 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/issy/Walker.java diff --git a/src/main/java/com/issy/Walker.java b/src/main/java/com/issy/Walker.java new file mode 100644 index 0000000..ad5be4c --- /dev/null +++ b/src/main/java/com/issy/Walker.java @@ -0,0 +1,23 @@ +package com.issy; + +import com.issy.compiler.FileMatcher; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Stream; + +public class Walker { + + public List walk(String startPath, FileMatcher fileMatcher) { + try (Stream pathStream = Files.walk(Path.of(startPath))) { + return pathStream.map(Path::toString).filter(fileMatcher::matches).toList(); + } catch (IOException e) { + throw new RuntimeException("Error reading file: " + e.getMessage()); + } catch (SecurityException e) { + throw new RuntimeException("Not permitted to read file: " + e.getMessage()); + } + } + +} diff --git a/src/main/java/com/issy/compiler/Lexer.java b/src/main/java/com/issy/compiler/Lexer.java index 124428a..8964f8a 100644 --- a/src/main/java/com/issy/compiler/Lexer.java +++ b/src/main/java/com/issy/compiler/Lexer.java @@ -6,6 +6,7 @@ import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; +import java.util.stream.Stream; import static com.issy.compiler.Token.*; @@ -22,36 +23,37 @@ public Lexer(String input) { public List parse() { final List tokens = new ArrayList<>(); while (cursor.getValue() < input.length()) { - String currentChar = charAt(cursor.getValue()); + final Position position = positionAt(cursor.getValue()); + final String currentChar = charAt(cursor.getValue()); if (currentChar.equals("\"")) { String munched = collectUntil(stringLiteralTerminationPredicate(cursor.getValue())); - tokens.add(new TokenContext(STRING, parseStringLiteral(munched))); + tokens.add(TokenContext.withPosition(STRING, parseStringLiteral(munched), position)); cursor.increment(); } else if (currentChar.equals("(")) { - tokens.add(new TokenContext(OPEN_PAREN, "(")); + tokens.add(TokenContext.withPosition(OPEN_PAREN, "(", position)); cursor.increment(); } else if (currentChar.equals(")")) { - tokens.add(new TokenContext(CLOSE_PAREN, ")")); + tokens.add(TokenContext.withPosition(CLOSE_PAREN, ")", position)); cursor.increment(); } else if (currentChar.equals("!")) { - tokens.add(new TokenContext(NOT, "!")); + tokens.add(TokenContext.withPosition(NOT, "!", position)); cursor.increment(); } else if (currentChar.equals("&")) { if (charAt(cursor.increment()).equals("&")) { - tokens.add(new TokenContext(OR, "&&")); + tokens.add(TokenContext.withPosition(OR, "&&", position)); } else { throw new RuntimeException("Expected &&"); } cursor.increment(); } else if (currentChar.equals("|")) { if (charAt(cursor.increment()).equals("|")) { - tokens.add(new TokenContext(OR, "||")); + tokens.add(TokenContext.withPosition(OR, "||", position)); } else { throw new RuntimeException("Expected ||"); } cursor.increment(); } else if (Character.isLetter(input.charAt(cursor.getValue()))) { - tokens.add(new TokenContext(IDENTIFIER, collectUntil(identifierNameTerminationPredicate()))); + tokens.add(TokenContext.withPosition(IDENTIFIER, collectUntil(identifierNameTerminationPredicate()), position)); } else if (currentChar.equals(" ") || currentChar.equals("\n") || currentChar.equals("\t") || currentChar.equals("\r")) { cursor.increment(); continue; @@ -93,6 +95,19 @@ private String charAt(int index) { return String.valueOf(input.charAt(index)); } + private Position positionAt(int index) { + List lines = input.lines().toList(); + int count = 0; + for (int i = 0; i < lines.size(); i++) { + String line = lines.get(i); + count += line.length(); + if (count > index) { + return new Position(i + 1, index % count); + } + } + throw new IllegalArgumentException("Index exceeds string length"); + } + private static class Cursor { private int value; @@ -126,4 +141,7 @@ public boolean atLimit() { } } + public static record Position(Integer line, Integer column) { + } + } diff --git a/src/main/java/com/issy/compiler/TokenContext.java b/src/main/java/com/issy/compiler/TokenContext.java index 4efad77..3b725cb 100644 --- a/src/main/java/com/issy/compiler/TokenContext.java +++ b/src/main/java/com/issy/compiler/TokenContext.java @@ -1,5 +1,14 @@ package com.issy.compiler; // TODO: Include line:col position data for better error messages -public record TokenContext(Token token, String value) { +public record TokenContext(Token token, String value, Integer line, Integer column) { + + public static TokenContext withPosition(Token token, String value, Lexer.Position position) { + return new TokenContext(token, value, position.line(), position.column()); + } + + public String getFormattedPosition() { + return String.format("%d:%d", line + 1, column); + } + } diff --git a/src/test/java/com/issy/compiler/CompilerTest.java b/src/test/java/com/issy/compiler/CompilerTest.java index ef6f3a6..40cfd92 100644 --- a/src/test/java/com/issy/compiler/CompilerTest.java +++ b/src/test/java/com/issy/compiler/CompilerTest.java @@ -12,14 +12,14 @@ class CompilerTest { void canCompile() { // Given final List tokenContexts = List.of( - new TokenContext(Token.IDENTIFIER, Identifier.HAS_FILE_EXTENSION.getName()), - new TokenContext(Token.OPEN_PAREN, "("), - new TokenContext(Token.STRING, "\".tsx\""), - new TokenContext(Token.CLOSE_PAREN, ")"), - new TokenContext(Token.AND, "&&"), - new TokenContext(Token.IDENTIFIER, Identifier.IS_IN_BASE_DIRECTORY.getName()), - new TokenContext(Token.OPEN_PAREN, "("), - new TokenContext(Token.CLOSE_PAREN, ")") + new TokenContext(Token.IDENTIFIER, Identifier.HAS_FILE_EXTENSION.getName(), 0, 0), + new TokenContext(Token.OPEN_PAREN, "(", 0, 0), + new TokenContext(Token.STRING, "\".tsx\"", 0, 0), + new TokenContext(Token.CLOSE_PAREN, ")", 0, 0), + new TokenContext(Token.AND, "&&", 0, 0), + new TokenContext(Token.IDENTIFIER, Identifier.IS_IN_BASE_DIRECTORY.getName(), 0, 0), + new TokenContext(Token.OPEN_PAREN, "(", 0, 0), + new TokenContext(Token.CLOSE_PAREN, ")", 0, 0) ); final Compiler compiler = new Compiler(tokenContexts);