SyntaxChecker.java
package org.thewonderlemming.c4plantuml.syntaxchecker;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Optional;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeListener;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.thewonderlemming.c4plantuml.commons.Reporter;
import org.thewonderlemming.c4plantuml.grammars.C4BaseListener;
import org.thewonderlemming.c4plantuml.grammars.SourceType;
import org.thewonderlemming.c4plantuml.grammars.generated.C4L1Parser;
import org.thewonderlemming.c4plantuml.grammars.generated.C4L2Parser;
import org.thewonderlemming.c4plantuml.grammars.generated.C4L3Parser;
/**
* An ANTLR4 based tool to analyse C4 PlantUML source files syntax.
*
* @author thewonderlemming
*
*/
public class SyntaxChecker {
private static final Logger LOGGER = LoggerFactory.getLogger(SyntaxChecker.class);
private static final ParseTreeListener PARSE_TREE_LISTENER = new C4BaseListener();
private final Reporter reporter;
/**
* Default constructor.
*
* @param reporter the {@link Reporter} to report to.
*/
public SyntaxChecker(final Reporter reporter) {
this.reporter = reporter;
}
/**
* Parses a given file and checks its syntax for errors, using {@code UTF-8} encoding.
*
* @param c4SourceFile the given file to parse.
*/
public void check(final Path c4SourceFile) {
check(c4SourceFile, StandardCharsets.UTF_8);
}
/**
* Parses a given file and checks its syntax for errors.
*
* @param c4SourceFile the given file to parse.
* @param charset the {@link Charset} to use while parsing the file.
*/
public void check(final Path c4SourceFile, final Charset charset) {
SourceType
.getSourceTypeFromFilename(c4SourceFile)
.ifPresent(sourceType -> {
final SyntaxCheckerErrorListener errorListener = new SyntaxCheckerErrorListener(
this.reporter,
c4SourceFile);
sourceType
.createParser(c4SourceFile, charset, errorListener)
.ifPresent(parser -> getParseTree(parser)
.ifPresent(tree -> new ParseTreeWalker().walk(PARSE_TREE_LISTENER, tree)));
});
}
private Optional<ParseTree> getParseTree(final Parser parser) {
final ParseTree tree;
if (parser instanceof C4L1Parser) {
tree = ((C4L1Parser) parser).diagram();
} else if (parser instanceof C4L2Parser) {
tree = ((C4L2Parser) parser).diagram();
} else if (parser instanceof C4L3Parser) {
tree = ((C4L3Parser) parser).diagram();
} else {
LOGGER.error("Unsupported parser type {} was given", parser.getClass());
return Optional.empty();
}
return Optional.ofNullable(tree);
}
}