code: private Expression parseVersionExpression() {
      int major = intOf(consumeNextToken(NUMERIC).lexeme);
      consumeNextToken(DOT);
      if (tokens.positiveLookahead(STAR)) {
        tokens.consume();
        return new And(new GreaterOrEqual(versionOf(major, 0, 0)),
            new Less(versionOf(major + 1, 0, 0)));
      }
      int minor = intOf(consumeNextToken(NUMERIC).lexeme);
      consumeNextToken(DOT);
      consumeNextToken(STAR);
      return new And(new GreaterOrEqual(versionOf(major, minor, 0)),
          new Less(versionOf(major, minor + 1, 0)));
    }
docs: Parses the {@literal <version-expr>} non-terminal.
  
  <pre>
  {@literal
  <version-expr> ::= <major> "." "*"
  | <major> "." <minor> "." "*"
  }
  </pre>
  
  @return the expression AST