diff --git a/README.md b/README.md
index 4247b15..627fa2a 100644
--- a/README.md
+++ b/README.md
@@ -3,9 +3,9 @@
# Antlr4Formatter
-Building
-====
-The project uses [maven wrapper](https://github.com/takari/maven-wrapper), so it's easy to build the project without worring about having the right Maven version installed locally.
+## Building
+
+The project uses [maven wrapper](https://github.com/takari/maven-wrapper), so it's easy to build the project without worrying about having the right Maven version installed locally.
To build `antlr4-formatter` and the standalone utility `antlr4-formatter-standalone` run:
@@ -13,19 +13,15 @@ To build `antlr4-formatter` and the standalone utility `antlr4-formatter-standal
./mvnw clean package
```
-Using the standalone formatter
-====
+## Using the standalone formatter
To format a grammar use the script `formatFile.sh` passing the grammar file as an argument to the script.
-Maven Coordinates
-====
+## Maven Coordinates
```
com.khubla.antlr4formatter
antlr4-formatter
1.1.0
jar
-```
-
-
+```
\ No newline at end of file
diff --git a/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4Formatter.java b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4Formatter.java
index feec3f6..4f79b0b 100644
--- a/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4Formatter.java
+++ b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4Formatter.java
@@ -17,7 +17,17 @@
*/
package com.khubla.antlr4formatter;
-import java.io.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@@ -39,104 +49,100 @@
* @author Tom Everett
*/
public class Antlr4Formatter {
-
- private Antlr4Formatter() {}
-
- private static final Logger LOG = LoggerFactory.getLogger(Antlr4Formatter.class);
-
- public static String format(String string) {
- try {
- if (null != string) {
- StringWriter writer = new StringWriter();
- CodePointCharStream input = CharStreams.fromString(string);
- formatGrammar(input, writer);
- return writer.toString();
- } else {
- return "";
- }
- } catch (final Exception e) {
- throw new RuntimeException("Exception reading and parsing file", e);
- }
- }
-
- private static void formatGrammar(CharStream input, Writer output) {
- final ANTLRv4Lexer lexer = new ANTLRv4Lexer(input);
- final CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
- final ANTLRv4Parser parser = new ANTLRv4Parser(commonTokenStream);
- final GrammarSpecContext grammarSpecContext = parser.grammarSpec();
- ParseTreeWalker.DEFAULT.walk(new Antlr4ParseTreeListenerImpl(output, commonTokenStream), grammarSpecContext);
- }
-
- public static void format(InputStream inputStream, OutputStream outputStream) {
-
- if (null == inputStream) {
- throw new IllegalArgumentException("Input stream must not be null!");
- }
- final Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
- try (OutputStreamWriter writer = new OutputStreamWriter(outputStream)) {
- formatGrammar(CharStreams.fromReader(reader), writer);
- } catch (IOException e) {
- LOG.error("Could not format file", e);
- }
- }
-
- public static void formatDirectory(String inputDirOption) throws Exception {
- List files = new ArrayList<>();
- files = listFilesFromDirectory(inputDirOption, files, ".g4");
- for (final String filename : files) {
- final File file = new File(filename);
- formatSingleFile(file, file);
- }
- }
-
- public static void formatSingleFile(File inputFile, File outputFile) throws Exception {
-
- if (inputFile.exists()) {
-
- final File tempFile = File.createTempFile(inputFile.getName(), ".g4");
-
- LOG.info("Formatting: {}", inputFile.getName());
-
- format(new FileInputStream(inputFile), new FileOutputStream(tempFile));
-
- Files.copy(tempFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
- Files.delete(tempFile.toPath());
- } else {
- throw new Exception("Unable to find: '" + inputFile + "'");
- }
- }
-
- public static void formatSingleFile(String inputFilename, String outputFilename) throws Exception {
- final File inputFile = new File(inputFilename);
- File outputFile;
-
- if (null == outputFilename) {
- outputFile = inputFile;
- } else {
- outputFile = new File(outputFilename);
- }
-
- formatSingleFile(inputFile, outputFile);
- }
-
- private static List listFilesFromDirectory(String dir, List files, String filter) {
- final File file = new File(dir);
- final String[] list = file.list();
- if (null != list) {
- for (String s : list) {
- final String fileName = dir + (dir.endsWith("/") ? "" : "/") + s;
- final File f2 = new File(fileName);
- if (!f2.isHidden()) {
- if (f2.isDirectory()) {
- listFilesFromDirectory(fileName + "/", files, filter);
- } else {
- if (fileName.endsWith(filter)) {
- files.add(fileName);
- }
- }
- }
- }
- }
- return files;
- }
+ private static final Logger LOG = LoggerFactory.getLogger(Antlr4Formatter.class);
+
+ public static void format(InputStream inputStream, OutputStream outputStream) {
+ if (null == inputStream) {
+ throw new IllegalArgumentException("Input stream must not be null!");
+ }
+ final Reader reader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
+ try (OutputStreamWriter writer = new OutputStreamWriter(outputStream)) {
+ formatGrammar(CharStreams.fromReader(reader), writer);
+ } catch (final IOException e) {
+ LOG.error("Could not format file", e);
+ }
+ }
+
+ public static String format(String string) throws Antlr4FormatterException {
+ try {
+ if (null != string) {
+ final StringWriter writer = new StringWriter();
+ final CodePointCharStream input = CharStreams.fromString(string);
+ formatGrammar(input, writer);
+ return writer.toString();
+ } else {
+ return "";
+ }
+ } catch (final Exception e) {
+ throw new Antlr4FormatterException("Exception reading and parsing file", e);
+ }
+ }
+
+ public static void formatDirectory(String inputDirOption) throws Antlr4FormatterException {
+ List files = new ArrayList<>();
+ files = listFilesFromDirectory(inputDirOption, files, ".g4");
+ for (final String filename : files) {
+ final File file = new File(filename);
+ formatSingleFile(file, file);
+ }
+ }
+
+ private static void formatGrammar(CharStream input, Writer output) {
+ final ANTLRv4Lexer lexer = new ANTLRv4Lexer(input);
+ final CommonTokenStream commonTokenStream = new CommonTokenStream(lexer);
+ final ANTLRv4Parser parser = new ANTLRv4Parser(commonTokenStream);
+ final GrammarSpecContext grammarSpecContext = parser.grammarSpec();
+ ParseTreeWalker.DEFAULT.walk(new Antlr4ParseTreeListenerImpl(output, commonTokenStream), grammarSpecContext);
+ }
+
+ public static void formatSingleFile(File inputFile, File outputFile) throws Antlr4FormatterException {
+ try {
+ if (inputFile.exists()) {
+ final File tempFile = File.createTempFile(inputFile.getName(), ".g4");
+ LOG.info("Formatting: {}", inputFile.getName());
+ format(new FileInputStream(inputFile), new FileOutputStream(tempFile));
+ Files.copy(tempFile.toPath(), outputFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ Files.delete(tempFile.toPath());
+ } else {
+ throw new Exception("Unable to find: '" + inputFile + "'");
+ }
+ } catch (final Exception e) {
+ throw new Antlr4FormatterException("Exception fromatting file", e);
+ }
+ }
+
+ public static void formatSingleFile(String inputFilename, String outputFilename) throws Antlr4FormatterException {
+ final File inputFile = new File(inputFilename);
+ File outputFile;
+ if (null == outputFilename) {
+ outputFile = inputFile;
+ } else {
+ outputFile = new File(outputFilename);
+ }
+ formatSingleFile(inputFile, outputFile);
+ }
+
+ private static List listFilesFromDirectory(String dir, List files, String filter) {
+ final File file = new File(dir);
+ final String[] list = file.list();
+ if (null != list) {
+ for (final String s : list) {
+ final String fileName = dir + (dir.endsWith("/") ? "" : "/") + s;
+ final File f2 = new File(fileName);
+ if (!f2.isHidden()) {
+ if (f2.isDirectory()) {
+ listFilesFromDirectory(fileName + "/", files, filter);
+ } else {
+ if (fileName.endsWith(filter)) {
+ files.add(fileName);
+ }
+ }
+ }
+ }
+ }
+ return files;
+ }
+
+ private Antlr4Formatter() {
+ }
}
diff --git a/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4FormatterException.java b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4FormatterException.java
new file mode 100644
index 0000000..85bbedf
--- /dev/null
+++ b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4FormatterException.java
@@ -0,0 +1,34 @@
+/*
+ * Antlr4Formatter Copyright 2018, khubla.com
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+package com.khubla.antlr4formatter;
+
+public class Antlr4FormatterException extends Exception {
+ private static final long serialVersionUID = 1L;
+
+ public Antlr4FormatterException(Exception e) {
+ super(e);
+ }
+
+ public Antlr4FormatterException(String message) {
+ super(message);
+ }
+
+ public Antlr4FormatterException(String message, Exception e) {
+ super(message, e);
+ }
+}
\ No newline at end of file
diff --git a/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4ParseTreeListenerImpl.java b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4ParseTreeListenerImpl.java
index cb529d0..17ecb30 100644
--- a/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4ParseTreeListenerImpl.java
+++ b/antlr4-formatter/src/main/java/com/khubla/antlr4formatter/Antlr4ParseTreeListenerImpl.java
@@ -37,295 +37,297 @@
import org.slf4j.LoggerFactory;
public class Antlr4ParseTreeListenerImpl implements ParseTreeListener {
+ /**
+ *
+ */
+ private static final Logger LOG = LoggerFactory.getLogger(Antlr4ParseTreeListenerImpl.class);
+ /**
+ * non space tokens
+ */
+ private static final Set noSpacingBeforeTokens = new HashSet<>(Arrays.asList(new String[] { "?", "*", ";", ")" }));
+ private static final Set noSpacingAfterTokens = new HashSet<>(Arrays.asList(new String[] { "(" }));
+ /**
+ * indent
+ */
+ private int indent = 0;
+ /**
+ * current context
+ */
+ private ParserRuleContext ctx;
+ /**
+ * newline
+ */
+ private boolean newline = true;
+ /**
+ * PrintStream
+ */
+ private final Writer writer;
+ /**
+ * token stream
+ */
+ private final CommonTokenStream commonTokenStream;
+ /**
+ * hidden token marker
+ */
+ private int hiddenTokenPos = -1;
+ /**
+ * parenth count
+ */
+ private int parenthcount = 0;
+ /**
+ * previous token
+ */
+ private String previousToken = "";
- /**
- *
- */
- private static final Logger LOG = LoggerFactory.getLogger(Antlr4ParseTreeListenerImpl.class);
- /**
- * non space tokens
- */
- private static final Set noSpacingBeforeTokens = new HashSet<>(Arrays.asList(new String[]{"?", "*", ";", ")"}));
- private static final Set noSpacingAfterTokens = new HashSet<>(Arrays.asList(new String[]{"("}));
- /**
- * indent
- */
- private int indent = 0;
- /**
- * current context
- */
- private ParserRuleContext ctx;
- /**
- * newline
- */
- boolean newline = true;
- /**
- * PrintStream
- */
- private final Writer writer;
- /**
- * token stream
- */
- private final CommonTokenStream commonTokenStream;
- /**
- * hidden token marker
- */
- private int hiddenTokenPos = -1;
- /**
- * parenth count
- */
- private int parenthcount = 0;
- /**
- * previous token
- */
- private String previousToken = "";
+ /**
+ * ctor
+ */
+ public Antlr4ParseTreeListenerImpl(Writer writer, CommonTokenStream commonTokenStream) {
+ this.writer = writer;
+ this.commonTokenStream = commonTokenStream;
+ }
- /**
- * ctor
- */
- public Antlr4ParseTreeListenerImpl(Writer writer, CommonTokenStream commonTokenStream) {
- this.writer = writer;
- this.commonTokenStream = commonTokenStream;
- }
+ /**
+ * build indent
+ */
+ private String buildIndent(int indent) {
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < (indent * 3); i++) {
+ sb.append(" ");
+ }
+ return sb.toString();
+ }
- /**
- * build indent
- */
- String buildIndent(int indent) {
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < (indent * 3); i++) {
- sb.append(" ");
- }
- return sb.toString();
- }
+ @Override
+ public void enterEveryRule(ParserRuleContext ctx) {
+ /*
+ * check for hidden tokens
+ */
+ final int tokPos = ctx.getStart().getTokenIndex();
+ if (tokPos > hiddenTokenPos) {
+ hiddenTokenPos = tokPos;
+ final List refChannel = commonTokenStream.getHiddenTokensToLeft(tokPos, ANTLRv4Lexer.OFF_CHANNEL);
+ if ((null != refChannel) && (refChannel.size() > 0)) {
+ for (final Token token : refChannel) {
+ /*
+ * print comments
+ */
+ final String str = token.getText().trim();
+ if (str.length() > 0) {
+ if (str.trim().startsWith("//") || str.trim().startsWith("/*")) {
+ if ((false == (ctx instanceof ANTLRv4Parser.GrammarSpecContext))) {
+ writeCR();
+ }
+ write(token.getText());
+ if ((true == ((ctx instanceof ANTLRv4Parser.GrammarSpecContext))) || (ctx instanceof ANTLRv4Parser.GrammarTypeContext)) {
+ writeCR();
+ }
+ }
+ }
+ }
+ }
+ }
+ if (ctx instanceof ANTLRv4Parser.RuleSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.GrammarSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.OptionsSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.TokensSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.ChannelsSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.ModeSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.LexerRuleSpecContext) {
+ this.ctx = ctx;
+ writeCR();
+ } else if (ctx instanceof ANTLRv4Parser.LabeledAltContext) {
+ this.ctx = ctx;
+ } else if (ctx instanceof ANTLRv4Parser.ActionBlockContext) {
+ this.ctx = ctx;
+ }
+ }
- /**
- * write a CR
- */
- void CR() {
- writeSimple("\n");
- writeSimple(buildIndent(indent));
- newline = true;
- }
+ @Override
+ public void exitEveryRule(ParserRuleContext ctx) {
+ // do nothing
+ }
- @Override
- public void enterEveryRule(ParserRuleContext ctx) {
- /*
- * check for hidden tokens
- */
- final int tokPos = ctx.getStart().getTokenIndex();
- if (tokPos > hiddenTokenPos) {
- hiddenTokenPos = tokPos;
- final List refChannel = commonTokenStream.getHiddenTokensToLeft(tokPos, ANTLRv4Lexer.OFF_CHANNEL);
- if ((null != refChannel) && (refChannel.size() > 0)) {
- for (final Token token : refChannel) {
- /*
- * print comments
- */
- final String str = token.getText().trim();
- if (str.length() > 0) {
- if (str.trim().startsWith("//") || str.trim().startsWith("/*")) {
- if ((false == (ctx instanceof ANTLRv4Parser.GrammarSpecContext))) {
- CR();
- }
- write(token.getText());
- if ((true == ((ctx instanceof ANTLRv4Parser.GrammarSpecContext))) || (ctx instanceof ANTLRv4Parser.GrammarTypeContext)) {
- CR();
- }
- }
- }
- }
- }
- }
- if (ctx instanceof ANTLRv4Parser.RuleSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.GrammarSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.OptionsSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.TokensSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.ChannelsSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.ModeSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.LexerRuleSpecContext) {
- this.ctx = ctx;
- CR();
- } else if (ctx instanceof ANTLRv4Parser.LabeledAltContext) {
- this.ctx = ctx;
- } else if (ctx instanceof ANTLRv4Parser.ActionBlockContext) {
- this.ctx = ctx;
- }
- }
+ @Override
+ public void visitErrorNode(ErrorNode node) {
+ // do nothing
+ }
- @Override
- public void exitEveryRule(ParserRuleContext ctx) {}
+ @Override
+ public void visitTerminal(TerminalNode node) {
+ /*
+ * log the rule
+ */
+ LOG.debug(ctx.getClass().getSimpleName() + " : " + node.getText());
+ /*
+ * options indenting
+ */
+ if ((ctx instanceof ANTLRv4Parser.OptionsSpecContext) || (ctx instanceof ANTLRv4Parser.ModeSpecContext) || (ctx instanceof ANTLRv4Parser.TokensSpecContext)
+ || (ctx instanceof ANTLRv4Parser.ChannelsSpecContext)) {
+ if (node.getSymbol().getType() == ANTLRv4Lexer.LBRACE) {
+ indent++;
+ writeCR();
+ write(node);
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.RBRACE) {
+ write(node);
+ indent--;
+ writeCR();
+ } else {
+ write(node);
+ }
+ } else if (ctx instanceof ANTLRv4Parser.LabeledAltContext) {
+ if (node.getSymbol().getType() == ANTLRv4Lexer.LPAREN) {
+ parenthcount++;
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.RPAREN) {
+ parenthcount--;
+ }
+ if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
+ writeCR();
+ write(node);
+ indent--;
+ writeCR();
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.OR) {
+ if (parenthcount == 0) {
+ writeCR();
+ }
+ write(node);
+ } else {
+ if (node.getSymbol().getType() != Recognizer.EOF) {
+ write(node);
+ }
+ }
+ }
+ /*
+ * rule indenting
+ */
+ else if ((ctx instanceof ANTLRv4Parser.RuleSpecContext) || (ctx instanceof ANTLRv4Parser.LexerRuleSpecContext)) {
+ parenthcount = 0;
+ if (node.getSymbol().getType() == ANTLRv4Lexer.COLON) {
+ indent++;
+ writeCR();
+ write(node);
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
+ writeCR();
+ write(node);
+ indent--;
+ writeCR();
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
+ write(node);
+ writeCR();
+ } else {
+ if (node.getSymbol().getType() != Recognizer.EOF) {
+ write(node);
+ }
+ }
+ }
+ /*
+ * grammar spec
+ */
+ else if (ctx instanceof ANTLRv4Parser.GrammarSpecContext) {
+ if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
+ write(node);
+ writeCR();
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
+ write(node);
+ writeCR();
+ } else {
+ write(node);
+ }
+ }
+ /*
+ * grammar spec
+ */
+ else if (ctx instanceof ANTLRv4Parser.ActionBlockContext) {
+ if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
+ write(node);
+ writeCR();
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
+ write(node);
+ writeCR();
+ } else if (node.getSymbol().getType() == ANTLRv4Lexer.AT) {
+ write(node);
+ writeCR();
+ } else {
+ write(node);
+ }
+ }
+ /*
+ * grammar spec
+ */
+ else {
+ write(node);
+ }
+ }
- @Override
- public void visitErrorNode(ErrorNode node) {}
+ /**
+ * write to the output stream
+ */
+ private void write(String str) {
+ /*
+ * print token
+ */
+ writeSimple(str);
+ if (true == newline) {
+ newline = false;
+ }
+ /*
+ * save the previous
+ */
+ previousToken = str;
+ }
- @Override
- public void visitTerminal(TerminalNode node) {
- /*
- * log the rule
- */
- LOG.debug(ctx.getClass().getSimpleName() + " : " + node.getText());
- /*
- * options indenting
- */
- if ((ctx instanceof ANTLRv4Parser.OptionsSpecContext) || (ctx instanceof ANTLRv4Parser.ModeSpecContext) || (ctx instanceof ANTLRv4Parser.TokensSpecContext)
- || (ctx instanceof ANTLRv4Parser.ChannelsSpecContext)) {
- if (node.getSymbol().getType() == ANTLRv4Lexer.LBRACE) {
- indent++;
- CR();
- write(node);
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.RBRACE) {
- write(node);
- indent--;
- CR();
- } else {
- write(node);
- }
- } else if (ctx instanceof ANTLRv4Parser.LabeledAltContext) {
- if (node.getSymbol().getType() == ANTLRv4Lexer.LPAREN) {
- parenthcount++;
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.RPAREN) {
- parenthcount--;
- }
- if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
- CR();
- write(node);
- indent--;
- CR();
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.OR) {
- if (parenthcount == 0) {
- CR();
- }
- write(node);
- } else {
- if (node.getSymbol().getType() != Recognizer.EOF) {
- write(node);
- }
- }
- }
- /*
- * rule indenting
- */
- else if ((ctx instanceof ANTLRv4Parser.RuleSpecContext) || (ctx instanceof ANTLRv4Parser.LexerRuleSpecContext)) {
- parenthcount = 0;
- if (node.getSymbol().getType() == ANTLRv4Lexer.COLON) {
- indent++;
- CR();
- write(node);
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
- CR();
- write(node);
- indent--;
- CR();
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
- write(node);
- CR();
- } else {
- if (node.getSymbol().getType() != Recognizer.EOF) {
- write(node);
- }
- }
- }
- /*
- * grammar spec
- */
- else if (ctx instanceof ANTLRv4Parser.GrammarSpecContext) {
- if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
- write(node);
- CR();
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
- write(node);
- CR();
- } else {
- write(node);
- }
- }
- /*
- * grammar spec
- */
- else if (ctx instanceof ANTLRv4Parser.ActionBlockContext) {
- if (node.getSymbol().getType() == ANTLRv4Lexer.SEMI) {
- write(node);
- CR();
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.DOC_COMMENT) {
- write(node);
- CR();
- } else if (node.getSymbol().getType() == ANTLRv4Lexer.AT) {
- write(node);
- CR();
- } else {
- write(node);
- }
- }
- /*
- * grammar spec
- */
- else {
- write(node);
- }
- }
+ /**
+ * write to the output stream
+ */
+ private void write(TerminalNode node) {
+ LOG.debug("Writing: '" + node.getText() + "'");
+ /*
+ * space before the output
+ */
+ if (false == (ctx instanceof ANTLRv4Parser.ActionBlockContext)) {
+ if ((false == newline) && (false == noSpacingAfterTokens.contains(previousToken)) && (false == noSpacingBeforeTokens.contains(node.getText()))) {
+ writeSimple(" ");
+ }
+ }
+ /*
+ * print token
+ */
+ writeSimple(node.getText());
+ if (true == newline) {
+ newline = false;
+ }
+ /*
+ * save the previous
+ */
+ previousToken = node.getText();
+ }
- private void writeSimple(String string) {
- try {
- writer.write(string);
- } catch (IOException e) {
- throw new RuntimeException("Could not write to writer", e);
- }
- }
+ /**
+ * write a CR
+ */
+ private void writeCR() {
+ writeSimple("\n");
+ writeSimple(buildIndent(indent));
+ newline = true;
+ }
- /**
- * write to the output stream
- */
- void write(String str) {
- /*
- * print token
- */
- writeSimple(str);
- if (true == newline) {
- newline = false;
- }
- /*
- * save the previous
- */
- previousToken = str;
-
- }
-
- /**
- * write to the output stream
- */
- void write(TerminalNode node) {
- LOG.debug("Writing: '" + node.getText() + "'");
- /*
- * space before the output
- */
- if (false == (ctx instanceof ANTLRv4Parser.ActionBlockContext)) {
- if ((false == newline) && (false == noSpacingAfterTokens.contains(previousToken)) && (false == noSpacingBeforeTokens.contains(node.getText()))) {
- writeSimple(" ");
- }
- }
- /*
- * print token
- */
- writeSimple(node.getText());
- if (true == newline) {
- newline = false;
- }
- /*
- * save the previous
- */
- previousToken = node.getText();
- }
+ private void writeSimple(String string) {
+ try {
+ writer.write(string);
+ } catch (final IOException e) {
+ throw new RuntimeException("Could not write to writer", e);
+ }
+ }
}
diff --git a/antlr4-formatter/src/main/java/org/antlr/parser/antlr4/LexerAdaptor.java b/antlr4-formatter/src/main/java/org/antlr/parser/antlr4/LexerAdaptor.java
index 0ac2b74..416a6f8 100644
--- a/antlr4-formatter/src/main/java/org/antlr/parser/antlr4/LexerAdaptor.java
+++ b/antlr4-formatter/src/main/java/org/antlr/parser/antlr4/LexerAdaptor.java
@@ -6,68 +6,68 @@
import org.antlr.v4.runtime.misc.Interval;
public abstract class LexerAdaptor extends Lexer {
- /**
- * Track whether we are inside of a rule and whether it is lexical parser. currentRuleType==Token.INVALID_TYPE means that we are outside of a rule. At the first sign of a rule name reference and
- * currentRuleType==invalid, we can assume that we are starting a parser rule. Similarly, seeing a token reference when not already in rule means starting a token rule. The terminating ';' of a
- * rule, flips this back to invalid type. This is not perfect logic but works. For example, "grammar T;" means that we start and stop a lexical rule for the "T;". Dangerous but works. The whole
- * point of this state information is to distinguish between [..arg actions..] and [charsets]. Char sets can only occur in lexical rules and arg actions cannot occur.
- */
- private int currentRuleType = Token.INVALID_TYPE;
+ /**
+ * Track whether we are inside of a rule and whether it is lexical parser. currentRuleType==Token.INVALID_TYPE means that we are outside of a rule. At the first sign of a rule name reference and
+ * currentRuleType==invalid, we can assume that we are starting a parser rule. Similarly, seeing a token reference when not already in rule means starting a token rule. The terminating ';' of a
+ * rule, flips this back to invalid type. This is not perfect logic but works. For example, "grammar T;" means that we start and stop a lexical rule for the "T;". Dangerous but works. The whole
+ * point of this state information is to distinguish between [..arg actions..] and [charsets]. Char sets can only occur in lexical rules and arg actions cannot occur.
+ */
+ private int currentRuleType = Token.INVALID_TYPE;
- public LexerAdaptor(CharStream input) {
- super(input);
- }
+ public LexerAdaptor(CharStream input) {
+ super(input);
+ }
- @Override
- public Token emit() {
- if (_type == ANTLRv4Lexer.ID) {
- final String firstChar = _input.getText(Interval.of(_tokenStartCharIndex, _tokenStartCharIndex));
- if (Character.isUpperCase(firstChar.charAt(0))) {
- _type = ANTLRv4Lexer.TOKEN_REF;
- } else {
- _type = ANTLRv4Lexer.RULE_REF;
- }
- if (currentRuleType == Token.INVALID_TYPE) { // if outside of rule def
- currentRuleType = _type; // set to inside lexer or parser rule
- }
- } else if (_type == ANTLRv4Lexer.SEMI) { // exit rule def
- currentRuleType = Token.INVALID_TYPE;
- }
- return super.emit();
- }
+ @Override
+ public Token emit() {
+ if (_type == ANTLRv4Lexer.ID) {
+ final String firstChar = _input.getText(Interval.of(_tokenStartCharIndex, _tokenStartCharIndex));
+ if (Character.isUpperCase(firstChar.charAt(0))) {
+ _type = ANTLRv4Lexer.TOKEN_REF;
+ } else {
+ _type = ANTLRv4Lexer.RULE_REF;
+ }
+ if (currentRuleType == Token.INVALID_TYPE) { // if outside of rule def
+ currentRuleType = _type; // set to inside lexer or parser rule
+ }
+ } else if (_type == ANTLRv4Lexer.SEMI) { // exit rule def
+ currentRuleType = Token.INVALID_TYPE;
+ }
+ return super.emit();
+ }
- public int getCurrentRuleType() {
- return currentRuleType;
- }
+ public int getCurrentRuleType() {
+ return currentRuleType;
+ }
- protected void handleBeginArgument() {
- if (inLexerRule()) {
- pushMode(ANTLRv4Lexer.LexerCharSet);
- more();
- } else {
- pushMode(ANTLRv4Lexer.Argument);
- }
- }
+ protected void handleBeginArgument() {
+ if (inLexerRule()) {
+ pushMode(ANTLRv4Lexer.LexerCharSet);
+ more();
+ } else {
+ pushMode(ANTLRv4Lexer.Argument);
+ }
+ }
- protected void handleEndAction() {
- popMode();
- if (_modeStack.size() > 0) {
- setType(ANTLRv4Lexer.ACTION_CONTENT);
- }
- }
+ protected void handleEndAction() {
+ popMode();
+ if (_modeStack.size() > 0) {
+ setType(ANTLRv4Lexer.ACTION_CONTENT);
+ }
+ }
- protected void handleEndArgument() {
- popMode();
- if (_modeStack.size() > 0) {
- setType(ANTLRv4Lexer.ARGUMENT_CONTENT);
- }
- }
+ protected void handleEndArgument() {
+ popMode();
+ if (_modeStack.size() > 0) {
+ setType(ANTLRv4Lexer.ARGUMENT_CONTENT);
+ }
+ }
- private boolean inLexerRule() {
- return currentRuleType == ANTLRv4Lexer.TOKEN_REF;
- }
+ private boolean inLexerRule() {
+ return currentRuleType == ANTLRv4Lexer.TOKEN_REF;
+ }
- public void setCurrentRuleType(int ruleType) {
- currentRuleType = ruleType;
- }
+ public void setCurrentRuleType(int ruleType) {
+ currentRuleType = ruleType;
+ }
}
diff --git a/antlr4-formatter/src/test/java/com/khubla/antlr4formatter/Antlr4FormatterTest.java b/antlr4-formatter/src/test/java/com/khubla/antlr4formatter/Antlr4FormatterTest.java
index abf5713..2635230 100644
--- a/antlr4-formatter/src/test/java/com/khubla/antlr4formatter/Antlr4FormatterTest.java
+++ b/antlr4-formatter/src/test/java/com/khubla/antlr4formatter/Antlr4FormatterTest.java
@@ -13,28 +13,24 @@
import org.junit.Test;
public class Antlr4FormatterTest {
-
- @Test
- public void formatString() throws IOException {
- // given
- String unformattedGrammar = readFileAsUtf8ToString("Hello.unformatted.g4");
- String formattedGrammar = readFileAsUtf8ToString("Hello.formatted.g4");
-
- // when
- String result = Antlr4Formatter.format(unformattedGrammar);
-
- // then
- assertThat(result).isEqualTo(formattedGrammar);
- }
-
- private String readFileAsUtf8ToString(String fileName) throws IOException {
- try {
- URI uri = Antlr4FormatterTest.class.getClassLoader().getResource(fileName).toURI();
- Path path = Paths.get(uri);
- return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
- } catch (URISyntaxException e) {
- throw new RuntimeException(e);
- }
- }
-
+ @Test
+ public void formatString() throws Antlr4FormatterException, IOException {
+ // given
+ String unformattedGrammar = readFileAsUtf8ToString("Hello.unformatted.g4");
+ String formattedGrammar = readFileAsUtf8ToString("Hello.formatted.g4");
+ // when
+ String result = Antlr4Formatter.format(unformattedGrammar);
+ // then
+ assertThat(result).isEqualTo(formattedGrammar);
+ }
+
+ private String readFileAsUtf8ToString(String fileName) throws IOException, Antlr4FormatterException {
+ try {
+ URI uri = Antlr4FormatterTest.class.getClassLoader().getResource(fileName).toURI();
+ Path path = Paths.get(uri);
+ return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
+ } catch (URISyntaxException e) {
+ throw new Antlr4FormatterException(e);
+ }
+ }
}