private ExpressionNode parseTerm() throws ParseExpressionException {
    ExpressionNode rootNode = null;

    scanner.nextSymbol();
    while (scanner.isNot()) {

      ExpressionNode oldRoot = rootNode;
      rootNode = new ExpressionNotNode(oldRoot);
      scanner.nextSymbol();
    }

    if (scanner.isMiIdentifier()) {
      if (rootNode != null) {
        ExpressionNotNode tmpNode = (ExpressionNotNode) rootNode;
        while (tmpNode.getChild() != null) {
          tmpNode = (ExpressionNotNode) tmpNode.getChild();
        }
        tmpNode.setChild(new ExpressionMiNode(scanner.getCurrSymbol()));
      } else {
        rootNode = new ExpressionMiNode(scanner.getCurrSymbol());
      }
    } else if (scanner.isFreeText()) {
      if (rootNode != null) {
        ExpressionNotNode tmpNode = (ExpressionNotNode) rootNode;
        while (tmpNode.getChild() != null) {
          tmpNode = (ExpressionNotNode) tmpNode.getChild();
        }
        tmpNode.setChild(parseFreeText());

      } else {
        rootNode = parseFreeText();
      }
    } else if (scanner.isLeftPar()) {
      if (rootNode != null) {
        ExpressionNotNode tmpNode = (ExpressionNotNode) rootNode;
        while (tmpNode.getChild() != null) {
          tmpNode = (ExpressionNotNode) tmpNode.getChild();
        }
        tmpNode.setChild(parseExpression());
      } else {
        rootNode = parseExpression();
      }

      scanner.nextSymbol();
      if (!scanner.isRightPar()) {
        throw new ParseExpressionException();
      }
    } else {
      throw new ParseExpressionException();
    }

    return rootNode;
  }
  private ExpressionNode parseFreeText() throws ParseExpressionException {
    Set<String> ids = miOntologyTree.getIdByName(scanner.getCurrSymbol());

    ExpressionNode rootNode = null;

    if (ids.size() > 0) {
      Object[] idsArr = ids.toArray();
      String tmpExpression = (String) idsArr[0];

      for (int i = 1; i < idsArr.length; ++i) {
        tmpExpression = tmpExpression + " or " + (String) idsArr[i];
      }

      ExpressionTree tmpTree = new ExpressionTree(tmpExpression, miOntologyTree, false);

      rootNode = tmpTree.getRootNode();

    } else {
      // TODO FIXME if I give a tag that doesn't have an MI identifier, we return all services.
      // TODO collect these non matching terms and print a warning message on the resulting HTML
      // page.
      rootNode = new ExpressionTrueNode();
    }

    return rootNode;
  }
  private ExpressionNode parseExpression() throws ParseExpressionException {
    ExpressionNode rootNode = null;

    rootNode = parseTerm();
    scanner.nextSymbol();
    while (isLogicalOp()) {
      if (scanner.isAnd()) {
        ExpressionNode oldRootNode = rootNode;
        rootNode = new ExpressionAndNode(oldRootNode, parseTerm());
      } else if (scanner.isOr()) {
        ExpressionNode oldRootNode = rootNode;
        rootNode = new ExpressionOrNode(oldRootNode, parseTerm());
      } else {
        throw new ParseExpressionException();
      }
    }

    return rootNode;
  }
 private boolean isLogicalOp() {
   return (scanner.isAnd() || scanner.isOr());
 }