java复杂逻辑条件解析器

标签 java algorithm parsing logical-operators recursive-descent

我有一组传入记录,需要根据定义和存储的一组逻辑子句进行评估。一个示例逻辑子句如下:

Acct1 != 'Y' AND Acct2 > 1004 AND Acct3 >= 96 AND Acct4 < 1004 AND Acct5 = 99 AND ((Acct6 <= 9090 OR Acct7 IN (A1,A2,A6) AND Acct1 NOT IN (A3,A4)) AND Formatted LIKE 'LINUX' AND Acct9 NOT LIKE 'WINDOWS' AND (Acct10 = 'N' AND NOT Acct11 = 'N') AND EditableField BETWEEN (10 AND 20) )

我对子句的数据输入如下:

map.put(Acct1,"Y")
map.put(Acct2,1010)
map.put(Acct3,99)
map.put(Acct4,1015)
map.put(Acct5,99)
map.put(Acct6,9090)
map.put(Acct7,"A3")
map.put(Formatted,"LINUX_INST")
map.put(Updated,"LINUX_TMP")
map.put(Acct10,"Y")
map.put(Acct11,"N")
map.put(EditableFIeld,25)

我必须根据上面定义的子句评估填充到映射中的传入记录,并根据评估结果打印真或假。

子句条件和映射值也将被更改和执行。

我要评估以下条件子句:

!=
>
>=
<
=
<=
IN(
NOT IN(
LIKE(
NOT LIKE(
BETWEEN(
AND
OR
AND NOT
OR NOT

我尝试过使用语法生成器,但有人告诉我这不是我们应用程序的推荐解决方案,因此我正在寻找 Java 代码,并且我有这个详细的示例供引用 AND、OR、=。 resolving logical operations - AND, OR, looping conditions dynamically并在可能的情况下寻找在此基础上构建的片段。

最佳答案

如果您想避免解析器生成器,请考虑使用 StreamTokenizer 来实现递归下降解析器,每个语法规则都有一个方法。

对于你的语法的一个子集,这应该看起来大致像这样(并且应该很容易扩展到你的完整语法):

public class Parser {

  public static Node parse(String expr) {
    StreamTokenizer tokenizer = 
        new StreamTokenizer(new StringReader(expr));
    tokenizer.nextToken();
    Parser parser = new Parser(tokenizer);
    Node result = parser.parseExpression();
    if (tokenizer.ttype != StreamTokenizer.TT_EOF) {
      throw new RuntimeException("EOF expected, got " 
          + tokenizer.ttype + "/" + tokenizer.sval);
  }

  private StreamTokenizer tokenizer;

  private Parser(StreamTokenizer tokenizer) {
    this.tokenizer = tokenizer;
  } 

  private Node parseExpression() {
    Node left = parseAnd();
    if (tokenizer.ttype == StreamTokenizer.TT_WORD
        && tokenizer.sval.equals("OR")) {
      tokenizer.nextToken();
      return new OperationNode(OperationNode.Type.OR, 
          left, parseExpression());
    }
    return left;
  }

  private Node parseAnd() {
    Node left = parseRelational();
    if (tokenizer.ttype == StreamTokenizer.TT_WORD
        && tokenizer.sval.equals("AND")) {
      tokenizer.nextToken();
      return new OperationNode(OperationNode.Type.AND, 
          left, parseAnd());
    }
    return left;
  }

  private Node parseRelational() {
    Node left = parsePrimary();
    OperationNode.Type type;
    switch (tokenizer.ttype) {
      case '<': type = OperationNode.Type.LESS; break;
      case '=': type = OperationNode.Type.EQUAL; break;
      case '>': type = OperationNode.Type.GREATER; break;
      default:  
        return left;
    }
    tokenizer.nextToken();
    return new OperationNode(type, left, parseRelational());
  }

  private Node parsePrimary() {
    Node result;
    if (tokenizer.ttype == '(') {
      tokenizer.nextToken();
      result = parseExpression();
      if (tokenizer.ttype != ')') {
        throw new RuntimeException(") expected, got "
          + tokenizer.ttype + "/" + tokenizer.sval);
       }
    } else if (tokenizer.ttype == '"' || tokenizer.ttype == '\'') {
      result = new LiteralNode(tokenizer.sval);
    } else if (tokenizer.ttype == TT_NUMBER) {
      result = new LiteralNode(tokenizer.nval);
    } else if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
      result = new FieldNode(tokenizer.sval);
    } else {
      throw new RuntimeException("Unrecognized token: " 
          + tokenizer.ttype + "/" + tokenizer.sval);
    }
    tokenizer.nextToken();
    return result;
  }
}

这假定了一个像这样的 Node 对象层次结构:

interface Node {
   Object eval(Map<String,Object> data);
}

class FieldNode implements Node {
   private String name; 
   FieldNode(String name) {
     this.name = name;
   }
   public Object eval(Map<String,Object> data) {
     return data.get(name);
   }
}

class LiteralNode implements Node {
   private Object value; 
   FieldNode(Object value) {
     this.value = value;
   }
   public Object eval(Map<String,Object> data) {
     return value;
   }
}

class OperationNode implements Node {
  enum Type {
    AND, OR, LESS, GREATER, EQUALS
  }
  private Type type;
  private Node leftChild;
  private Node rightChild;

  OperationNode(Type type, Node leftChild, Node rightChild) {
    this.type = type;
    this.leftChild = leftChild;
    this.rightChild = rightChild;
  }

  public Object eval(Map<String,Object> data) {
    Object left = leftChild.eval(data);
    Object right = rightChild.eval(data);
    switch (type) {
      case AND: return ((Boolean) left) && ((Boolean) right);
      case OR: return ((Boolean) left) || ((Boolean) right);
      case LESS: return ((Comparable) left).compareTo(right) < 0;
      case EQUALS: return left.equals(right);
      case GREATE: return ((Comparable) left).compareTo(right) > 0;
      default:
        throw new RuntimeException("Invalid op: " + type);
    }
  }    

关于java复杂逻辑条件解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32726833/

相关文章:

java - 如何从 context.xml 资源获取 URL

javascript - 如何编写一个 for 循环,从中断处开始计算?

algorithm - 美国国旗排序优化

python - 仅一个循环的排序和非排序排列

javascript - PHP 解析 JavaScript

java - spring xml上下文实用程序:map key is ignored and bean id used instead

"Object"类的 java 泛型函数参数类型不匹配

java - 如何将接收到的数据转换为输入流和输出流

ios - 在开源解析服务器上实现云代码

java - 在 Java 中静态输入脚本语言