added copy and fixed cleaning of semicolons

This commit is contained in:
gnembon committed 2019-11-04 00:35:32 -04:00
1 parent e2c614c6de
commit efb87c8497
7 files changed
+86 -17

No files matched your search

+3 -16
View File
@@ -46,7 +46,6 @@ import java.util.function.Supplier;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import static java.lang.Math.abs; import static java.lang.Math.abs;
import static java.lang.Math.max; import static java.lang.Math.max;
@@ -2775,6 +2774,8 @@ public class Expression implements Cloneable
{ {
addUnaryFunction("hash_code", v -> new NumericValue(v.hashCode())); addUnaryFunction("hash_code", v -> new NumericValue(v.hashCode()));
addUnaryFunction("copy", Value::deepcopy);
addLazyFunction("bool", 1, (c, t, lv) -> { addLazyFunction("bool", 1, (c, t, lv) -> {
Value v = lv.get(0).evalValue(c, Context.BOOLEAN); Value v = lv.get(0).evalValue(c, Context.BOOLEAN);
if (v instanceof StringValue) if (v instanceof StringValue)
@@ -3044,21 +3045,7 @@ public class Expression implements Cloneable
Tokenizer tokenizer = new Tokenizer(this, expression, allowComments, allowNewlineSubstitutions); Tokenizer tokenizer = new Tokenizer(this, expression, allowComments, allowNewlineSubstitutions);
// stripping lousy but acceptable semicolons // stripping lousy but acceptable semicolons
Iterable<Tokenizer.Token> iterable = () -> tokenizer; List<Tokenizer.Token> cleanedTokens = tokenizer.fixSemicolons();
List<Tokenizer.Token> originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
List<Tokenizer.Token> cleanedTokens = new ArrayList<>();
Tokenizer.Token last = null;
while (originalTokens.size() > 0)
{
Tokenizer.Token current = originalTokens.remove(originalTokens.size()-1);
if (current.type != Tokenizer.Token.TokenType.OPERATOR
|| !current.surface.equals(";")
|| (last != null && last.type != Tokenizer.Token.TokenType.CLOSE_PAREN && last.type != Tokenizer.Token.TokenType.COMMA && !last.surface.equals(";")))
cleanedTokens.add(current);
if (current.type != Tokenizer.Token.TokenType.MARKER)
last = current;
}
Collections.reverse(cleanedTokens);
Tokenizer.Token lastFunction = null; Tokenizer.Token lastFunction = null;
Tokenizer.Token previousToken = null; Tokenizer.Token previousToken = null;
@@ -4,8 +4,11 @@ import carpet.script.exception.ExpressionException;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
/** /**
* Expression tokenizer that allows to iterate over a {@link String} * Expression tokenizer that allows to iterate over a {@link String}
@@ -38,6 +41,32 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
this.newLinesMarkers = allowNewLineMakers; this.newLinesMarkers = allowNewLineMakers;
} }
public List<Token> fixSemicolons()
{
Iterable<Token> iterable = () -> this;
List<Token> originalTokens = StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList());
List<Token> cleanedTokens = new ArrayList<>();
Token last = null;
while (originalTokens.size() > 0)
{
Token current = originalTokens.remove(originalTokens.size()-1);
if (!isSemicolon(current)
|| (last != null && last.type != Token.TokenType.CLOSE_PAREN && last.type != Token.TokenType.COMMA && !isSemicolon(last)))
{
if (isSemicolon(current))
{
current.surface = ";";
current.type = Token.TokenType.OPERATOR;
}
cleanedTokens.add(current);
}
if (current.type != Token.TokenType.MARKER)
last = current;
}
Collections.reverse(cleanedTokens);
return cleanedTokens;
}
@Override @Override
public boolean hasNext() public boolean hasNext()
{ {
@@ -60,6 +89,12 @@ public class Tokenizer implements Iterator<Tokenizer.Token>
|| (ch >= 'A' && ch <= 'F'); || (ch >= 'A' && ch <= 'F');
} }
public static boolean isSemicolon(Token tok)
{
return ( tok.type == Token.TokenType.OPERATOR && tok.surface.equals(";") )
|| (tok.type == Token.TokenType.UNARY_OPERATOR && tok.surface.equals(";u") );
}
public static List<Token> simplepass(String input) public static List<Token> simplepass(String input)
{ {
Tokenizer tok = new Tokenizer(null, input, false, false); Tokenizer tok = new Tokenizer(null, input, false, false);
@@ -58,6 +58,7 @@ import java.util.stream.Collectors;
import static carpet.script.value.NBTSerializableValue.nameFromRegistryId; import static carpet.script.value.NBTSerializableValue.nameFromRegistryId;
// TODO: decide whether copy(entity) should duplicate entity in the world.
public class EntityValue extends Value public class EntityValue extends Value
{ {
private Entity entity; private Entity entity;
@@ -43,6 +43,15 @@ public class ListValue extends AbstractListValue implements ContainerValueInterf
{ {
return new ListValue(items); return new ListValue(items);
} }
@Override
public Value deepcopy()
{
List<Value> copyItems = new ArrayList<>(items.size());
for (Value entry: items) copyItems.add(entry.deepcopy());
return new ListValue(copyItems);
}
public ListValue(Collection<? extends Value> list) public ListValue(Collection<? extends Value> list)
{ {
items = new ArrayList<>(); items = new ArrayList<>();
@@ -63,6 +63,15 @@ public class MapValue extends AbstractListValue implements ContainerValueInterfa
{ {
return new MapValue(map); return new MapValue(map);
} }
@Override
public Value deepcopy()
{
Map<Value, Value> copyMap = new HashMap<>();
map.forEach((key, value) -> copyMap.put(key.deepcopy(), value.deepcopy()));
return new MapValue(copyMap);
}
public MapValue(Map<Value,Value> other) public MapValue(Map<Value,Value> other)
{ {
map = new HashMap<>(other); map = new HashMap<>(other);
@@ -95,11 +95,26 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return value; return value;
} }
@Override
public Value clone() public Value clone()
{ {
return new NBTSerializableValue(getTag().copy()); // sets only nbttag, even if emtpy;
NBTSerializableValue copy = new NBTSerializableValue(nbtTag);
copy.nbtSupplier = this.nbtSupplier;
copy.nbtString = this.nbtString;
return copy;
} }
@Override
public Value deepcopy()
{
NBTSerializableValue copy = (NBTSerializableValue) clone();
// same fields except when tag is set - need to copy it.
if (copy.nbtTag != null)
copy.nbtTag = copy.getTag().copy();
return copy;
}
public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset) public static InventoryLocator locateInventory(CarpetContext c, List<LazyValue> params, int offset)
{ {
@@ -189,4 +189,17 @@ public abstract class Value implements Comparable<Value>, Cloneable
if (stringVal.isEmpty()) return 0; if (stringVal.isEmpty()) return 0;
return ("s"+stringVal).hashCode(); return ("s"+stringVal).hashCode();
} }
public Value deepcopy()
{
try
{
return (Value)this.clone();
}
catch (CloneNotSupportedException e)
{
// should never happen
throw new InternalExpressionException("Cannot make a copy of value: "+this);
}
};
} }