Files
prog-intro-2025/java/expression/common/NodeRenderer.java
2026-01-29 23:20:12 +05:00

97 lines
3.3 KiB
Java

package expression.common;
import base.ExtendedRandom;
import java.util.List;
import java.util.Map;
/**
* @author Georgiy Korneev (kgeorgiy@kgeorgiy.info)
*/
public class NodeRenderer<C> {
public static final String PAREN = "[";
public static final List<Paren> DEFAULT_PARENS = List.of(paren("(", ")"));
public static final Mode MINI_MODE = Mode.SIMPLE_MINI; // Replace by TRUE_MINI for some challenge;
public static final Settings FULL = Mode.FULL.settings(0);
public static final Settings FULL_EXTRA = Mode.FULL.settings(Integer.MAX_VALUE / 4);
public static final Settings SAME = Mode.SAME.settings(0);
public static final Settings MINI = MINI_MODE.settings(0);
public static final Settings TRUE_MINI = Mode.TRUE_MINI.settings(0);
private final Renderer<C, Settings, Node<C>> renderer;
private final Map<String, String> brackets;
private final ExtendedRandom random;
public NodeRenderer(
final Renderer<C, Settings, Node<C>> renderer,
final Map<String, String> brackets,
final ExtendedRandom random
) {
this.renderer = renderer;
this.brackets = Map.copyOf(brackets);
this.random = random;
}
public static <C> Node<C> paren(final boolean condition, final Node<C> node) {
return condition ? Node.op(PAREN, 1, node) : node;
}
public static Paren paren(final String open, final String close) {
return new Paren(open, close);
}
public Node<C> renderToNode(final Settings settings, final Expr<C, ?> expr) {
final Expr<C, Node<C>> convert = expr.convert((name, variable) -> Node.op(name));
return renderer.render(convert, settings);
}
public String render(final Node<C> node, final List<Paren> parens) {
return node.cata(
String::valueOf,
name -> name,
(name, priority, arg) ->
name == PAREN ? random.randomItem(parens).apply(arg) :
priority == Integer.MAX_VALUE ? name + arg + brackets.get(name) :
(priority & 1) == 1 ? name + arg :
arg + name,
(name, a, b) -> a + " " + name + " " + b
);
}
public String render(final Expr<C, ?> expr, final Settings settings) {
return render(renderToNode(settings, expr), settings.parens());
}
public enum Mode {
FULL, SAME, TRUE_MINI, SIMPLE_MINI;
public Settings settings(final int limit) {
return new Settings(this, limit);
}
}
public record Paren(String open, String close) {
String apply(final String expression) {
return open() + expression + close();
}
}
public record Settings(Mode mode, int limit, List<Paren> parens) {
public Settings(final Mode mode, final int limit) {
this(mode, limit, DEFAULT_PARENS);
}
public <C> Node<C> extra(Node<C> node, final ExtendedRandom random) {
while (random.nextInt(Integer.MAX_VALUE) < limit) {
node = paren(true, node);
}
return node;
}
public Settings withParens(final List<Paren> parens) {
return this.parens.equals(parens) ? this : new Settings(mode, limit, List.copyOf(parens));
}
}
}