All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.applic.expressions.Expressions Maven / Gradle / Ivy

The newest version!
package cdc.applic.expressions;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import cdc.applic.expressions.ast.AndNode;
import cdc.applic.expressions.ast.EqualNode;
import cdc.applic.expressions.ast.EquivalenceNode;
import cdc.applic.expressions.ast.GreaterNode;
import cdc.applic.expressions.ast.GreaterOrEqualNode;
import cdc.applic.expressions.ast.ImplicationNode;
import cdc.applic.expressions.ast.InNode;
import cdc.applic.expressions.ast.InformalNode;
import cdc.applic.expressions.ast.LessNode;
import cdc.applic.expressions.ast.LessOrEqualNode;
import cdc.applic.expressions.ast.NaryAndNode;
import cdc.applic.expressions.ast.NaryOrNode;
import cdc.applic.expressions.ast.NeitherGreaterNorEqualNode;
import cdc.applic.expressions.ast.NeitherLessNorEqualNode;
import cdc.applic.expressions.ast.Node;
import cdc.applic.expressions.ast.NotEqualNode;
import cdc.applic.expressions.ast.NotGreaterNode;
import cdc.applic.expressions.ast.NotInNode;
import cdc.applic.expressions.ast.NotLessNode;
import cdc.applic.expressions.ast.NotNode;
import cdc.applic.expressions.ast.OrNode;
import cdc.applic.expressions.ast.ParsingNode;
import cdc.applic.expressions.ast.RefNode;
import cdc.applic.expressions.ast.XorNode;
import cdc.applic.expressions.content.IntegerRange;
import cdc.applic.expressions.content.IntegerValue;
import cdc.applic.expressions.content.RealRange;
import cdc.applic.expressions.content.RealValue;
import cdc.applic.expressions.content.SItem;
import cdc.applic.expressions.content.SItemSet;
import cdc.applic.expressions.content.SItemSetUtils;
import cdc.applic.expressions.content.Value;
import cdc.applic.expressions.content.ValueUtils;
import cdc.applic.expressions.literals.InformalText;
import cdc.applic.expressions.literals.Name;

public class Expressions {
    private final ExpressionsFeatures features;
    private final ExpressionPool pool;

    public static final Expressions NO_FORMATTING_NO_SIMPLIFY =
            new Expressions(ExpressionsFeatures.builder()
                                               .formatting(null)
                                               .simplify(false)
                                               .build());

    public static final Expressions SHORT_NARROW_NO_SIMPLIFY =
            new Expressions(ExpressionsFeatures.builder()
                                               .formatting(Formatting.SHORT_NARROW)
                                               .simplify(false)
                                               .build());

    public static final Expressions SHORT_NARROW_SIMPLIFY =
            new Expressions(ExpressionsFeatures.builder()
                                               .formatting(Formatting.SHORT_NARROW)
                                               .simplify(true)
                                               .build());

    public Expressions(ExpressionsFeatures features,
                       ExpressionPool pool) {
        this.features = features;
        this.pool = pool;
    }

    public Expressions(ExpressionsFeatures features) {
        this(features, null);
    }

    private Expression create(ParsingNode node) {
        final Expression expression = new Expression(node, features.getFormatting());
        return pool == null
                ? expression
                : pool.get(expression);
    }

    /**
     * Remove duplicates.
     *
     * @param alphas The expressions
     * @return The same expression without duplicates.
     */
    private static Node[] filter(Expression... alphas) {
        if (alphas.length == 1) {
            final Node[] result = new ParsingNode[1];
            result[0] = alphas[0].getRootNode();
            return result;
        } else {
            final Set set = new LinkedHashSet<>();
            Collections.addAll(set, alphas);
            final Node[] result = new Node[set.size()];
            int index = 0;
            for (final Expression x : set) {
                result[index] = x.getRootNode();
                index++;
            }
            return result;
        }
    }

    private Expression naryAnd(Expression... alphas) {
        return create((ParsingNode) NaryAndNode.createSimplestAnd(filter(alphas)));
    }

    private Expression naryOr(Expression... alphas) {
        return create((ParsingNode) NaryOrNode.createSimplestOr(filter(alphas)));
    }

    public Expression and(Expression alpha,
                          Expression beta) {
        if (features.simplify()) {
            if (alpha.isFalse() || beta.isFalse()) {
                return Expression.FALSE;
            } else if (alpha.isTrue()) {
                return beta;
            } else if (beta.isTrue()) {
                return alpha;
            }
        }
        return create(new AndNode(alpha.getRootNode(), beta.getRootNode()));
    }

    public Expression and(Collection alphas) {
        return and(alphas.toArray(new Expression[alphas.size()]));
    }

    public ExpressionPool getPool() {
        return pool;
    }

    public Expression and(Expression... alphas) {
        if (features.simplify()) {
            if (alphas.length == 1) {
                return alphas[0];
            } else {
                int trueCount = 0;
                for (final Expression alpha : alphas) {
                    if (alpha.isFalse()) {
                        return Expression.FALSE;
                    } else if (alpha.isTrue()) {
                        trueCount++;
                    }
                }
                if (trueCount == 0) {
                    // No true, so we can not do much
                    return naryAnd(alphas);
                } else if (trueCount == alphas.length) {
                    // All true, so result is true
                    return Expression.TRUE;
                } else {
                    // Extract non true operands
                    final Expression[] nonTrue = new Expression[alphas.length - trueCount];
                    int index = 0;
                    for (final Expression alpha : alphas) {
                        if (!alpha.isTrue()) {
                            nonTrue[index] = alpha;
                            index++;
                        }
                    }
                    return naryAnd(nonTrue);
                }
            }
        } else {
            return naryAnd(alphas);
        }
    }

    public Expression or(Expression alpha,
                         Expression beta) {
        if (features.simplify()) {
            if (alpha.isTrue() || beta.isTrue()) {
                return Expression.TRUE;
            } else if (alpha.isFalse()) {
                return beta;
            } else if (beta.isFalse()) {
                return alpha;
            }
        }
        return create(new OrNode(alpha.getRootNode(), beta.getRootNode()));
    }

    public Expression or(Collection alphas) {
        return or(alphas.toArray(new Expression[alphas.size()]));
    }

    public Expression or(Expression... alphas) {
        if (features.simplify()) {
            if (alphas.length == 1) {
                return alphas[0];
            } else {
                int falseCount = 0;
                for (final Expression alpha : alphas) {
                    if (alpha.isTrue()) {
                        return Expression.TRUE;
                    } else if (alpha.isFalse()) {
                        falseCount++;
                    }
                }
                if (falseCount == 0) {
                    // No false, so we can not do much
                    return naryOr(alphas);
                } else if (falseCount == alphas.length) {
                    // All false, so result is false
                    return Expression.FALSE;
                } else {
                    // Extract non false operands
                    final Expression[] nonFalse = new Expression[alphas.length - falseCount];
                    int index = 0;
                    for (final Expression alpha : alphas) {
                        if (!alpha.isFalse()) {
                            nonFalse[index] = alpha;
                            index++;
                        }
                    }
                    return naryOr(nonFalse);
                }
            }
        } else {
            return naryOr(alphas);
        }
    }

    public Expression xor(Expression alpha,
                          Expression beta) {
        return create(new XorNode(alpha.getRootNode(), beta.getRootNode()));
    }

    public Expression imp(Expression alpha,
                          Expression beta) {
        return create(new ImplicationNode(alpha.getRootNode(), beta.getRootNode()));
    }

    public Expression iff(Expression alpha,
                          Expression beta) {
        return create(new EquivalenceNode(alpha.getRootNode(), beta.getRootNode()));
    }

    public Expression not(Expression alpha) {
        if (features.simplify()) {
            if (alpha.isTrue()) {
                return Expression.FALSE;
            } else if (alpha.isFalse()) {
                return Expression.TRUE;
            } else {
                final Node node = alpha.getRootNode();
                if (node instanceof final NotNode x && x.getAlpha() instanceof final ParsingNode y) {
                    return create(y);
                }
            }
        }
        return create(new NotNode(alpha.getRootNode()));
    }

    public Expression ref(Name name) {
        return create(new RefNode(name));
    }

    public Expression ref(String name) {
        return ref(name(name));
    }

    public Expression equal(Name name,
                            Value value) {
        return create(new EqualNode(name, value));
    }

    public Expression equal(Name name,
                            String literal) {
        return equal(name, value(literal));
    }

    public Expression equal(String name,
                            Value value) {
        return equal(name(name), value);
    }

    public Expression equal(String name,
                            String literal) {
        return equal(name(name), value(literal));
    }

    public Expression notEqual(Name name,
                               Value value) {
        return create(new NotEqualNode(name, value));
    }

    public Expression notEqual(Name name,
                               String literal) {
        return notEqual(name, value(literal));
    }

    public Expression notEqual(String name,
                               Value value) {
        return notEqual(name(name), value);
    }

    public Expression notEqual(String name,
                               String literal) {
        return notEqual(name(name), value(literal));
    }

    public Expression in(Name name,
                         SItemSet set) {
        return create(new InNode(name, set));
    }

    public Expression in(Name name,
                         String content) {
        return in(name, set(content));
    }

    public Expression in(String name,
                         SItemSet set) {
        return in(name(name), set);
    }

    public Expression in(String name,
                         String content) {
        return in(name(name), set(content));
    }

    public Expression inOrEqual(Name name,
                                SItemSet set) {
        if (set.isSingleton()) {
            return equal(name, set.getSingletonValue());
        } else {
            return in(name, set);
        }
    }

    public Expression inOrEqual(Name name,
                                String content) {
        return inOrEqual(name, set(content));
    }

    public Expression inOrEqual(String name,
                                SItemSet set) {
        return inOrEqual(name(name), set);
    }

    public Expression inOrEqual(String name,
                                String content) {
        return inOrEqual(name(name), set(content));
    }

    public Expression notIn(Name name,
                            SItemSet set) {
        return create(new NotInNode(name, set));
    }

    public Expression notIn(Name name,
                            String content) {
        return notIn(name, set(content));
    }

    public Expression notIn(String name,
                            SItemSet set) {
        return notIn(name(name), set);
    }

    public Expression notIn(String name,
                            String content) {
        return notIn(name(name), set(content));
    }

    public Expression notInOrNotEqual(Name name,
                                      SItemSet set) {
        if (set.isSingleton()) {
            return notEqual(name, set.getSingletonValue());
        } else {
            return notIn(name, set);
        }
    }

    public Expression notInOrNotEqual(Name name,
                                      String content) {
        return notInOrNotEqual(name, set(content));
    }

    public Expression notInOrNotEqual(String name,
                                      SItemSet set) {
        return notInOrNotEqual(name(name), set);
    }

    public Expression notInOrNotEqual(String name,
                                      String content) {
        return notInOrNotEqual(name(name), set(content));
    }

    public Expression less(Name name,
                           Value value) {
        return create(new LessNode(name, value));
    }

    public Expression less(Name name,
                           String literal) {
        return less(name, value(literal));
    }

    public Expression less(String name,
                           Value value) {
        return less(name(name), value);
    }

    public Expression less(String name,
                           String literal) {
        return less(name(name), value(literal));
    }

    public Expression greater(Name name,
                              Value value) {
        return create(new GreaterNode(name, value));
    }

    public Expression greater(Name name,
                              String literal) {
        return greater(name, value(literal));
    }

    public Expression greater(String name,
                              Value value) {
        return greater(name(name), value);
    }

    public Expression greater(String name,
                              String literal) {
        return greater(name(name), value(literal));
    }

