简体   繁体   中英

Convert string of boolean expression to tree structure in C#

I'm trying to convert string of logical expressions like "a && b || c && d" or "(a && b) || (c && d)" into binary-tree structures:

      ||
    /    \
  &&      && 
 / \     /  \
a   b   c    d

Then apply a depth-first search to traverse them.

Is there any appropriate library to do this? I was thinking about Irony or Roslyn, but I was not sure.

I don't know about a library, but it can be implemented like this.

What you want is basically an expression tree from given expression (its in-order traversal)

To construct a tree use below steps: Loop through the expression

  1. If the character is not an operator push it into the stack.

  2. If the character is an operator pop two operands and make them its child and push the current node into stack.

  3. In the end only element in stack will be your tree.

Please refer this link for an implementation of the algorithm.

You can actually use a parser-generator library like ANTLR to achieve your result, but it would be overkill for a simple task.

You can instead define your own small grammar as follows (I have used '+' instead of '||' and '.' in place of '&&'. Replace those with your symbols while also making appropriate code changes to the recursive-descent parser code):

S → T '+' S | T
T → F '.' T | F
F → A | '('S')'
A → 'a' | 'b' | 'c' | ... | ɛ

Based on the above grammar, now you can easily write a recursive-descent parser as follows (following code may not be syntactically correct, just use it as a pseudocode):

public Node S(){
        Node  T = T();

        if(inputHasMoreUnseenCharacters() && peekNextCharacterInString().equals("+")){
            eatNextCharacterInString();//eats '+'
            Node S = S();
            return new NodeOR(T, S);
        }

        return T;
    }

public Node T(){
    Node F= F();

    if(inputHasMoreUnseenCharacters() && peekNextCharacterInString().equals(".")){
        eatNextCharacterInString();//eats '.'
        Node T = T();
        return new NodeAND(F, T);
    }

    return F;
}

public Node F(){
    String nextCharacterInput = eatNextCharacterInString();
    Node node = null;
    if(nextCharacterInput.equals("(")){
        //eatNextCharacterInString(); //eats '('
        node = S();
        eatNextCharacterInString(); //eats ')'
    }else{
        node = A(nextCharacterInput);
    }
    return node;
}

public Node A(String nextCharacterInput){
    Node node = null;
    return new NodeSingleValue(nextCharacterInput);
}

Classes NodeOR, NodeAND and NodeSingleValue all are child classes of class Node. Once you call the method S(), you get the root of your tree as an object of type Node.

For an intro to recursive-descent parsing, this link might be useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM