code: private Expression parseSemVerExpression() {
      Expression expr;
      if (tokens.positiveLookahead(NOT)) {
        tokens.consume();
        consumeNextToken(LEFT_PAREN);
        expr = new Not(parseSemVerExpression());
        consumeNextToken(RIGHT_PAREN);
      } else if (tokens.positiveLookahead(LEFT_PAREN)) {
        consumeNextToken(LEFT_PAREN);
        expr = parseSemVerExpression();
        consumeNextToken(RIGHT_PAREN);
      } else {
        expr = parseExpression();
      }
      return parseBooleanExpression(expr);
    }
docs: Parses the {@literal <semver-expr>} non-terminal.
  
  <pre>
  {@literal
  <semver-expr> ::= "(" <semver-expr> ")"
  | "!" "(" <semver-expr> ")"
  | <semver-expr> <boolean-expr>
  | <expr>
  }
  </pre>
  
  @return the expression AST