switch (next()) { case '-': expr = new Expr(ALIPHATIC_ORDER, 1); break; case '=': expr = new Expr(ALIPHATIC_ORDER, 2); break; case '#': expr = new Expr(ALIPHATIC_ORDER, 3); break; case '$': expr = new Expr(ALIPHATIC_ORDER, 4); break; case ':': expr = new Expr(Expr.Type.IS_AROMATIC); break; case '~': expr = new Expr(Expr.Type.TRUE); break; case '@': expr = new Expr(Expr.Type.IS_IN_RING); break; case '&': if (dest.type() == Expr.Type.NONE) return false; expr = new Expr(Expr.Type.NONE); if (!parseBondExpr(expr, bond, '&')) return false; break;
/** * Traverse an expression tree and flip all the stereo expressions. */ void flip(Expr expr) { for (; ; ) { switch (expr.type()) { case STEREOCHEMISTRY: if (expr.value() != 0) expr.setPrimitive(expr.type(), expr.value() ^ 0x3); return; case AND: case OR: flip(expr.left()); expr = expr.right(); break; case NOT: expr = expr.left(); break; } } }
private static boolean hasOr(Expr expr) { for (; ; ) { switch (expr.type()) { case AND: if (hasOr(expr.left())) return true; expr = expr.right(); break; case OR: return expr.left().type() != STEREOCHEMISTRY || expr.right().type() != STEREOCHEMISTRY || expr.right().value() != 0; case SINGLE_OR_AROMATIC: case SINGLE_OR_DOUBLE: case DOUBLE_OR_AROMATIC: return true; default: return false; } } }
/** * Utility, combine this expression with another, using conjunction. * The expression will only match if both conditions are met. * * @param expr the other expression * @return self for chaining */ public Expr and(Expr expr) { if (type == Type.TRUE) { set(expr); } else if (expr.type != Type.TRUE) { if (type.isLogical() && !expr.type.isLogical()) { if (type == AND) right.and(expr); else setLogical(Type.AND, expr, new Expr(this)); } else { setLogical(Type.AND, new Expr(this), expr); } } return this; }
/** * Utility, combine this expression with another, using disjunction. * The expression will match if either conditions is met. * @param expr the other expression * @return self for chaining */ public Expr or(Expr expr) { if (type == Type.TRUE || type == Type.FALSE || type == NONE) { set(expr); } else if (expr.type != Type.TRUE && expr.type != Type.FALSE && expr.type != Type.NONE) { if (type.isLogical() && !expr.type.isLogical()) { if (type == OR) right.or(expr); else setLogical(Type.OR, expr, new Expr(this)); } else setLogical(Type.OR, new Expr(this), expr); } return this; }
QueryBond qbond = ((QueryBond)bond); Expr e = qbond.getExpression(); switch (e.type()) { case ALIPHATIC_ORDER: case ORDER: bondType = e.value(); break; case IS_AROMATIC: case OR: if (e.equals(new Expr(Expr.Type.ALIPHATIC_ORDER, 1).or(new Expr(Expr.Type.ALIPHATIC_ORDER, 2))) || e.equals(new Expr(Expr.Type.ALIPHATIC_ORDER, 2).or(new Expr(Expr.Type.ALIPHATIC_ORDER, 1)))) bondType = 5; else if (e.equals(new Expr(Expr.Type.ALIPHATIC_ORDER, 1).or(new Expr(Expr.Type.IS_AROMATIC))) || e.equals(new Expr(Expr.Type.IS_AROMATIC).or(new Expr(Expr.Type.ALIPHATIC_ORDER, 1)))) bondType = 6; else if (e.equals(new Expr(Expr.Type.ALIPHATIC_ORDER, 2).or(new Expr(Expr.Type.IS_AROMATIC))) || e.equals(new Expr(Expr.Type.IS_AROMATIC).or(new Expr(Expr.Type.ALIPHATIC_ORDER, 2)))) bondType = 6; break;
switch (left.type()) { case AND: case OR: Expr sub1 = determineBondStereo(left.left(), right); Expr sub2 = determineBondStereo(left.right(), right); if (sub1 != null && sub2 != null) return new Expr(left.type(), sub1, sub2); else if (sub1 != null) return sub1; return null; case NOT: sub1 = determineBondStereo(left.left(), right); if (sub1 != null) return sub1.negate(); break; case STEREOCHEMISTRY: switch (right.type()) { case AND: case OR: sub1 = determineBondStereo(left, right.left()); sub2 = determineBondStereo(left, right.right()); if (sub1 != null && sub2 != null) return new Expr(right.type(), sub1, sub2); else if (sub1 != null) return sub1; return null; case NOT:
private boolean parseRange(Expr expr) { if (next() != '{') return false; int lo = nextUnsignedInt(); if (next() != '-') return false; int hi = nextUnsignedInt(); Expr.Type type = expr.type(); // adjusted types switch (type) { case HAS_IMPLICIT_HYDROGEN: type = IMPL_H_COUNT; break; } expr.setPrimitive(type, lo); for (int i = lo + 1; i <= hi; i++) expr.or(new Expr(type, i)); return next() == '}'; }
@Test public void testToString() { assertThat(new Expr(TRUE).toString(), is("TRUE")); assertThat(new Expr(ELEMENT, 8).toString(), is("ELEMENT=8")); assertThat(new Expr(ELEMENT, 8).or(new Expr(DEGREE, 3)).toString(), is("OR(ELEMENT=8,DEGREE=3)")); assertThat(new Expr(ELEMENT, 8).and(new Expr(DEGREE, 3)).toString(), is("AND(ELEMENT=8,DEGREE=3)")); assertThat(new Expr(ELEMENT, 8).negate().toString(), is("NOT(ELEMENT=8)")); assertThat(new Expr(RECURSIVE, null).toString(), is("RECURSIVE(...)")); }
@Test public void removeFalseOr() { assertThat(new Expr(DEGREE, 2).or(new Expr(FALSE)), is(new Expr(DEGREE, 2))); assertThat(new Expr(DEGREE, 2).or(new Expr(TRUE)), is(new Expr(DEGREE, 2))); assertThat(new Expr(FALSE).or(new Expr(DEGREE, 2)), is(new Expr(DEGREE, 2))); assertThat(new Expr(TRUE).or(new Expr(DEGREE, 2)), is(new Expr(DEGREE, 2))); }
new Expr(Expr.Type.ELEMENT, 1) : new Expr(Expr.Type.AND, new Expr(Expr.Type.ISOTOPE, isotope), new Expr(Expr.Type.ELEMENT, 1)); if (peek() == '+') { pos++; hExpr.and(new Expr(Expr.Type.FORMAL_CHARGE, +num)); } else if (peek() == '-') { pos++; hExpr.and(new Expr(FORMAL_CHARGE, -num)); dest.set(hExpr); return true; } else {
switch (expr.type()) { case AND: case OR: Expr left = strip(expr.left(), type); Expr right = strip(expr.right(), type); if (left != null && right != null) expr.setLogical(expr.type(), left, right); else if (left != null) return left; return null; case NOT: Expr sub = strip(expr.left(), type); if (sub != null) { expr.setLogical(expr.type(), sub, null); return expr; } else { return expr.type() == type ? null : expr;
/** * Utility to generate a bond expression. * <pre>{@code * Expr expr = new Expr(Expr.Type.TRUE); * String bExpr = Smarts.generateBond(expr); * // bExpr='~' * }</pre> * @see Expr * @param expr the expression * @return the SMARTS atom expression */ public static String generateBond(Expr expr) { // default bond type if (expr.type() == SINGLE_OR_AROMATIC) return ""; StringBuilder sb = new StringBuilder(); generateBond(sb, expr); return sb.toString(); }