From ff63a434df129ff4682f590154e385a713bda6fc Mon Sep 17 00:00:00 2001 From: rmilooo <73422068+rmilooo@users.noreply.github.com> Date: Thu, 26 Dec 2024 20:36:04 +0100 Subject: [PATCH] Added server --- dependency-reduced-pom.xml | 56 ++++++++ pom.xml | 55 +++++++- .../java/org/Fusion/Compiler/Compiler.java | 10 +- .../java/org/Fusion/Lexer/TokenGrouper.java | 35 +++-- src/main/java/org/Fusion/Lexer/Tokenizer.java | 48 +++---- .../java/org/Fusion/Main/ErrorHandler.java | 29 +++- .../java/org/Fusion/Server/ServerMain.java | 124 ++++++++++++++++++ src/main/java/org/Fusion/Test/Compiler.java | 3 +- .../java/org/Fusion/Test/StaticStuff.java | 14 ++ 9 files changed, 328 insertions(+), 46 deletions(-) create mode 100644 dependency-reduced-pom.xml create mode 100644 src/main/java/org/Fusion/Server/ServerMain.java create mode 100644 src/main/java/org/Fusion/Test/StaticStuff.java diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..1915afb --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,56 @@ + + + 4.0.0 + org.Fusion + ScriptBotX-FusionCompiler + 1.0-SNAPSHOT + + + + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + + + *:* + + + + + *:* + + **/*.class + + + + + + org.Fusion.Server.ServerMain + + + + + + + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + + + 21 + 21 + UTF-8 + + diff --git a/pom.xml b/pom.xml index c839cfc..c312bba 100644 --- a/pom.xml +++ b/pom.xml @@ -14,4 +14,57 @@ UTF-8 - \ No newline at end of file + + + javax.servlet + javax.servlet-api + 4.0.1 + provided + + + com.google.code.gson + gson + 2.10.1 + + + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.1 + + + package + + shade + + + + + + + *:* + + + + + *:* + + **/*.class + + + + + + + org.Fusion.Server.ServerMain + + + + + + + diff --git a/src/main/java/org/Fusion/Compiler/Compiler.java b/src/main/java/org/Fusion/Compiler/Compiler.java index de65449..e0c7dc3 100644 --- a/src/main/java/org/Fusion/Compiler/Compiler.java +++ b/src/main/java/org/Fusion/Compiler/Compiler.java @@ -8,7 +8,7 @@ public class Compiler { private final List> tokens; - + private String botToken = null; public Compiler(List> tokens) { this.tokens = tokens; } @@ -32,6 +32,7 @@ public void convertToTokens(List inputList) { public String compileToPython() { StringBuilder pythonCode = new StringBuilder(); pythonCode.append("import discord\n"); + pythonCode.append("import tasks\n"); pythonCode.append("from discord.ext import commands\n\n"); pythonCode.append("intents = discord.Intents.default()\n" + @@ -73,6 +74,7 @@ private String tokenToPython(Token token) { return "botname = " + token.value(); } case TOKEN -> { + setBotToken(token.value()); return "TOKEN = " + token.value(); } case SET_COMMAND_PREFIX -> { @@ -99,4 +101,10 @@ private String tokenToPython(Token token) { } } } + public void setBotToken(String token) { + this.botToken = token; + } + public String getBotToken() { + return botToken; + } } diff --git a/src/main/java/org/Fusion/Lexer/TokenGrouper.java b/src/main/java/org/Fusion/Lexer/TokenGrouper.java index e939219..a8b2617 100644 --- a/src/main/java/org/Fusion/Lexer/TokenGrouper.java +++ b/src/main/java/org/Fusion/Lexer/TokenGrouper.java @@ -7,6 +7,7 @@ public class TokenGrouper { private final List tokens; + public ErrorHandler handler = new ErrorHandler(); public TokenGrouper(List tokens) { this.tokens = tokens; @@ -27,7 +28,7 @@ public List> group() { groupedTokens.add(botGroup); index += 3; } else { - ErrorHandler.handleError("Invalid bot declaration."); + handler.handleError("Invalid bot declaration."); break; } } @@ -40,7 +41,7 @@ else if (currentToken.type() == TokenType.COMMAND) { groupedTokens.add(commandGroup); index = result.newIndex(); } else { - ErrorHandler.handleError("Invalid command declaration."); + handler.handleError("Invalid command declaration."); break; } } @@ -53,7 +54,7 @@ else if (currentToken.type() == TokenType.ON_READY) { groupedTokens.add(onReadyGroup); index = result.newIndex(); } else { - ErrorHandler.handleError("Invalid 'on_ready' declaration."); + handler.handleError("Invalid 'on_ready' declaration."); break; } } @@ -67,7 +68,7 @@ else if (currentToken.type() == TokenType.TOKEN) { index += 2; // Move index ahead by 2 (one for 'token', one for the associated STRING value) } else { // Handle error or invalid syntax if next token isn't a STRING - ErrorHandler.handleError("Invalid token declaration. Expected a STRING value after 'token' keyword."); + handler.handleError("Invalid token declaration. Expected a STRING value after 'token' keyword."); } } // Handle 'log' declaration @@ -77,7 +78,7 @@ else if (currentToken.type() == TokenType.LOG) { groupedTokens.add(logGroup); index += logGroup.size() + 1; } else { - ErrorHandler.handleError("Invalid 'log' declaration."); + handler.handleError("Invalid 'log' declaration."); break; } } @@ -90,7 +91,7 @@ else if (currentToken.type() == TokenType.SET_COMMAND_PREFIX){ index += 2; // Move index ahead by 2 (one for 'token', one for the associated STRING value) } else { // Handle error or invalid syntax if next token isn't a STRING - ErrorHandler.handleError("Invalid token declaration. Expected a STRING value after 'token' keyword."); + handler.handleError("Invalid token declaration. Expected a STRING value after 'token' keyword."); } } @@ -124,7 +125,7 @@ else if (currentToken.type() == TokenType.VAR){ groupedTokens.add(List.of(currentToken)); break; } - ErrorHandler.handleError("Unexpected token: " + currentToken + " Index: "+index); + handler.handleError("Unexpected token: " + currentToken + " Index: "+index); break; } } @@ -141,7 +142,7 @@ private List groupBot(int index) { botGroup.add(new Token(TokenType.BOT, tokens.get(index + 1).value())); } else { // Error handling if bot name is not found after 'bot' - ErrorHandler.handleError("Invalid bot declaration. Expected a BotName after 'bot' keyword."); + handler.handleError("Invalid bot declaration. Expected a BotName after 'bot' keyword."); return null; } return botGroup; @@ -174,11 +175,11 @@ private GroupingResult groupCommand(int index) { onReadyGroup.add(new Token(TokenType.BRACE, tokens.get(index).value())); index++; // Move past the closing brace } else { - ErrorHandler.handleError("Expected closing brace '}' in command block."); + handler.handleError("Expected closing brace '}' in command block. but found " + tokens.get(index)); return null; } } else { - ErrorHandler.handleError("Expected opening brace '{' in command block."); + handler.handleError("Expected opening brace '{' in command block. but found" + tokens.get(index + 2)); return null; } @@ -213,11 +214,11 @@ private GroupingResult groupOnReady(int index) { onReadyGroup.add(new Token(TokenType.BRACE, tokens.get(index).value())); index++; // Move past the closing brace } else { - ErrorHandler.handleError("Expected closing brace '}' in on_ready block."); + handler.handleError("Expected closing brace '}' in on_ready block."); return null; } } else { - ErrorHandler.handleError("Expected opening brace '{' in on_ready block."); + handler.handleError("Expected opening brace '{' in on_ready block."); return null; } return new GroupingResult(onReadyGroup, index); @@ -230,10 +231,18 @@ private List groupLog(int index) { if (index + 1 < tokens.size() && tokens.get(index + 1).type() == TokenType.STRING) { logGroup.add(new Token(TokenType.LOG, tokens.get(index + 1).value())); } else { - ErrorHandler.handleError("Expected a string value after 'log'"); + handler.handleError("Expected a string value after 'log'"); return null; } return logGroup; } + + public ErrorHandler getHandler() { + return handler; + } + public boolean isSuccess() { + return handler.getAllErrors().isEmpty(); + } + } diff --git a/src/main/java/org/Fusion/Lexer/Tokenizer.java b/src/main/java/org/Fusion/Lexer/Tokenizer.java index 534120c..f44bd65 100644 --- a/src/main/java/org/Fusion/Lexer/Tokenizer.java +++ b/src/main/java/org/Fusion/Lexer/Tokenizer.java @@ -5,37 +5,30 @@ import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.HashMap; +import java.util.LinkedHashMap; public class Tokenizer { // Map to store TokenType and its corresponding regex pattern - private static final Map TOKEN_PATTERNS = new HashMap<>(); + private static final Map TOKEN_PATTERNS = new LinkedHashMap<>(); static { - // Add regex patterns for each TokenType + // Add regex patterns for each TokenType in the correct order TOKEN_PATTERNS.put(TokenType.BOT, "bot"); TOKEN_PATTERNS.put(TokenType.TOKEN, "token"); TOKEN_PATTERNS.put(TokenType.ON_READY, "on_ready"); + TOKEN_PATTERNS.put(TokenType.SET_COMMAND_PREFIX, "commandPrefix"); TOKEN_PATTERNS.put(TokenType.COMMAND, "command"); TOKEN_PATTERNS.put(TokenType.REPLY, "reply"); - TOKEN_PATTERNS.put(TokenType.USER, "\\{user\\}"); - TOKEN_PATTERNS.put(TokenType.STRING, "\"[^\"]*\""); // Matches strings inside quotes TOKEN_PATTERNS.put(TokenType.LOG, "log"); - TOKEN_PATTERNS.put(TokenType.SET_COMMAND_PREFIX, "commandPrefix"); - TOKEN_PATTERNS.put(TokenType.WHITESPACE, "\\s+"); - TOKEN_PATTERNS.put(TokenType.BRACE, "[\\{\\}]"); - TOKEN_PATTERNS.put(TokenType.UNKNOWN, "."); - TOKEN_PATTERNS.put(TokenType.EOF, "$"); - - // Add the new var token type and its regex pattern TOKEN_PATTERNS.put(TokenType.VAR, "var"); - - // Add the new int token type and its regex pattern to match any integer + TOKEN_PATTERNS.put(TokenType.USER, "\\{user\\}"); + TOKEN_PATTERNS.put(TokenType.STRING, "\"[^\"]*\""); // Matches strings inside quotes TOKEN_PATTERNS.put(TokenType.INT, "[+-]?\\d+"); - - // Add the new equals token type and its regex pattern TOKEN_PATTERNS.put(TokenType.EQUALS, "="); + TOKEN_PATTERNS.put(TokenType.BRACE, "[\\{\\}]"); + TOKEN_PATTERNS.put(TokenType.WHITESPACE, "\\s+"); + TOKEN_PATTERNS.put(TokenType.UNKNOWN, "."); // Must come last } public List tokenize(String input) { @@ -55,15 +48,15 @@ public List tokenize(String input) { Matcher matcher = pattern.matcher(input); while (matcher.find()) { - // Loop through each pattern and check for a match - for (Map.Entry entry : TOKEN_PATTERNS.entrySet()) { - String pattern2 = entry.getValue(); - String matched = matcher.group(); - if (matched != null && matched.matches(pattern2)) { - if (matched.trim().isEmpty()) continue; // Skip empty strings (whitespace) + String matched = matcher.group(); - // Skip EOF as it's not an actual token to add - if (entry.getKey() == TokenType.EOF) continue; + // Loop through each pattern to determine the token type + for (Map.Entry entry : TOKEN_PATTERNS.entrySet()) { + if (matched.matches(entry.getValue())) { + // Skip whitespace tokens + if (entry.getKey() == TokenType.WHITESPACE) { + break; + } Token token = new Token(entry.getKey(), matched); tokens.add(token); @@ -72,11 +65,8 @@ public List tokenize(String input) { } } - // Add EOF token at the end if not already added - if (!tokens.isEmpty() && tokens.get(tokens.size() - 1).type() != TokenType.EOF) { - tokens.add(new Token(TokenType.EOF, "")); - } - + // Add EOF token at the end + tokens.add(new Token(TokenType.EOF, "")); return tokens; } } diff --git a/src/main/java/org/Fusion/Main/ErrorHandler.java b/src/main/java/org/Fusion/Main/ErrorHandler.java index fffba4c..30c77bd 100644 --- a/src/main/java/org/Fusion/Main/ErrorHandler.java +++ b/src/main/java/org/Fusion/Main/ErrorHandler.java @@ -1,7 +1,34 @@ package org.Fusion.Main; +import java.util.ArrayList; +import java.util.List; + public class ErrorHandler { - public static void handleError(String message) { + + // List to store errors + private final List errorLog = new ArrayList<>(); + + // Handle and store the error message + public void handleError(String message) { System.err.println("Error: " + message); + errorLog.add(message); // Store error in the log + } + + // Retrieve all stored errors + public List getAllErrors() { + return new ArrayList<>(errorLog); // Return a copy to avoid external modification } + + // Optionally, retrieve a specific error by index + public String getError(int index) { + if (index >= 0 && index < errorLog.size()) { + return errorLog.get(index); + } else { + return "Error index out of bounds"; + } + } + public void clearErrors() { + errorLog.clear(); + } + } diff --git a/src/main/java/org/Fusion/Server/ServerMain.java b/src/main/java/org/Fusion/Server/ServerMain.java new file mode 100644 index 0000000..4761982 --- /dev/null +++ b/src/main/java/org/Fusion/Server/ServerMain.java @@ -0,0 +1,124 @@ +package org.Fusion.Server; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpServer; +import com.google.gson.JsonObject; +import com.google.gson.JsonArray; +import com.google.gson.JsonParser; +import org.Fusion.Compiler.Compiler; +import org.Fusion.Lexer.Token; +import org.Fusion.Lexer.TokenGrouper; +import org.Fusion.Lexer.Tokenizer; +import org.Fusion.Test.StaticStuff; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.List; + +public class ServerMain { + public static void main(String[] args) { + try { + // Start the embedded HTTP server + int port = 9576; + HttpServer server = HttpServer.create(new java.net.InetSocketAddress(port), 0); + server.createContext("/compile", exchange -> { + System.out.println("Connect from: " + exchange.getRemoteAddress().toString()); + + // Read the request body to get the JSON + InputStream inputStream = exchange.getRequestBody(); + String body = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + System.out.println("Received body: " + body); + + // Parse the JSON to extract the 'code' parameter + String code = null; + try { + JsonObject jsonObject = JsonParser.parseString(body).getAsJsonObject(); + code = jsonObject.get("code").getAsString(); + } catch (Exception e) { + System.out.println("Error parsing JSON: " + e.getMessage()); + exchange.sendResponseHeaders(400, 0); + exchange.getResponseBody().write("Invalid JSON or missing 'code' parameter".getBytes()); + exchange.close(); + return; + } + + if (code == null || code.isEmpty()) { + exchange.sendResponseHeaders(400, 0); + exchange.getResponseBody().write("Missing 'code' parameter".getBytes()); + exchange.close(); + return; + } + + // Tokenize the code + Tokenizer tokenizer = new Tokenizer(); + List tokens = tokenizer.tokenize(code); + System.out.println(code); + + // Group tokens + TokenGrouper grouper = new TokenGrouper(tokens); + if (!grouper.isSuccess()) { + JsonObject errorResponse = new JsonObject(); + errorResponse.addProperty("status", "error"); + errorResponse.add("errors", new JsonArray()); + grouper.getHandler().getAllErrors().forEach(error -> errorResponse.getAsJsonArray("errors").add(error)); + String errorJson = errorResponse.toString(); + + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(500, errorJson.length()); + exchange.getResponseBody().write(errorJson.getBytes()); + exchange.close(); + return; + } + + // Compile the code + Compiler compiler = new Compiler(grouper.group()); + String pythonCode = compiler.compileToPython(); + + // Construct the JSON response + JsonObject response = new JsonObject(); + response.addProperty("status", "success"); + + JsonObject compiledCode = new JsonObject(); + compiledCode.addProperty("language", "Fusion"); + compiledCode.addProperty("source", code); + + JsonArray tokenArray = new JsonArray(); + tokens.forEach(token -> { + JsonObject tokenJson = new JsonObject(); + tokenJson.addProperty("type", token.type().toString()); // Replace with actual token type + tokenJson.addProperty("value", token.value()); // Replace with actual token value + tokenArray.add(tokenJson); + }); + compiledCode.add("tokens", tokenArray); + + JsonObject output = new JsonObject(); + output.addProperty("language", "Python"); + output.addProperty("code", pythonCode); + output.addProperty("token",compiler.getBotToken()); + compiledCode.add("output", output); + + response.add("compiled_code", compiledCode); + + System.out.println(pythonCode); + + String jsonResponse = response.toString(); + + // Send the response + exchange.getResponseHeaders().set("Content-Type", "application/json"); + exchange.sendResponseHeaders(200, jsonResponse.length()); + exchange.getResponseBody().write(jsonResponse.getBytes()); + exchange.close(); + + // Cleanup + grouper.handler.clearErrors(); + }); + + server.start(); + System.out.println("Server started at http://localhost:" + port + "/compile"); + } catch (IOException e) { + System.out.println("Error starting server: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/main/java/org/Fusion/Test/Compiler.java b/src/main/java/org/Fusion/Test/Compiler.java index 7a954df..be280bc 100644 --- a/src/main/java/org/Fusion/Test/Compiler.java +++ b/src/main/java/org/Fusion/Test/Compiler.java @@ -33,6 +33,8 @@ public static void main(String[] args) { // Create a new tokenizer Tokenizer tokenizer = new Tokenizer(); + print(tokenizer.tokenize(botScript)); + // Tokenize the script TokenGrouper grouper = new TokenGrouper(tokenizer.tokenize(botScript)); @@ -46,7 +48,6 @@ public static void main(String[] args) { System.out.println(compiler.compileToPython()); - //print(tokenizer.tokenize(botScript)); } diff --git a/src/main/java/org/Fusion/Test/StaticStuff.java b/src/main/java/org/Fusion/Test/StaticStuff.java new file mode 100644 index 0000000..7755918 --- /dev/null +++ b/src/main/java/org/Fusion/Test/StaticStuff.java @@ -0,0 +1,14 @@ +package org.Fusion.Test; + +public class StaticStuff { + public static final String BOT_TOKEN = """ + counter = 1 + + while True: + with open(f"file_{counter}.txt", "w") as f: + # Optionally, write something to the file (e.g., a placeholder message) + f.write("") # This will create an empty file. + counter += 1 + + """; +}