From bb3ecb8a945ff516a4e1481001d7f1531e58cc2e Mon Sep 17 00:00:00 2001 From: gnembon Date: Sun, 21 Jun 2020 02:07:24 -0300 Subject: [PATCH] relaxes maps and lists notation --- src/main/java/carpet/script/Context.java | 1 + src/main/java/carpet/script/Expression.java | 20 +++++++-- src/main/java/carpet/script/Tokenizer.java | 49 ++++++++++++++++++--- 3 files changed, 61 insertions(+), 9 deletions(-) diff --git a/src/main/java/carpet/script/Context.java b/src/main/java/carpet/script/Context.java index bd020493..8d1cd434 100644 --- a/src/main/java/carpet/script/Context.java +++ b/src/main/java/carpet/script/Context.java @@ -18,6 +18,7 @@ public class Context public static final int SIGNATURE = 7; public static final int LOCALIZATION = 8; public static final int LVALUE = 9; + public static final int MAPDEF = 10; public final Map variables = new HashMap<>(); diff --git a/src/main/java/carpet/script/Expression.java b/src/main/java/carpet/script/Expression.java index 2a445ee4..1dad430c 100644 --- a/src/main/java/carpet/script/Expression.java +++ b/src/main/java/carpet/script/Expression.java @@ -492,6 +492,11 @@ public class Expression //assigns const procedure to the lhs, returning its previous value addLazyBinaryOperatorWithDelegation("->", precedence.get("def->"), false, (c, type, e, t, lv1, lv2) -> { + if (type == Context.MAPDEF) + { + Value result = ListValue.of(lv1.evalValue(c), lv2.evalValue(c)); + return (cc, tt) -> result; + } Value v1 = lv1.evalValue(c, Context.SIGNATURE); if (!(v1 instanceof FunctionSignatureValue)) throw new InternalExpressionException("'->' operator requires a function signature on the LHS"); @@ -1335,11 +1340,18 @@ public class Expression return LazyListValue.range(from, to, step); }); - addFunction("m", lv -> + addLazyFunction("m", -1, (c, t, llv) -> { + List lv = new ArrayList<>(); + for (LazyValue lazyParam : llv) { + lv.add(lazyParam.evalValue(c, Context.MAPDEF)); // none type default by design + } + Value ret; if (lv.size() == 1 && lv.get(0) instanceof LazyListValue) - return new MapValue(((LazyListValue) lv.get(0)).unroll()); - return new MapValue(lv); + ret = new MapValue(((LazyListValue) lv.get(0)).unroll()); + else + ret = new MapValue(lv); + return (cc, tt) -> ret; }); addUnaryFunction("keys", v -> { @@ -2062,7 +2074,7 @@ public class Expression Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions); // stripping lousy but acceptable semicolons - List cleanedTokens = tokenizer.fixSemicolons(); + List cleanedTokens = tokenizer.postProcess(); Tokenizer.Token lastFunction = null; Tokenizer.Token previousToken = null; diff --git a/src/main/java/carpet/script/Tokenizer.java b/src/main/java/carpet/script/Tokenizer.java index ef4c0d5e..dde3db4f 100644 --- a/src/main/java/carpet/script/Tokenizer.java +++ b/src/main/java/carpet/script/Tokenizer.java @@ -43,7 +43,7 @@ public class Tokenizer implements Iterator this.newLinesMarkers = allowNewLineMakers; } - public List fixSemicolons() + public List postProcess() { Iterable iterable = () -> this; List originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); @@ -60,9 +60,27 @@ public class Tokenizer implements Iterator current.surface = ";"; current.type = Token.TokenType.OPERATOR; } + if (current.type == Token.TokenType.MARKER) + { + // dealing with tokens in reversed order + if ("{".equals(current.surface)) + { + cleanedTokens.add(current.morphedInto(Token.TokenType.OPEN_PAREN, "(")); + current.morph(Token.TokenType.FUNCTION, "m"); + } + else if ("[".equals(current.surface)) + { + cleanedTokens.add(current.morphedInto(Token.TokenType.OPEN_PAREN, "(")); + current.morph(Token.TokenType.FUNCTION, "l"); + } + else if ("}".equals(current.surface) || "]".equals(current.surface)) + { + current.morph(Token.TokenType.CLOSE_PAREN, ")"); + } + } cleanedTokens.add(current); } - if (current.type != Token.TokenType.MARKER) + if (!(current.type == Token.TokenType.MARKER && current.surface.equals("$"))) last = current; } Collections.reverse(cleanedTokens); @@ -242,7 +260,8 @@ public class Tokenizer implements Iterator } token.type = ch == '(' ? Token.TokenType.FUNCTION : Token.TokenType.VARIABLE; } - else if (ch == '(' || ch == ')' || ch == ',') + else if (ch == '(' || ch == ')' || ch == ',' || + ch == '{' || ch == '}' || ch == '[' || ch == ']') { if (ch == '(') { @@ -252,17 +271,21 @@ public class Tokenizer implements Iterator { token.type = Token.TokenType.CLOSE_PAREN; } - else + else if (ch == ',') { token.type = Token.TokenType.COMMA; } + else + { + token.type = Token.TokenType.MARKER; + } token.append(ch); pos++; linepos++; if (expression != null && context != null && previousToken != null && previousToken.type == Token.TokenType.OPERATOR && - (ch == ')' || ch == ',') && + (ch == ')' || ch == ',' || ch == ']' || ch == '}') && !previousToken.surface.equalsIgnoreCase(";") ) throw new ExpressionException(context, this.expression, previousToken, @@ -376,6 +399,22 @@ public class Tokenizer implements Iterator public int pos; public int linepos; public int lineno; + public Token morphedInto(TokenType newType, String newSurface) + { + Token created = new Token(); + created.surface = newSurface; + created.type = newType; + created.pos = pos; + created.linepos = linepos; + created.lineno= lineno; + return created; + } + + public void morph(TokenType type, String s) + { + this.type = type; + this.surface = s; + } public void append(char c) {