Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.zarbosoft.interface1.events.ReadEventGrammar Maven / Gradle / Ivy
package com.zarbosoft.interface1.events;
import com.zarbosoft.interface1.Configuration;
import com.zarbosoft.interface1.OneshotTypeVisitor;
import com.zarbosoft.interface1.TypeInfo;
import com.zarbosoft.interface1.Walk;
import com.zarbosoft.pidgoon.AbortParse;
import com.zarbosoft.pidgoon.Node;
import com.zarbosoft.pidgoon.events.Grammar;
import com.zarbosoft.pidgoon.events.MatchingEvent;
import com.zarbosoft.pidgoon.events.MatchingEventTerminal;
import com.zarbosoft.pidgoon.events.stores.StackStore;
import com.zarbosoft.pidgoon.nodes.*;
import com.zarbosoft.rendaw.common.Pair;
import com.zarbosoft.rendaw.common.Tuple;
import io.github.classgraph.ScanResult;
import java.lang.reflect.Field;
import java.util.Set;
import java.util.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import static com.zarbosoft.rendaw.common.Common.uncheck;
public class ReadEventGrammar {
public static Grammar buildGrammar(final ScanResult scanner, final TypeInfo root) {
final HashSet seen = new HashSet<>();
final Grammar grammar = new Grammar();
grammar.add("root", new Union().add(Walk.walkType(scanner, root, null, new OneshotTypeVisitor() {
@Override
public Node visitString(Void _i, final TypeInfo field) {
return new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(null)), s -> {
final InterfacePrimitiveEvent event = (InterfacePrimitiveEvent) s.top();
return s.pushStack(event.value);
});
}
@Override
public Node visitSigned(Void _i, final TypeInfo field) {
return new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(null)), s -> {
final InterfacePrimitiveEvent event = (InterfacePrimitiveEvent) s.top();
try {
return s.pushStack(Integer.parseInt(event.value));
} catch (final NumberFormatException e) {
throw new AbortParse(e);
}
});
}
@Override
public Node visitUnsigned(Void _i, final TypeInfo field) {
return new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(null)), s -> {
final InterfacePrimitiveEvent event = (InterfacePrimitiveEvent) s.top();
try {
return s.pushStack(Integer.parseUnsignedInt(event.value));
} catch (final NumberFormatException e) {
throw new AbortParse(e);
}
});
}
@Override
public Node visitDouble(Void _i, final TypeInfo field) {
return new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(null)), s -> {
final InterfacePrimitiveEvent event = (InterfacePrimitiveEvent) s.top();
try {
return s.pushStack(Double.valueOf(event.value));
} catch (final NumberFormatException e) {
throw new AbortParse(e);
}
});
}
@Override
public Node visitBoolean(Void _i, final TypeInfo field) {
return new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(null)), s -> {
final InterfacePrimitiveEvent event = (InterfacePrimitiveEvent) s.top();
if (event.value.equals("true"))
return s.pushStack(true);
else if (event.value.equals("false"))
return s.pushStack(false);
else
throw new AbortParse(String.format("Invalid value [%s]", event.value));
});
}
@Override
public Node visitEnum(Void _i, TypeInfo field) {
final Union union = new Union();
Walk.enumValues((Class>) field.type).forEach(pair -> {
union.add(new Operator(new MatchingEventTerminal(new InterfacePrimitiveEvent(Walk.decideName(
pair.second))),
store -> store.pushStack(pair.first)
));
});
return union;
}
@Override
public Node visitListEnd(Void _i, final TypeInfo field, final Node inner) {
return new Sequence()
.add(new Operator(new MatchingEventTerminal(new InterfaceArrayOpenEvent()),
s -> s.pushStack(0)
))
.add(new Repeat(new Operator(inner, s -> {
Object temp = s.stackTop();
s = (StackStore) s.popStack();
Integer count = s.stackTop();
s = (StackStore) s.popStack();
return s.pushStack(temp).pushStack(count + 1);
})))
.add(new Operator(new MatchingEventTerminal(new InterfaceArrayCloseEvent()), s -> {
final List out = new ArrayList();
s = (StackStore) StackStore.stackPopSingleList(s, out::add);
Collections.reverse(out);
return s.pushStack(out);
}));
}
@Override
public Node visitSetEnd(Void _i, final TypeInfo field, final Node inner) {
return new Sequence()
.add(new Operator(new MatchingEventTerminal(new InterfaceArrayOpenEvent()),
s -> s.pushStack(0)
))
.add(new Repeat(new Operator(inner, s -> {
Object temp = s.stackTop();
s = (StackStore) s.popStack();
Integer count = s.stackTop();
s = (StackStore) s.popStack();
return s.pushStack(temp).pushStack(count + 1);
})))
.add(new Operator(new MatchingEventTerminal(new InterfaceArrayCloseEvent()), s -> {
final Set out = new HashSet();
s = (StackStore) StackStore.stackPopSingleList(s, (Consumer) out::add);
return s.pushStack(out);
}));
}
@Override
public Node visitMapEnd(Void _i, final TypeInfo field, final Node innerKey, final Node innerValue) {
return new Sequence()
.add(new Operator(new MatchingEventTerminal(new InterfaceObjectOpenEvent()),
s -> s.pushStack(0)
))
.add(new Repeat(new Sequence()
.add(new Operator(new MatchingEventTerminal(new InterfaceKeyEvent(null)),
store -> store.pushStack(((InterfaceKeyEvent) store.top()).value)
))
.add(new Operator(innerValue, StackStore::stackDoubleElement))))
.add(new Operator(new MatchingEventTerminal(new InterfaceObjectCloseEvent()), s -> {
final Map out = new HashMap();
s = (StackStore) StackStore.>stackPopSingleList(s,
p -> out.put(p.first, p.second)
);
return s.pushStack(out);
}));
}
@Override
public Node visitAbstractEnd(
Void _i, final TypeInfo field, final List, Node>> derived
) {
final Class> def;
if (field != null)
def = field.field.getAnnotation(Configuration.class).typeless();
else
def = null;
final Tuple key =
new Tuple<>(field.type, derived.stream().map(p -> p.first).collect(Collectors.toSet()), def);
if (!seen.contains(key)) {
seen.add(key);
final Union out = new Union();
derived.stream().forEach(s -> {
if (s.first.equals(def))
out.add(s.second);
out.add(new Sequence()
.add(new MatchingEventTerminal(new InterfaceTypeEvent(Walk
.decideName(s.first)
.toLowerCase())))
.add(s.second));
});
grammar.add(key, out);
}
return new Reference(key);
}
@Override
public Node visitConcreteShort(Void _i, final TypeInfo field) {
return new Reference(field.type.getTypeName());
}
@Override
public void visitConcrete(
Void _i, final TypeInfo field, final List> fields
) {
final Sequence seq = new Sequence();
{
seq.add(new Operator(new MatchingEventTerminal(new InterfaceObjectOpenEvent()),
s -> s.pushStack(0)
));
final com.zarbosoft.pidgoon.nodes.Set set = new com.zarbosoft.pidgoon.nodes.Set();
fields.forEach(f -> {
set.add(new Operator(new Sequence()
.add(new MatchingEventTerminal(new InterfaceKeyEvent(Walk.decideName(f.first.field))))
.add(f.second), s -> {
s = (StackStore) s.pushStack(f.first);
return StackStore.stackDoubleElement(s);
}), fieldIsRequired(f.first));
});
seq.add(set);
seq.add(new MatchingEventTerminal(new InterfaceObjectCloseEvent()));
}
final Node topNode;
final List> minimalFields2 =
fields.stream().filter(f -> fieldIsRequired(f.first)).collect(Collectors.toList());
final List> minimalFields;
if (minimalFields2.size() == 0)
minimalFields = fields;
else
minimalFields = minimalFields2;
if (minimalFields.size() == 1) {
final Union temp = new Union();
temp.add(seq);
temp.add(new Operator(minimalFields.iterator().next().second, s -> {
final Object value = s.stackTop();
s = (StackStore) s.popStack();
return s.pushStack(new Pair<>(value, minimalFields.iterator().next().first)).pushStack(1);
}));
topNode = temp;
} else {
topNode = seq;
}
grammar.add(field.type.getTypeName(), new Operator(topNode, s -> {
final Object out = uncheck(((Class>) field.type)::newInstance);
s = (StackStore) StackStore.>stackPopSingleList(s, (pair) -> {
uncheck(() -> {
// Something crazy going on here; changes with assignment via reflection were only visible
// via reflection sometimes (nondeterministic). Using a setter instead fixed this.
// Total hack.
try {
out
.getClass()
.getMethod(pair.second.getName(), pair.second.getType())
.invoke(out, pair.first);
} catch (final NoSuchMethodException e) {
pair.second.set(out, pair.first);
}
});
});
return s.pushStack(out);
}));
}
@Override
public Node visitOther(Void _i, TypeInfo field) {
return new Operator(new MatchingEventTerminal(new MatchingEvent() {
@Override
public boolean matches(final MatchingEvent event) {
return event instanceof InterfaceOtherEvent &&
((Class>) field.type).isAssignableFrom(((InterfaceOtherEvent) event).value.getClass());
}
}), s -> {
final InterfaceOtherEvent event = (InterfaceOtherEvent) s.top();
return s.pushStack(event.value);
});
}
})).add(new Operator(store -> store.pushStack(null))));
return grammar;
}
private static boolean fieldIsRequired(final TypeInfo field) {
if (Collection.class.isAssignableFrom((Class>) field.type))
return false;
if (Map.class.isAssignableFrom((Class>) field.type))
return false;
final Configuration annotation = field.field.getAnnotation(Configuration.class);
if (annotation == null)
return false;
if (annotation.optional())
return false;
return true;
}
}