relaxes maps and lists notation
This commit is contained in:
1 parent
f09744b04e
commit
bb3ecb8a94
3 files changed
+61
-9
No files matched your search
@@ -18,6 +18,7 @@ public class Context
|
|||||||
public static final int SIGNATURE = 7;
|
public static final int SIGNATURE = 7;
|
||||||
public static final int LOCALIZATION = 8;
|
public static final int LOCALIZATION = 8;
|
||||||
public static final int LVALUE = 9;
|
public static final int LVALUE = 9;
|
||||||
|
public static final int MAPDEF = 10;
|
||||||
|
|
||||||
public final Map<String, LazyValue> variables = new HashMap<>();
|
public final Map<String, LazyValue> variables = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
@@ -492,6 +492,11 @@ public class Expression
|
|||||||
//assigns const procedure to the lhs, returning its previous value
|
//assigns const procedure to the lhs, returning its previous value
|
||||||
addLazyBinaryOperatorWithDelegation("->", precedence.get("def->"), false, (c, type, e, t, lv1, lv2) ->
|
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);
|
Value v1 = lv1.evalValue(c, Context.SIGNATURE);
|
||||||
if (!(v1 instanceof FunctionSignatureValue))
|
if (!(v1 instanceof FunctionSignatureValue))
|
||||||
throw new InternalExpressionException("'->' operator requires a function signature on the LHS");
|
throw new InternalExpressionException("'->' operator requires a function signature on the LHS");
|
||||||
@@ -1335,11 +1340,18 @@ public class Expression
|
|||||||
return LazyListValue.range(from, to, step);
|
return LazyListValue.range(from, to, step);
|
||||||
});
|
});
|
||||||
|
|
||||||
addFunction("m", lv ->
|
addLazyFunction("m", -1, (c, t, llv) ->
|
||||||
{
|
{
|
||||||
|
List<Value> 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)
|
if (lv.size() == 1 && lv.get(0) instanceof LazyListValue)
|
||||||
return new MapValue(((LazyListValue) lv.get(0)).unroll());
|
ret = new MapValue(((LazyListValue) lv.get(0)).unroll());
|
||||||
return new MapValue(lv);
|
else
|
||||||
|
ret = new MapValue(lv);
|
||||||
|
return (cc, tt) -> ret;
|
||||||
});
|
});
|
||||||
|
|
||||||
addUnaryFunction("keys", v -> {
|
addUnaryFunction("keys", v -> {
|
||||||
@@ -2062,7 +2074,7 @@ public class Expression
|
|||||||
|
|
||||||
Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions);
|
Tokenizer tokenizer = new Tokenizer(c, this, expression, allowComments, allowNewlineSubstitutions);
|
||||||
// stripping lousy but acceptable semicolons
|
// stripping lousy but acceptable semicolons
|
||||||
List<Tokenizer.Token> cleanedTokens = tokenizer.fixSemicolons();
|
List<Tokenizer.Token> cleanedTokens = tokenizer.postProcess();
|
||||||
|
|
||||||
Tokenizer.Token lastFunction = null;
|
Tokenizer.Token lastFunction = null;
|
||||||
Tokenizer.Token previousToken = null;
|
Tokenizer.Token previousToken = null;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
this.newLinesMarkers = allowNewLineMakers;
|
this.newLinesMarkers = allowNewLineMakers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Token> fixSemicolons()
|
public List<Token> postProcess()
|
||||||
{
|
{
|
||||||
Iterable<Token> iterable = () -> this;
|
Iterable<Token> iterable = () -> this;
|
||||||
List<Token> originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
|
List<Token> originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
|
||||||
@@ -60,9 +60,27 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
current.surface = ";";
|
current.surface = ";";
|
||||||
current.type = Token.TokenType.OPERATOR;
|
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);
|
cleanedTokens.add(current);
|
||||||
}
|
}
|
||||||
if (current.type != Token.TokenType.MARKER)
|
if (!(current.type == Token.TokenType.MARKER && current.surface.equals("$")))
|
||||||
last = current;
|
last = current;
|
||||||
}
|
}
|
||||||
Collections.reverse(cleanedTokens);
|
Collections.reverse(cleanedTokens);
|
||||||
@@ -242,7 +260,8 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
}
|
}
|
||||||
token.type = ch == '(' ? Token.TokenType.FUNCTION : Token.TokenType.VARIABLE;
|
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 == '(')
|
if (ch == '(')
|
||||||
{
|
{
|
||||||
@@ -252,17 +271,21 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
{
|
{
|
||||||
token.type = Token.TokenType.CLOSE_PAREN;
|
token.type = Token.TokenType.CLOSE_PAREN;
|
||||||
}
|
}
|
||||||
else
|
else if (ch == ',')
|
||||||
{
|
{
|
||||||
token.type = Token.TokenType.COMMA;
|
token.type = Token.TokenType.COMMA;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token.type = Token.TokenType.MARKER;
|
||||||
|
}
|
||||||
token.append(ch);
|
token.append(ch);
|
||||||
pos++;
|
pos++;
|
||||||
linepos++;
|
linepos++;
|
||||||
|
|
||||||
if (expression != null && context != null && previousToken != null &&
|
if (expression != null && context != null && previousToken != null &&
|
||||||
previousToken.type == Token.TokenType.OPERATOR &&
|
previousToken.type == Token.TokenType.OPERATOR &&
|
||||||
(ch == ')' || ch == ',') &&
|
(ch == ')' || ch == ',' || ch == ']' || ch == '}') &&
|
||||||
!previousToken.surface.equalsIgnoreCase(";")
|
!previousToken.surface.equalsIgnoreCase(";")
|
||||||
)
|
)
|
||||||
throw new ExpressionException(context, this.expression, previousToken,
|
throw new ExpressionException(context, this.expression, previousToken,
|
||||||
@@ -376,6 +399,22 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|
|||||||
public int pos;
|
public int pos;
|
||||||
public int linepos;
|
public int linepos;
|
||||||
public int lineno;
|
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)
|
public void append(char c)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in new issue
Block a user