    public Expression lessOrEqual(Name name,
                                  Value value) {
        return create(new LessOrEqualNode(name, value));
    }

    public Expression lessOrEqual(Name name,
                                  String literal) {
        return lessOrEqual(name, value(literal));
    }

    public Expression lessOrEqual(String name,
                                  Value value) {
        return lessOrEqual(name(name), value);
    }

    public Expression lessOrEqual(String name,
                                  String literal) {
        return lessOrEqual(name(name), value(literal));
    }

    public Expression greaterOrEqual(Name name,
                                     Value value) {
        return create(new GreaterOrEqualNode(name, value));
    }

    public Expression greaterOrEqual(Name name,
                                     String literal) {
        return greaterOrEqual(name, value(literal));
    }

    public Expression greaterOrEqual(String name,
                                     Value value) {
        return greaterOrEqual(name(name), value);
    }

    public Expression greaterOrEqual(String name,
                                     String literal) {
        return greaterOrEqual(name(name), value(literal));
    }

    public Expression notLess(Name name,
                              Value value) {
        return create(new NotLessNode(name, value));
    }

    public Expression notLess(Name name,
                              String literal) {
        return notLess(name, value(literal));
    }

    public Expression notLess(String name,
                              Value value) {
        return notLess(name(name), value);
    }

    public Expression notLess(String name,
                              String literal) {
        return notLess(name(name), value(literal));
    }

    public Expression notGreater(Name name,
                                 Value value) {
        return create(new NotGreaterNode(name, value));
    }

    public Expression notGreater(Name name,
                                 String literal) {
        return notGreater(name, value(literal));
    }

    public Expression notGreater(String name,
                                 Value value) {
        return notGreater(name(name), value);
    }

    public Expression notGreater(String name,
                                 String literal) {
        return notGreater(name(name), value(literal));
    }

    public Expression neitherLessNorEqual(Name name,
                                          Value value) {
        return create(new NeitherLessNorEqualNode(name, value));
    }

    public Expression neitherLessNorEqual(Name name,
                                          String literal) {
        return neitherLessNorEqual(name, value(literal));
    }

    public Expression neitherLessNorEqual(String name,
                                          Value value) {
        return neitherLessNorEqual(name(name), value);
    }

    public Expression neitherLessNorEqual(String name,
                                          String literal) {
        return neitherLessNorEqual(name(name), value(literal));
    }

    public Expression neitherGreaterNorEqual(Name name,
                                             Value value) {
        return create(new NeitherGreaterNorEqualNode(name, value));
    }

    public Expression neitherGreaterNorEqual(Name name,
                                             String literal) {
        return neitherGreaterNorEqual(name, value(literal));
    }

    public Expression neitherGreaterNorEqual(String name,
                                             Value value) {
        return neitherGreaterNorEqual(name(name), value);
    }

    public Expression neitherGreaterNorEqual(String name,
                                             String literal) {
        return neitherGreaterNorEqual(name(name), value(literal));
    }

    public Expression informal(String text) {
        return create(new InformalNode(InformalText.of(text)));
    }

    public Name name(String literal) {
        return Name.of(literal);
    }

    public Name name(String literal,
                     boolean escaped) {
        return Name.of(literal, escaped);
    }

    public Value value(String literal) {
        return ValueUtils.create(literal);
    }

    public IntegerValue value(int number) {
        return IntegerValue.of(number);
    }

    public IntegerRange range(int number) {
        return IntegerRange.of(number);
    }

    public IntegerRange range(int min,
                              int max) {
        return IntegerRange.of(min, max);
    }

    public RealValue value(double number) {
        return RealValue.of(number);
    }

    public RealRange range(double number) {
        return RealRange.of(number);
    }

    public RealRange range(double min,
                           double max) {
        return RealRange.of(min, max);
    }

    public SItemSet set(String content) {
        return SItemSetUtils.createBest(content);
    }

    public SItemSet set(SItem... items) {
        return SItemSetUtils.createBest(items);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy