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

de.gwdg.metadataqa.marc.utils.parser.BooleanParser Maven / Gradle / Ivy

package de.gwdg.metadataqa.marc.utils.parser;

import java.util.Deque;
import java.util.LinkedList;

/**
 * A top level parser which parser string such as
 *    .... AND ... AND (... OR ...)
 * It takes care of operators and parenthesis, but does not parse the content of individual units.
 */
public class BooleanParser {

  String token = "";
  String last = "";
  int start = 0;
  boolean skippedOp = false;
  String input;
  Deque parens = new LinkedList<>();

  private BooleanParser(String input) {
    this.input = input;
  }

  public static BooleanContainer parse(String input) {
    BooleanParser parser = new BooleanParser(input);
    return parser.parse();
  }

  private BooleanContainer parse() {
    BooleanContainer root = new BooleanContainer<>();
    for (int i = 0; i < input.length(); i++) {
      String n = input.substring(i, i+1);
      if (n.equals("&") && last.equals("&")) {
        processOp(i, root, BooleanContainer.Op.AND);
      } else if (n.equals("|") && last.equals("|")) {
        processOp(i, root, BooleanContainer.Op.OR);
      } else if (n.equals("(")) {
        parens.add(i);
      } else if (n.equals(")")) {
        if (parens.isEmpty())
          throw new IllegalArgumentException("Error: closing parens without opening one: " + input);
        parens.pollLast();
      }
      last = n;
    }
    token = input.substring(start).trim();
    addChild(root, token);
    if (!parens.isEmpty())
      throw new IllegalArgumentException("Error: opening parens without closing one: " + input);
    return root;
  }

  private void processOp(int i, BooleanContainer root, BooleanContainer.Op and) {
    if (parens.isEmpty()) {
      if (root.getOp() == null)
        root.setOp(and);
      addChild(root, input.substring(start, i -1).trim());
      start = i +1;
      skippedOp = false;
    } else {
      skippedOp = true;
    }
  }

  private void addChild(BooleanContainer root, String token) {
    if (skippedOp && !(token.startsWith("(") && token.endsWith(")")))
      throw new IllegalArgumentException("internal operator with imperfect parenthes: " + input);

    BooleanContainer child = (token.startsWith("(") && token.endsWith(")"))
      ? parse(token.substring(1, token.length()-1))
      : new BooleanContainer<>(token);
    if (child.getValue() != null && child.getOp() == null && root.getOp() == null)
      root.setValue(child.getValue());
    else
      root.getChildren().add(child);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy