From a45f4109d8c31f27916dd3bf83c2ea3a3e3bc3f6 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 30 Aug 2024 21:00:20 +0300 Subject: [PATCH] feat: add environment in Source --- .../topchetoeu/jscript/common/Compiler.java | 2 +- .../topchetoeu/jscript/common/json/JSON.java | 2 +- .../jscript/common/parsing/ParseRes.java | 4 -- .../jscript/common/parsing/Parser.java | 5 ++ .../jscript/common/parsing/Parsing.java | 2 - .../jscript/common/parsing/Source.java | 11 +++- .../compilation/AssignableStatement.java | 50 ---------------- .../jscript/compilation/ExpressionParser.java | 5 ++ .../jscript/compilation/JavaScript.java | 59 ++++++++++--------- .../values/operations/CallStatement.java | 2 +- .../values/primitives/NumberValue.java | 4 +- .../values/primitives/StringValue.java | 2 +- 12 files changed, 56 insertions(+), 92 deletions(-) create mode 100644 src/java/me/topchetoeu/jscript/common/parsing/Parser.java create mode 100644 src/java/me/topchetoeu/jscript/compilation/ExpressionParser.java diff --git a/src/java/me/topchetoeu/jscript/common/Compiler.java b/src/java/me/topchetoeu/jscript/common/Compiler.java index 5944988..1d6e7d2 100644 --- a/src/java/me/topchetoeu/jscript/common/Compiler.java +++ b/src/java/me/topchetoeu/jscript/common/Compiler.java @@ -12,7 +12,7 @@ import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; public interface Compiler { public static final Compiler DEFAULT = (env, filename, raw) -> { - var res = JavaScript.compile(filename, raw); + var res = JavaScript.compile(env, filename, raw); var body = res.body(); DebugContext.get(env).onSource(filename, raw); registerFunc(env, body, res); diff --git a/src/java/me/topchetoeu/jscript/common/json/JSON.java b/src/java/me/topchetoeu/jscript/common/json/JSON.java index 74434ba..e93f3f3 100644 --- a/src/java/me/topchetoeu/jscript/common/json/JSON.java +++ b/src/java/me/topchetoeu/jscript/common/json/JSON.java @@ -101,7 +101,7 @@ public class JSON { public static JSONElement parse(Filename filename, String raw) { if (filename == null) filename = new Filename("jscript", "json"); - var res = parseValue(new Source(filename, raw), 0); + var res = parseValue(new Source(null, filename, raw), 0); if (res.isFailed()) throw new SyntaxException(null, "Invalid JSON given."); else if (res.isError()) throw new SyntaxException(null, res.error); else return JSONElement.of(res.result); diff --git a/src/java/me/topchetoeu/jscript/common/parsing/ParseRes.java b/src/java/me/topchetoeu/jscript/common/parsing/ParseRes.java index d50d289..c1af040 100644 --- a/src/java/me/topchetoeu/jscript/common/parsing/ParseRes.java +++ b/src/java/me/topchetoeu/jscript/common/parsing/ParseRes.java @@ -1,10 +1,6 @@ package me.topchetoeu.jscript.common.parsing; public class ParseRes { - public static interface Parser { - public ParseRes parse(Source src, int i); - } - public static enum State { SUCCESS, FAILED, diff --git a/src/java/me/topchetoeu/jscript/common/parsing/Parser.java b/src/java/me/topchetoeu/jscript/common/parsing/Parser.java new file mode 100644 index 0000000..d40f4f4 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/common/parsing/Parser.java @@ -0,0 +1,5 @@ +package me.topchetoeu.jscript.common.parsing; + +public interface Parser { + public ParseRes parse(Source src, int i); +} \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/common/parsing/Parsing.java b/src/java/me/topchetoeu/jscript/common/parsing/Parsing.java index a0a5f27..62e2cdd 100644 --- a/src/java/me/topchetoeu/jscript/common/parsing/Parsing.java +++ b/src/java/me/topchetoeu/jscript/common/parsing/Parsing.java @@ -3,8 +3,6 @@ package me.topchetoeu.jscript.common.parsing; import me.topchetoeu.jscript.compilation.values.constants.NumberStatement; import me.topchetoeu.jscript.runtime.exceptions.SyntaxException; -// TODO: this has to be rewritten -// @SourceFile public class Parsing { public static boolean isDigit(Character c) { return c != null && c >= '0' && c <= '9'; diff --git a/src/java/me/topchetoeu/jscript/common/parsing/Source.java b/src/java/me/topchetoeu/jscript/common/parsing/Source.java index 6fa9095..d04c1e4 100644 --- a/src/java/me/topchetoeu/jscript/common/parsing/Source.java +++ b/src/java/me/topchetoeu/jscript/common/parsing/Source.java @@ -2,7 +2,10 @@ package me.topchetoeu.jscript.common.parsing; import java.util.function.Predicate; +import me.topchetoeu.jscript.common.environment.Environment; + public class Source { + public final Environment env; public final Filename filename; public final String src; @@ -41,7 +44,10 @@ public class Source { return src.substring(start, end); } - public Source(Filename filename, String src) { + public Source(Environment env, Filename filename, String src) { + if (env == null) this.env = new Environment(); + else this.env = env; + this.filename = filename; this.src = src; @@ -63,4 +69,7 @@ public class Source { System.arraycopy(lineStarts, 0, newArr, 0, n); lineStarts = newArr; } + public Source(String src) { + this(null, null, src); + } } diff --git a/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java index a0e2175..40f9930 100644 --- a/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java @@ -4,54 +4,4 @@ import me.topchetoeu.jscript.common.Operation; public interface AssignableStatement { public abstract Statement toAssign(Statement val, Operation operation); - - // private static final Map operations = Map.ofEntries( - // Map.entry("*=", Operation.MULTIPLY), - // Map.entry("/=", Operation.DIVIDE), - // Map.entry("%=", Operation.MODULO), - // Map.entry("-=", Operation.SUBTRACT), - // Map.entry("+=", Operation.ADD), - // Map.entry(">>=", Operation.SHIFT_RIGHT), - // Map.entry("<<=", Operation.SHIFT_LEFT), - // Map.entry(">>>=", Operation.USHIFT_RIGHT), - // Map.entry("&=", Operation.AND), - // Map.entry("^=", Operation.XOR), - // Map.entry("|=", Operation.OR) - // ); - // private static final List operatorsByLength = operations.keySet().stream().sorted().collect(Collectors.toList()); - - - // public static ParseRes parse(Source src, int i, Statement prev, int precedence) { - // if (precedence > 2) return ParseRes.failed(); - - // var n = Parsing.skipEmpty(src, i); - - // for (var op : operatorsByLength) { - // if (!src.is(i + n, op)) continue; - // n += op.length() + 1; - - // if (!(prev instanceof AssignableStatement)) { - // return ParseRes.error(src.loc(i + n), "Invalid expression on left hand side of assign operator"); - // } - - // var res = Parsing.parseValue(src, i + n, 2); - // if (!res.isSuccess()) return res.chainError(src.loc(i + n), String.format("Expected a value after the '%s=' operator", op)); - // n += res.n; - - // return ParseRes.res(((AssignableStatement)prev).toAssign(res.result, operations.get(op)), n); - // } - - // if (!src.is(i + n, "=")) return ParseRes.failed(); - // n++; - - // if (!(prev instanceof AssignableStatement)) { - // return ParseRes.error(src.loc(i + n), "Invalid expression on left hand side of assign operator"); - // } - - // var res = Parsing.parseValue(src, i + n, 2); - // if (!res.isSuccess()) return res.chainError(src.loc(i + n), "Expected a value after the '=' operator"); - // n += res.n; - - // return ParseRes.res(((AssignableStatement)prev).toAssign(res.result, null), n); - // } } diff --git a/src/java/me/topchetoeu/jscript/compilation/ExpressionParser.java b/src/java/me/topchetoeu/jscript/compilation/ExpressionParser.java new file mode 100644 index 0000000..cfbfafc --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/ExpressionParser.java @@ -0,0 +1,5 @@ +package me.topchetoeu.jscript.compilation; + +public class ExpressionParser { + +} diff --git a/src/java/me/topchetoeu/jscript/compilation/JavaScript.java b/src/java/me/topchetoeu/jscript/compilation/JavaScript.java index a07e92b..949a3ea 100644 --- a/src/java/me/topchetoeu/jscript/compilation/JavaScript.java +++ b/src/java/me/topchetoeu/jscript/compilation/JavaScript.java @@ -5,6 +5,7 @@ import java.util.List; import java.util.Set; import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.common.parsing.ParseRes; import me.topchetoeu.jscript.common.parsing.Parsing; @@ -72,8 +73,8 @@ public class JavaScript { public static ParseRes parseSimple(Source src, int i, boolean statement) { return ParseRes.first(src, i, - (a, b) -> statement ? ParseRes.failed() : ObjectStatement.parse(a, b), - (a, b) -> statement ? ParseRes.failed() : FunctionStatement.parseFunction(a, b, false), + (s, j) -> statement ? ParseRes.failed() : ObjectStatement.parse(s, j), + (s, j) -> statement ? ParseRes.failed() : FunctionStatement.parseFunction(s, j, false), JavaScript::parseLiteral, StringStatement::parse, RegexStatement::parse, @@ -196,27 +197,6 @@ public class JavaScript { return res.addN(n); } - public static Statement[] parse(Filename filename, String raw) { - var src = new Source(filename, raw); - var list = new ArrayList(); - int i = 0; - - while (true) { - if (i >= src.size()) break; - - var res = parseStatement(src, i); - - if (res.isError()) throw new SyntaxException(src.loc(i), res.error); - else if (res.isFailed()) throw new SyntaxException(src.loc(i), "Unexpected syntax"); - - i += res.n; - - list.add(res.result); - } - - return list.toArray(Statement[]::new); - } - public static ParseRes parseStatementEnd(Source src, int i) { var n = Parsing.skipEmpty(src, i); if (i >= src.size()) return ParseRes.res(true, n + 1); @@ -231,10 +211,6 @@ public class JavaScript { return ParseRes.failed(); } - public static boolean checkVarName(String name) { - return !JavaScript.reserved.contains(name); - } - public static ParseRes> parseParamList(Source src, int i) { var n = Parsing.skipEmpty(src, i); @@ -271,6 +247,31 @@ public class JavaScript { return ParseRes.res(args, n); } + public static Statement[] parse(Environment env, Filename filename, String raw) { + var src = new Source(env, filename, raw); + var list = new ArrayList(); + int i = 0; + + while (true) { + if (i >= src.size()) break; + + var res = parseStatement(src, i); + + if (res.isError()) throw new SyntaxException(src.loc(i), res.error); + else if (res.isFailed()) throw new SyntaxException(src.loc(i), "Unexpected syntax"); + + i += res.n; + + list.add(res.result); + } + + return list.toArray(Statement[]::new); + } + + public static boolean checkVarName(String name) { + return !JavaScript.reserved.contains(name); + } + public static CompileResult compile(Statement ...statements) { var target = new CompileResult(new LocalScopeRecord()); var stm = new CompoundStatement(null, true, statements); @@ -296,7 +297,7 @@ public class JavaScript { return target; } - public static CompileResult compile(Filename filename, String raw) { - return JavaScript.compile(JavaScript.parse(filename, raw)); + public static CompileResult compile(Environment env, Filename filename, String raw) { + return JavaScript.compile(JavaScript.parse(env, filename, raw)); } } diff --git a/src/java/me/topchetoeu/jscript/compilation/values/operations/CallStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/operations/CallStatement.java index ad022e1..306c61c 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/operations/CallStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/operations/CallStatement.java @@ -77,7 +77,7 @@ public class CallStatement extends Statement { var bracket = JSON.stringify(JSONElement.string(val)); if (!bracket.substring(1, bracket.length() - 1).equals(val)) return res + "[" + bracket + "]"; - if (Parsing.parseIdentifier(new Source(null, val), 0).n != val.length()) return res + "[" + bracket + "]"; + if (Parsing.parseIdentifier(new Source(val), 0).n != val.length()) return res + "[" + bracket + "]"; return res + "." + val; } diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java index bfd4aac..09c2029 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java @@ -43,7 +43,7 @@ public final class NumberValue extends PrimitiveValue { if (radix < 2 || radix > 36) return new NumberValue(Double.NaN); str = str.trim(); - var res = Parsing.parseInt(new Source(null, str), 0, "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, radix), true); + var res = Parsing.parseInt(new Source(str), 0, "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, radix), true); if (res.isSuccess()) { if (relaxed || res.n == str.length()) return new NumberValue(res.result); } @@ -51,7 +51,7 @@ public final class NumberValue extends PrimitiveValue { } public static NumberValue parseFloat(String str, boolean relaxed) { str = str.trim(); - var res = Parsing.parseFloat(new Source(null, str), 0, true); + var res = Parsing.parseFloat(new Source(str), 0, true); if (res.isSuccess()) { if (relaxed || res.n == str.length()) return new NumberValue(res.result); } diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java index 0da0f7c..ec87847 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java @@ -20,7 +20,7 @@ public final class StringValue extends PrimitiveValue { @Override public NumberValue toNumber(Environment ext) { var val = value.trim(); if (val.equals("")) return new NumberValue(0); - var res = Parsing.parseNumber(new Source(null, val), 0, true); + var res = Parsing.parseNumber(new Source(val), 0, true); if (res.isSuccess() && res.n == val.length()) return new NumberValue(res.result); else return new NumberValue(Double.NaN);