code: public static PathMatcher valueOf(Reader reader) throws IOException, ParseException {
          class DescriptiveErrorListener extends BaseErrorListener {
              public List<String> errors = new ArrayList<>();
  
              @Override
              public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol,
                                      int line, int charPositionInLine,
                                      String msg, org.antlr.v4.runtime.RecognitionException e) {
                  LOG.log(Level.INFO, "Parse error: {0}:{1} -> {2}", new Object[]{line, charPositionInLine, msg});
                  errors.add(String.format("%d:%d: %s", line, charPositionInLine, msg));
              }
          }
  
          final DescriptiveErrorListener error_listener = new DescriptiveErrorListener();
  
          final PathMatcherLexer lexer = new PathMatcherLexer(CharStreams.fromReader(reader));
          lexer.removeErrorListeners();
          lexer.addErrorListener(error_listener);
  
          final PathMatcherGrammar parser = new PathMatcherGrammar(new BufferedTokenStream(lexer));
          parser.removeErrorListeners();
          parser.addErrorListener(error_listener);
  
          final PathMatcherGrammar.ExprContext expr;
          try {
              expr = parser.expr();
          } catch (Exception ex) {
              LOG.log(Level.SEVERE, "parser yielded exceptional return", ex);
              if (!error_listener.errors.isEmpty())
                  throw new ParseException(error_listener.errors, ex);
              else
                  throw ex;
          }
  
          if (!error_listener.errors.isEmpty()) {
              if (expr.exception != null)
                  throw new ParseException(error_listener.errors, expr.exception);
              throw new ParseException(error_listener.errors);
          } else if (expr.exception != null) {
              throw new ParseException(expr.exception);
          }
          return expr.s;
      }
docs: Read path matcher from reader.
  
  @param reader A reader supplying the input of a path expression.
  @return A PathMatcher corresponding to the parsed input
  from the reader.
  @throws IOException on IO errors from the reader.
  @throws
  com.groupon.lex.metrics.PathMatcher.ParseException
  on invalid path expression.