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

io.fixprotocol.md.event.DocumentParser Maven / Gradle / Ivy

There is a newer version: 1.2.1
Show newest version
/*
 * Copyright 2020 FIX Protocol Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 *
 */
package io.fixprotocol.md.event;

import java.io.IOException;
import java.io.InputStream;
import java.util.function.Consumer;
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import io.fixprotocol.md.antlr.MarkdownBaseListener;
import io.fixprotocol.md.antlr.MarkdownEventSource;
import io.fixprotocol.md.antlr.MarkdownLexer;
import io.fixprotocol.md.antlr.MarkdownParser;
import io.fixprotocol.md.antlr.MarkdownParser.DocumentContext;

public final class DocumentParser {
  
  /**
   * Listens for parser errors
   */
  public interface ParserErrorListener {
    void parseError(int line, int charPositionInLine, String msg);
  }

  private static class SyntaxErrorListener extends BaseErrorListener {
    private final Logger logger = LogManager.getLogger(getClass());
    private int errors = 0;
    private final ParserErrorListener errorListener;

    public SyntaxErrorListener(ParserErrorListener errorListener) {
      this.errorListener = errorListener;
    }

    public int getErrors() {
      return errors;
    }

    @Override
    public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line,
        int charPositionInLine, String msg, RecognitionException e) {
      errors++;
      logError(line, charPositionInLine, msg);
      if (errorListener != null) {
        errorListener.parseError(line, charPositionInLine, msg);
      }
    }

    void logError(int line, int charPositionInLine, String msg) {
      logger.error("Markdown parser failed at line {} position {} due to {}", line,
          charPositionInLine, msg);
    }
  }
  
  /**
   * Parse a markdown document
   *
   * @param inputStream input as markdown
   * @param contextConsumer consumer of document events
   * @return {@code true} if the document is fully parsed without errors
   * @throws IOException if the document cannot be read
   */
  public boolean parse(InputStream inputStream, Consumer contextConsumer)
      throws IOException {
    return parse(inputStream, contextConsumer, null);
  }

  /**
   * Parse a markdown document
   *
   * @param inputStream input as markdown
   * @param contextConsumer consumer of document events
   * @param parserListener listens for parser errors. May be {@code null}.
   * @return {@code true} if the document is fully parsed without errors
   * @throws IOException if the document cannot be read
   */
  public boolean parse(InputStream inputStream, Consumer contextConsumer, ParserErrorListener parserListener)
      throws IOException {
    final MarkdownLexer lexer = new MarkdownLexer(CharStreams.fromStream(inputStream));
    final MarkdownParser parser = new MarkdownParser(new CommonTokenStream(lexer));
    final SyntaxErrorListener errorListener = new SyntaxErrorListener(parserListener);
    parser.addErrorListener(errorListener);
    final ParseTreeListener listener = new MarkdownEventSource(contextConsumer);
    final ParseTreeWalker walker = new ParseTreeWalker();
    final DocumentContext documentContext = parser.document();
    walker.walk(listener, documentContext);

    final int errors = errorListener.getErrors();
    return (errors == 0);
  }

  /**
   * Validate a markdown document
   *
   * @param inputStream input as markdown
   * @param parserListener listens for parser errors.
   * @return {@code true} if the document is fully parsed without errors
   * @throws IOException if the document cannot be read
   */
  public boolean validate(InputStream inputStream, ParserErrorListener parserListener)
      throws IOException {
    final MarkdownLexer lexer = new MarkdownLexer(CharStreams.fromStream(inputStream));
    final MarkdownParser parser = new MarkdownParser(new CommonTokenStream(lexer));
    final SyntaxErrorListener errorListener = new SyntaxErrorListener(parserListener);
    parser.addErrorListener(errorListener);
    final ParseTreeWalker walker = new ParseTreeWalker();
    final DocumentContext documentContext = parser.document();
    walker.walk(new MarkdownBaseListener(), documentContext);

    final int errors = errorListener.getErrors();
    return (errors == 0);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy