mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Совместимость с Android-версией
This commit is contained in:
parent
8a000cd6c2
commit
3a21089d4e
@ -20,6 +20,10 @@ public final class Converters {
|
|||||||
int apply();
|
int apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface VoidToLongFunction {
|
||||||
|
long apply();
|
||||||
|
}
|
||||||
|
|
||||||
public interface VoidToFloatFunction {
|
public interface VoidToFloatFunction {
|
||||||
float apply();
|
float apply();
|
||||||
}
|
}
|
||||||
@ -28,6 +32,10 @@ public final class Converters {
|
|||||||
double apply();
|
double apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface VoidToCharSequenceFunction {
|
||||||
|
CharSequence apply();
|
||||||
|
}
|
||||||
|
|
||||||
public interface VoidToStringFunction {
|
public interface VoidToStringFunction {
|
||||||
String apply();
|
String apply();
|
||||||
}
|
}
|
||||||
@ -44,6 +52,14 @@ public final class Converters {
|
|||||||
void apply(int i);
|
void apply(int i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IntToLongFunction {
|
||||||
|
long apply(int i);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Int2ToVoidFunction {
|
||||||
|
void apply(int i1, int i2);
|
||||||
|
}
|
||||||
|
|
||||||
public interface Int4ToVoidFunction {
|
public interface Int4ToVoidFunction {
|
||||||
void apply(int i1, int i2, int i3, int i4);
|
void apply(int i1, int i2, int i3, int i4);
|
||||||
}
|
}
|
||||||
@ -68,6 +84,10 @@ public final class Converters {
|
|||||||
void apply(double d1, double d2, double d3, double d4);
|
void apply(double d1, double d2, double d3, double d4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface CharSequenceToVoidFunction {
|
||||||
|
void apply(CharSequence s);
|
||||||
|
}
|
||||||
|
|
||||||
public interface StringToVoidFunction {
|
public interface StringToVoidFunction {
|
||||||
void apply(String s);
|
void apply(String s);
|
||||||
}
|
}
|
||||||
@ -88,6 +108,10 @@ public final class Converters {
|
|||||||
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FunctionValue voidToLong(VoidToLongFunction f) {
|
||||||
|
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
||||||
|
}
|
||||||
|
|
||||||
public static FunctionValue voidToFloat(VoidToFloatFunction f) {
|
public static FunctionValue voidToFloat(VoidToFloatFunction f) {
|
||||||
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
||||||
}
|
}
|
||||||
@ -95,6 +119,10 @@ public final class Converters {
|
|||||||
public static FunctionValue voidToDouble(VoidToDoubleFunction f) {
|
public static FunctionValue voidToDouble(VoidToDoubleFunction f) {
|
||||||
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
return new FunctionValue(args -> NumberValue.of(f.apply()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FunctionValue voidToCharSequence(VoidToCharSequenceFunction f) {
|
||||||
|
return new FunctionValue(args -> new StringValue(f.apply().toString()));
|
||||||
|
}
|
||||||
|
|
||||||
public static FunctionValue voidToString(VoidToStringFunction f) {
|
public static FunctionValue voidToString(VoidToStringFunction f) {
|
||||||
return new FunctionValue(args -> new StringValue(f.apply()));
|
return new FunctionValue(args -> new StringValue(f.apply()));
|
||||||
@ -131,6 +159,22 @@ public final class Converters {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FunctionValue intToLong(IntToLongFunction f) {
|
||||||
|
return new FunctionValue(args -> {
|
||||||
|
Arguments.check(1, args.length);
|
||||||
|
return NumberValue.of(f.apply(args[0].asInt()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FunctionValue int2ToVoid(Int2ToVoidFunction f) {
|
||||||
|
return new FunctionValue(args -> {
|
||||||
|
Arguments.check(4, args.length);
|
||||||
|
f.apply(args[0].asInt(),
|
||||||
|
args[1].asInt());
|
||||||
|
return NumberValue.ZERO;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static FunctionValue int4ToVoid(Int4ToVoidFunction f) {
|
public static FunctionValue int4ToVoid(Int4ToVoidFunction f) {
|
||||||
return new FunctionValue(args -> {
|
return new FunctionValue(args -> {
|
||||||
Arguments.check(4, args.length);
|
Arguments.check(4, args.length);
|
||||||
@ -186,6 +230,23 @@ public final class Converters {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FunctionValue charSequenceToVoid(CharSequenceToVoidFunction f) {
|
||||||
|
return charSequenceToVoid(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FunctionValue charSequenceToVoid(CharSequenceToVoidFunction f, boolean emptyAsNull) {
|
||||||
|
return new FunctionValue(args -> {
|
||||||
|
Arguments.check(1, args.length);
|
||||||
|
final String text = args[0].asString();
|
||||||
|
if (emptyAsNull && (text != null) && (text.isEmpty())) {
|
||||||
|
f.apply(null);
|
||||||
|
} else {
|
||||||
|
f.apply(text);
|
||||||
|
}
|
||||||
|
return NumberValue.ZERO;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public static FunctionValue stringToVoid(StringToVoidFunction f) {
|
public static FunctionValue stringToVoid(StringToVoidFunction f) {
|
||||||
return new FunctionValue(args -> {
|
return new FunctionValue(args -> {
|
||||||
Arguments.check(1, args.length);
|
Arguments.check(1, args.length);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package com.annimon.ownlang.lib;
|
package com.annimon.ownlang.lib;
|
||||||
|
|
||||||
import com.annimon.ownlang.exceptions.TypeException;
|
import com.annimon.ownlang.exceptions.TypeException;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
@ -111,4 +113,17 @@ public final class ValueUtils {
|
|||||||
}
|
}
|
||||||
return ((FunctionValue) value).getValue();
|
return ((FunctionValue) value).getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T extends Number> MapValue collectNumberConstants(Class<?> clazz, Class<T> type) {
|
||||||
|
MapValue result = new MapValue(20);
|
||||||
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
|
if (!Modifier.isStatic(field.getModifiers())) continue;
|
||||||
|
if (!field.getType().equals(type)) continue;
|
||||||
|
try {
|
||||||
|
result.set(field.getName(), NumberValue.of((T) field.get(type)));
|
||||||
|
} catch (IllegalAccessException ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,9 @@
|
|||||||
package com.annimon.ownlang.modules.functional;
|
package com.annimon.ownlang.modules.functional;
|
||||||
|
|
||||||
import com.annimon.ownlang.exceptions.TypeException;
|
|
||||||
import com.annimon.ownlang.lib.Arguments;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.Function;
|
import com.annimon.ownlang.lib.Function;
|
||||||
import com.annimon.ownlang.lib.FunctionValue;
|
|
||||||
import com.annimon.ownlang.lib.Types;
|
|
||||||
import com.annimon.ownlang.lib.Value;
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.ValueUtils;
|
||||||
|
|
||||||
public final class functional_chain implements Function {
|
public final class functional_chain implements Function {
|
||||||
|
|
||||||
@ -15,11 +13,7 @@ public final class functional_chain implements Function {
|
|||||||
|
|
||||||
Value result = args[0];
|
Value result = args[0];
|
||||||
for (int i = 1; i < args.length; i += 2) {
|
for (int i = 1; i < args.length; i += 2) {
|
||||||
final Value arg = args[i];
|
final Function function = ValueUtils.consumeFunction(args[i], i);
|
||||||
if (arg.type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException(arg.toString() + " is not a function");
|
|
||||||
}
|
|
||||||
final Function function = ((FunctionValue) arg).getValue();
|
|
||||||
result = function.execute(result, args[i+1]);
|
result = function.execute(result, args[i+1]);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package com.annimon.ownlang.modules.functional;
|
package com.annimon.ownlang.modules.functional;
|
||||||
|
|
||||||
import com.annimon.ownlang.exceptions.TypeException;
|
import com.annimon.ownlang.exceptions.TypeException;
|
||||||
import com.annimon.ownlang.lib.*;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
|
import com.annimon.ownlang.lib.Function;
|
||||||
|
import com.annimon.ownlang.lib.NumberValue;
|
||||||
|
import com.annimon.ownlang.lib.Types;
|
||||||
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.ValueUtils;
|
||||||
|
|
||||||
public final class functional_dropwhile implements Function {
|
public final class functional_dropwhile implements Function {
|
||||||
|
|
||||||
@ -11,12 +17,8 @@ public final class functional_dropwhile implements Function {
|
|||||||
if (args[0].type() != Types.ARRAY) {
|
if (args[0].type() != Types.ARRAY) {
|
||||||
throw new TypeException("Array expected in first argument");
|
throw new TypeException("Array expected in first argument");
|
||||||
}
|
}
|
||||||
if (args[1].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException("Function expected in second argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Value container = args[0];
|
final Value container = args[0];
|
||||||
final Function predicate = ((FunctionValue) args[1]).getValue();
|
final Function predicate = ValueUtils.consumeFunction(args[1], 1);
|
||||||
return dropWhileArray((ArrayValue) container, predicate);
|
return dropWhileArray((ArrayValue) container, predicate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,12 +17,8 @@ public final class functional_filter implements Function {
|
|||||||
@Override
|
@Override
|
||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
Arguments.check(2, args.length);
|
Arguments.check(2, args.length);
|
||||||
if (args[1].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException("Function expected in second argument");
|
|
||||||
}
|
|
||||||
|
|
||||||
final Value container = args[0];
|
final Value container = args[0];
|
||||||
final Function predicate = ((FunctionValue) args[1]).getValue();
|
final Function predicate = ValueUtils.consumeFunction(args[1], 1);
|
||||||
if (container.type() == Types.ARRAY) {
|
if (container.type() == Types.ARRAY) {
|
||||||
return filterArray((ArrayValue) container, predicate, takeWhile);
|
return filterArray((ArrayValue) container, predicate, takeWhile);
|
||||||
}
|
}
|
||||||
@ -55,4 +51,4 @@ public final class functional_filter implements Function {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,10 @@ import com.annimon.ownlang.exceptions.TypeException;
|
|||||||
import com.annimon.ownlang.lib.Arguments;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.ArrayValue;
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
import com.annimon.ownlang.lib.Function;
|
import com.annimon.ownlang.lib.Function;
|
||||||
import com.annimon.ownlang.lib.FunctionValue;
|
|
||||||
import com.annimon.ownlang.lib.MapValue;
|
import com.annimon.ownlang.lib.MapValue;
|
||||||
import com.annimon.ownlang.lib.Types;
|
import com.annimon.ownlang.lib.Types;
|
||||||
import com.annimon.ownlang.lib.Value;
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.ValueUtils;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class functional_map implements Function {
|
public final class functional_map implements Function {
|
||||||
@ -18,22 +18,13 @@ public final class functional_map implements Function {
|
|||||||
|
|
||||||
final Value container = args[0];
|
final Value container = args[0];
|
||||||
if (container.type() == Types.ARRAY) {
|
if (container.type() == Types.ARRAY) {
|
||||||
if (args[1].type() != Types.FUNCTION) {
|
final Function mapper = ValueUtils.consumeFunction(args[1], 1);
|
||||||
throw new TypeException("Function expected in second arg");
|
|
||||||
}
|
|
||||||
final Function mapper = ((FunctionValue) args[1]).getValue();
|
|
||||||
return mapArray((ArrayValue) container, mapper);
|
return mapArray((ArrayValue) container, mapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container.type() == Types.MAP) {
|
if (container.type() == Types.MAP) {
|
||||||
if (args[1].type() != Types.FUNCTION) {
|
final Function keyMapper = ValueUtils.consumeFunction(args[1], 1);
|
||||||
throw new TypeException("Function expected in second arg");
|
final Function valueMapper = ValueUtils.consumeFunction(args[2], 2);
|
||||||
}
|
|
||||||
if (args[2].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException("Function expected in third arg");
|
|
||||||
}
|
|
||||||
final Function keyMapper = ((FunctionValue) args[1]).getValue();
|
|
||||||
final Function valueMapper = ((FunctionValue) args[2]).getValue();
|
|
||||||
return mapMap((MapValue) container, keyMapper, valueMapper);
|
return mapMap((MapValue) container, keyMapper, valueMapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,10 +4,10 @@ import com.annimon.ownlang.exceptions.TypeException;
|
|||||||
import com.annimon.ownlang.lib.Arguments;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.ArrayValue;
|
import com.annimon.ownlang.lib.ArrayValue;
|
||||||
import com.annimon.ownlang.lib.Function;
|
import com.annimon.ownlang.lib.Function;
|
||||||
import com.annimon.ownlang.lib.FunctionValue;
|
|
||||||
import com.annimon.ownlang.lib.MapValue;
|
import com.annimon.ownlang.lib.MapValue;
|
||||||
import com.annimon.ownlang.lib.Types;
|
import com.annimon.ownlang.lib.Types;
|
||||||
import com.annimon.ownlang.lib.Value;
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.ValueUtils;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public final class functional_reduce implements Function {
|
public final class functional_reduce implements Function {
|
||||||
@ -16,12 +16,9 @@ public final class functional_reduce implements Function {
|
|||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
Arguments.check(3, args.length);
|
Arguments.check(3, args.length);
|
||||||
|
|
||||||
if (args[2].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException("Function expected in third argument");
|
|
||||||
}
|
|
||||||
final Value container = args[0];
|
final Value container = args[0];
|
||||||
final Value identity = args[1];
|
final Value identity = args[1];
|
||||||
final Function accumulator = ((FunctionValue) args[2]).getValue();
|
final Function accumulator = ValueUtils.consumeFunction(args[2], 2);
|
||||||
if (container.type() == Types.ARRAY) {
|
if (container.type() == Types.ARRAY) {
|
||||||
Value result = identity;
|
Value result = identity;
|
||||||
final ArrayValue array = (ArrayValue) container;
|
final ArrayValue array = (ArrayValue) container;
|
||||||
|
@ -15,8 +15,9 @@ public final class functional_sortby implements Function {
|
|||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
Arguments.check(2, args.length);
|
Arguments.check(2, args.length);
|
||||||
if (args[0].type() != Types.ARRAY) {
|
if (args[0].type() != Types.ARRAY) {
|
||||||
throw new TypeException("Array expected in first argument");
|
throw new TypeException("Array expected at first argument");
|
||||||
}
|
}
|
||||||
|
|
||||||
final Value[] elements = ((ArrayValue) args[0]).getCopyElements();
|
final Value[] elements = ((ArrayValue) args[0]).getCopyElements();
|
||||||
final Function function = ValueUtils.consumeFunction(args[1], 1);
|
final Function function = ValueUtils.consumeFunction(args[1], 1);
|
||||||
Arrays.sort(elements, (o1, o2) -> function.execute(o1).compareTo(function.execute(o2)));
|
Arrays.sort(elements, (o1, o2) -> function.execute(o1).compareTo(function.execute(o2)));
|
||||||
|
@ -96,10 +96,7 @@ public final class functional_stream implements Function {
|
|||||||
Arrays.sort(elements);
|
Arrays.sort(elements);
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
if (args[0].type() != Types.FUNCTION) {
|
final Function comparator = ValueUtils.consumeFunction(args[0], 0);
|
||||||
throw new TypeException("Function expected in second argument");
|
|
||||||
}
|
|
||||||
final Function comparator = ((FunctionValue) args[0]).getValue();
|
|
||||||
Arrays.sort(elements, (o1, o2) -> comparator.execute(o1, o2).asInt());
|
Arrays.sort(elements, (o1, o2) -> comparator.execute(o1, o2).asInt());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -111,10 +108,7 @@ public final class functional_stream implements Function {
|
|||||||
|
|
||||||
private Value custom(Value... args) {
|
private Value custom(Value... args) {
|
||||||
Arguments.check(1, args.length);
|
Arguments.check(1, args.length);
|
||||||
if (args[0].type() != Types.FUNCTION) {
|
final Function f = ValueUtils.consumeFunction(args[0], 0);
|
||||||
throw new TypeException("Function expected in first argument");
|
|
||||||
}
|
|
||||||
final Function f = ((FunctionValue) args[0]).getValue();
|
|
||||||
final Value result = f.execute(container);
|
final Value result = f.execute(container);
|
||||||
if (result.type() == Types.ARRAY) {
|
if (result.type() == Types.ARRAY) {
|
||||||
return new StreamValue((ArrayValue) result);
|
return new StreamValue((ArrayValue) result);
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
package com.annimon.ownlang.modules.std;
|
package com.annimon.ownlang.modules.std;
|
||||||
|
|
||||||
import com.annimon.ownlang.exceptions.TypeException;
|
import com.annimon.ownlang.lib.Arguments;
|
||||||
import com.annimon.ownlang.lib.*;
|
import com.annimon.ownlang.lib.Function;
|
||||||
|
import com.annimon.ownlang.lib.FunctionValue;
|
||||||
|
import com.annimon.ownlang.lib.NumberValue;
|
||||||
|
import com.annimon.ownlang.lib.Value;
|
||||||
|
import com.annimon.ownlang.lib.ValueUtils;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
@ -10,9 +14,6 @@ public final class std_sync implements Function {
|
|||||||
@Override
|
@Override
|
||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
Arguments.check(1, args.length);
|
Arguments.check(1, args.length);
|
||||||
if (args[0].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException(args[0].toString() + " is not a function");
|
|
||||||
}
|
|
||||||
|
|
||||||
final BlockingQueue<Value> queue = new LinkedBlockingQueue<>(2);
|
final BlockingQueue<Value> queue = new LinkedBlockingQueue<>(2);
|
||||||
final Function synchronizer = (sArgs) -> {
|
final Function synchronizer = (sArgs) -> {
|
||||||
@ -23,7 +24,7 @@ public final class std_sync implements Function {
|
|||||||
}
|
}
|
||||||
return NumberValue.ZERO;
|
return NumberValue.ZERO;
|
||||||
};
|
};
|
||||||
final Function callback = ((FunctionValue) args[0]).getValue();
|
final Function callback = ValueUtils.consumeFunction(args[0], 0);
|
||||||
callback.execute(new FunctionValue(synchronizer));
|
callback.execute(new FunctionValue(synchronizer));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -34,4 +35,4 @@ public final class std_sync implements Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package com.annimon.ownlang.modules.std;
|
package com.annimon.ownlang.modules.std;
|
||||||
|
|
||||||
import com.annimon.ownlang.exceptions.TypeException;
|
|
||||||
import com.annimon.ownlang.lib.*;
|
import com.annimon.ownlang.lib.*;
|
||||||
|
|
||||||
public final class std_try implements Function {
|
public final class std_try implements Function {
|
||||||
@ -8,11 +7,8 @@ public final class std_try implements Function {
|
|||||||
@Override
|
@Override
|
||||||
public Value execute(Value... args) {
|
public Value execute(Value... args) {
|
||||||
Arguments.checkOrOr(1, 2, args.length);
|
Arguments.checkOrOr(1, 2, args.length);
|
||||||
if (args[0].type() != Types.FUNCTION) {
|
|
||||||
throw new TypeException(args[0].toString() + " is not a function");
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
return ((FunctionValue) args[0]).getValue().execute();
|
return ValueUtils.consumeFunction(args[0], 0).execute();
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
if (args.length == 2) {
|
if (args.length == 2) {
|
||||||
switch (args[1].type()) {
|
switch (args[1].type()) {
|
||||||
@ -30,4 +26,4 @@ public final class std_try implements Function {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -137,7 +137,7 @@ public final class Lexer {
|
|||||||
else if (current == '"') tokenizeText();
|
else if (current == '"') tokenizeText();
|
||||||
else if (current == '#') {
|
else if (current == '#') {
|
||||||
next();
|
next();
|
||||||
tokenizeHexNumber();
|
tokenizeHexNumber(1);
|
||||||
}
|
}
|
||||||
else if (OPERATOR_CHARS.indexOf(current) != -1) {
|
else if (OPERATOR_CHARS.indexOf(current) != -1) {
|
||||||
tokenizeOperator();
|
tokenizeOperator();
|
||||||
@ -155,7 +155,7 @@ public final class Lexer {
|
|||||||
if (current == '0' && (peek(1) == 'x' || (peek(1) == 'X'))) {
|
if (current == '0' && (peek(1) == 'x' || (peek(1) == 'X'))) {
|
||||||
next();
|
next();
|
||||||
next();
|
next();
|
||||||
tokenizeHexNumber();
|
tokenizeHexNumber(2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -170,7 +170,7 @@ public final class Lexer {
|
|||||||
addToken(TokenType.NUMBER, buffer.toString());
|
addToken(TokenType.NUMBER, buffer.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tokenizeHexNumber() {
|
private void tokenizeHexNumber(int skipped) {
|
||||||
clearBuffer();
|
clearBuffer();
|
||||||
char current = peek(0);
|
char current = peek(0);
|
||||||
while (isHexNumber(current) || (current == '_')) {
|
while (isHexNumber(current) || (current == '_')) {
|
||||||
@ -180,7 +180,8 @@ public final class Lexer {
|
|||||||
}
|
}
|
||||||
current = next();
|
current = next();
|
||||||
}
|
}
|
||||||
if (buffer.length() > 0) {
|
final int length = buffer.length();
|
||||||
|
if (length > 0) {
|
||||||
addToken(TokenType.HEX_NUMBER, buffer.toString());
|
addToken(TokenType.HEX_NUMBER, buffer.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,9 @@ public final class Parser {
|
|||||||
}
|
}
|
||||||
if (lookMatch(0, TokenType.DOT)) {
|
if (lookMatch(0, TokenType.DOT)) {
|
||||||
final List<Expression> indices = variableSuffix();
|
final List<Expression> indices = variableSuffix();
|
||||||
if (indices.isEmpty()) return expr;
|
if (indices == null || indices.isEmpty()) {
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
if (lookMatch(0, TokenType.LPAREN)) {
|
if (lookMatch(0, TokenType.LPAREN)) {
|
||||||
// next function call
|
// next function call
|
||||||
@ -452,7 +454,7 @@ public final class Parser {
|
|||||||
// x[0].prop += ...
|
// x[0].prop += ...
|
||||||
final int position = pos;
|
final int position = pos;
|
||||||
final Expression targetExpr = qualifiedName();
|
final Expression targetExpr = qualifiedName();
|
||||||
if (!(targetExpr instanceof Accessible)) {
|
if ((targetExpr == null) || !(targetExpr instanceof Accessible)) {
|
||||||
pos = position;
|
pos = position;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -759,7 +761,7 @@ public final class Parser {
|
|||||||
if (!match(TokenType.WORD)) return null;
|
if (!match(TokenType.WORD)) return null;
|
||||||
|
|
||||||
final List<Expression> indices = variableSuffix();
|
final List<Expression> indices = variableSuffix();
|
||||||
if (indices.isEmpty()) {
|
if (indices == null || indices.isEmpty()) {
|
||||||
return new VariableExpression(current.getText());
|
return new VariableExpression(current.getText());
|
||||||
}
|
}
|
||||||
return new ContainerAccessExpression(current.getText(), indices);
|
return new ContainerAccessExpression(current.getText(), indices);
|
||||||
@ -768,7 +770,7 @@ public final class Parser {
|
|||||||
private List<Expression> variableSuffix() {
|
private List<Expression> variableSuffix() {
|
||||||
// .key1.arr1[expr1][expr2].key2
|
// .key1.arr1[expr1][expr2].key2
|
||||||
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
|
if (!lookMatch(0, TokenType.DOT) && !lookMatch(0, TokenType.LBRACKET)) {
|
||||||
return Collections.emptyList();
|
return null;
|
||||||
}
|
}
|
||||||
final List<Expression> indices = new ArrayList<>();
|
final List<Expression> indices = new ArrayList<>();
|
||||||
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
while (lookMatch(0, TokenType.DOT) || lookMatch(0, TokenType.LBRACKET)) {
|
||||||
@ -805,7 +807,7 @@ public final class Parser {
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
final List<Expression> indices = variableSuffix();
|
final List<Expression> indices = variableSuffix();
|
||||||
if (indices.isEmpty()) {
|
if (indices == null || indices.isEmpty()) {
|
||||||
return strExpr;
|
return strExpr;
|
||||||
}
|
}
|
||||||
return new ContainerAccessExpression(strExpr, indices);
|
return new ContainerAccessExpression(strExpr, indices);
|
||||||
|
Loading…
Reference in New Issue
Block a user