diff --git a/wcfg/src/main/java/net/woggioni/wson/wcfg/ListenerImpl.java b/wcfg/src/main/java/net/woggioni/wson/wcfg/ListenerImpl.java index 248d552..46bd520 100644 --- a/wcfg/src/main/java/net/woggioni/wson/wcfg/ListenerImpl.java +++ b/wcfg/src/main/java/net/woggioni/wson/wcfg/ListenerImpl.java @@ -25,6 +25,8 @@ class ListenerImpl implements WCFGListener { @Getter private final Value result; + private final List holders = new ArrayList<>(); + private interface StackLevel { Value getValue(); } @@ -74,15 +76,22 @@ class ListenerImpl implements WCFGListener { private void add2Last(Value value) { StackLevel last = stack.get(stack.size() - 1); - ArrayStackLevel asl; - ObjectStackLevel osl; - ExpressionStackLevel esl; - if ((asl = dynamicCast(last, ArrayStackLevel.class)) != null) { + if (last instanceof ArrayStackLevel asl) { asl.value.add(value); - } else if ((osl = dynamicCast(last, ObjectStackLevel.class)) != null) { - osl.value.put(osl.currentKey, value); + if(value instanceof ValueHolder holder) { + Value arrayValue = asl.getValue(); + int index = arrayValue.size() - 1; + holder.addDeleter(() -> arrayValue.set(index, holder.getDelegate())); + } + } else if (last instanceof ObjectStackLevel osl) { + String key = osl.currentKey; osl.currentKey = null; - } else if((esl = dynamicCast(last, ExpressionStackLevel.class)) != null) { + osl.value.put(key, value); + if(value instanceof ValueHolder holder) { + Value objectValue = osl.getValue(); + holder.addDeleter(() -> objectValue.put(key, holder.getDelegate())); + } + } else if(last instanceof ExpressionStackLevel esl) { esl.elements.add((ObjectValue) value); } } @@ -117,7 +126,12 @@ class ListenerImpl implements WCFGListener { @Override public void enterAssignment(WCFGParser.AssignmentContext ctx) { ObjectStackLevel osl = (ObjectStackLevel) stack.get(0); - osl.currentKey = ctx.IDENTIFIER().getText(); + String key = ctx.IDENTIFIER().getText(); + osl.currentKey = key; + ValueHolder holder = new ValueHolder(); + holders.add(holder); + holder.addDeleter(() -> result.put(key, holder.getDelegate())); + result.put(key, holder); } @Override @@ -223,4 +237,10 @@ class ListenerImpl implements WCFGListener { public void exitEveryRule(ParserRuleContext ctx) { } + + public void replaceHolders() { + for(ValueHolder holder : holders) { + holder.replace(); + } + } } diff --git a/wcfg/src/main/java/net/woggioni/wson/wcfg/ValueHolder.java b/wcfg/src/main/java/net/woggioni/wson/wcfg/ValueHolder.java index ac1ff29..f372f69 100644 --- a/wcfg/src/main/java/net/woggioni/wson/wcfg/ValueHolder.java +++ b/wcfg/src/main/java/net/woggioni/wson/wcfg/ValueHolder.java @@ -1,12 +1,22 @@ package net.woggioni.wson.wcfg; +import lombok.Getter; import lombok.Setter; import net.woggioni.wson.xface.Value; +import java.util.ArrayList; +import java.util.List; import java.util.Map; -public class ValueHolder implements Value { +class ValueHolder implements Value { + private List deleters = new ArrayList<>(); + + public void addDeleter(Runnable runnable) { + deleters.add(runnable); + } + @Setter + @Getter private Value delegate = Value.Null; @Override public Type type() { @@ -107,4 +117,10 @@ public class ValueHolder implements Value { public boolean has(String key) { return delegate.has(key); } + + public void replace() { + for(Runnable run : deleters) { + run.run(); + } + } } diff --git a/wcfg/src/test/java/net/woggioni/wson/wcfg/ParseTest.java b/wcfg/src/test/java/net/woggioni/wson/wcfg/ParseTest.java index 0a5e017..2b84c9f 100644 --- a/wcfg/src/test/java/net/woggioni/wson/wcfg/ParseTest.java +++ b/wcfg/src/test/java/net/woggioni/wson/wcfg/ParseTest.java @@ -25,7 +25,8 @@ public class ParseTest { @ValueSource(strings = { // "build.wcfg", // "test.wcfg", - "recursive.wcfg", +// "recursive.wcfg", + "recursive2.wcfg", }) public void test(String resource) { try(Reader reader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(resource))) { @@ -37,6 +38,7 @@ public class ParseTest { ListenerImpl listener = new ListenerImpl(cfg); ParseTreeWalker walker = new ParseTreeWalker(); walker.walk(listener, parser.wcfg()); + listener.replaceHolders(); Value result = listener.getResult(); new JSONDumper(cfg).dump(result, System.out); } diff --git a/wcfg/src/test/resources/recursive.wcfg b/wcfg/src/test/resources/recursive.wcfg index 18735d9..aa1ee1d 100644 --- a/wcfg/src/test/resources/recursive.wcfg +++ b/wcfg/src/test/resources/recursive.wcfg @@ -3,4 +3,6 @@ value1 := { "myself" : value1 }; -value2 := [value1]; \ No newline at end of file +value2 := [value1]; + +value3 := [1, 2, value3, null, false]; \ No newline at end of file diff --git a/wcfg/src/test/resources/recursive2.wcfg b/wcfg/src/test/resources/recursive2.wcfg new file mode 100644 index 0000000..93c6d58 --- /dev/null +++ b/wcfg/src/test/resources/recursive2.wcfg @@ -0,0 +1 @@ +value := [1, 2, value, null, false]; \ No newline at end of file