BAEL-1732 - Java with ANTLR (#4243)

Examples for Java with ANTLR article
This commit is contained in:
Mariusz Kuligowski 2018-06-26 17:47:49 +02:00 committed by Josh Cummings
parent d1e092b850
commit 287d0a062a
10 changed files with 2045 additions and 2 deletions

66
antlr/pom.xml Normal file
View File

@ -0,0 +1,66 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>antlr</artifactId>
<name>antlr</name>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<build>
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr4-maven-plugin</artifactId>
<version>${antlr.version}</version>
<executions>
<execution>
<goals>
<goal>antlr4</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${mojo.version}</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated-sources/antlr4</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.antlr</groupId>
<artifactId>antlr4-runtime</artifactId>
<version>${antlr.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
<antlr.version>4.7.1</antlr.version>
<junit.version>4.12</junit.version>
<mojo.version>3.0.0</mojo.version>
</properties>
</project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
grammar Log;
log : entry+;
entry : timestamp ' ' level ' ' message CRLF;
timestamp : DATE ' ' TIME;
level : 'ERROR' | 'INFO' | 'DEBUG';
message : (TEXT | ' ')+;
fragment DIGIT : [0-9];
fragment TWODIGIT : DIGIT DIGIT;
fragment LETTER : [A-Za-z];
DATE : TWODIGIT TWODIGIT '-' LETTER LETTER LETTER '-' TWODIGIT;
TIME : TWODIGIT ':' TWODIGIT ':' TWODIGIT;
TEXT : LETTER+;
CRLF : '\r'? '\n' | '\r';

View File

@ -0,0 +1,28 @@
package com.baeldung.antlr.java;
import com.baeldung.antlr.Java8BaseListener;
import com.baeldung.antlr.Java8Parser;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class UppercaseMethodListener extends Java8BaseListener {
private List<String> errors = new ArrayList<String>();
@Override
public void enterMethodDeclarator(Java8Parser.MethodDeclaratorContext ctx) {
TerminalNode node = ctx.Identifier();
String methodName = node.getText();
if (Character.isUpperCase(methodName.charAt(0))){
errors.add(String.format("Method %s is uppercased!", methodName));
}
}
public List<String> getErrors(){
return Collections.unmodifiableList(errors);
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.antlr.log;
import com.baeldung.antlr.LogBaseListener;
import com.baeldung.antlr.LogParser;
import com.baeldung.antlr.log.model.LogLevel;
import com.baeldung.antlr.log.model.LogEntry;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
public class LogListener extends LogBaseListener {
private static final DateTimeFormatter DEFAULT_DATETIME_FORMATTER
= DateTimeFormatter.ofPattern("yyyy-MMM-dd HH:mm:ss", Locale.ENGLISH);
private List<LogEntry> entries = new ArrayList<>();
private LogEntry currentLogEntry;
@Override
public void enterEntry(LogParser.EntryContext ctx) {
this.currentLogEntry = new LogEntry();
}
@Override
public void exitEntry(LogParser.EntryContext ctx) {
entries.add(currentLogEntry);
}
@Override
public void enterTimestamp(LogParser.TimestampContext ctx) {
currentLogEntry.setTimestamp(LocalDateTime.parse(ctx.getText(), DEFAULT_DATETIME_FORMATTER));
}
@Override
public void enterMessage(LogParser.MessageContext ctx) {
currentLogEntry.setMessage(ctx.getText());
}
@Override
public void enterLevel(LogParser.LevelContext ctx) {
currentLogEntry.setLevel(LogLevel.valueOf(ctx.getText()));
}
public List<LogEntry> getEntries() {
return Collections.unmodifiableList(entries);
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.antlr.log.model;
import java.time.LocalDateTime;
public class LogEntry {
private LogLevel level;
private String message;
private LocalDateTime timestamp;
public LogLevel getLevel() {
return level;
}
public void setLevel(LogLevel level) {
this.level = level;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public LocalDateTime getTimestamp() {
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp) {
this.timestamp = timestamp;
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.antlr.log.model;
public enum LogLevel {
DEBUG, INFO, ERROR
}

View File

@ -0,0 +1,30 @@
package com.baeldung.antlr;
import com.baeldung.antlr.java.UppercaseMethodListener;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
public class JavaParserUnitTest {
@Test
public void whenOneMethodStartsWithUpperCase_thenOneErrorReturned() throws Exception{
String javaClassContent = "public class SampleClass { void DoSomething(){} }";
Java8Lexer java8Lexer = new Java8Lexer(CharStreams.fromString(javaClassContent));
CommonTokenStream tokens = new CommonTokenStream(java8Lexer);
Java8Parser java8Parser = new Java8Parser(tokens);
ParseTree tree = java8Parser.compilationUnit();
ParseTreeWalker walker = new ParseTreeWalker();
UppercaseMethodListener uppercaseMethodListener = new UppercaseMethodListener();
walker.walk(uppercaseMethodListener, tree);
assertThat(uppercaseMethodListener.getErrors().size(), is(1));
assertThat(uppercaseMethodListener.getErrors().get(0),
is("Method DoSomething is uppercased!"));
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.antlr;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import com.baeldung.antlr.log.LogListener;
import com.baeldung.antlr.log.model.LogLevel;
import com.baeldung.antlr.log.model.LogEntry;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
import org.junit.Test;
import java.time.LocalDateTime;
public class LogParserUnitTest {
@Test
public void whenLogContainsOneErrorLogEntry_thenOneErrorIsReturned() throws Exception {
String logLines = "2018-May-05 14:20:21 DEBUG entering awesome method\r\n" +
"2018-May-05 14:20:24 ERROR Bad thing happened\r\n";
LogLexer serverLogLexer = new LogLexer(CharStreams.fromString(logLines));
CommonTokenStream tokens = new CommonTokenStream( serverLogLexer );
LogParser logParser = new LogParser(tokens);
ParseTreeWalker walker = new ParseTreeWalker();
LogListener logWalker = new LogListener();
walker.walk(logWalker, logParser.log());
assertThat(logWalker.getEntries().size(), is(2));
LogEntry error = logWalker.getEntries().get(1);
assertThat(error.getLevel(), is(LogLevel.ERROR));
assertThat(error.getMessage(), is("Bad thing happened"));
assertThat(error.getTimestamp(), is(LocalDateTime.of(2018,5,5,14,20,24)));
}
}

View File

@ -266,8 +266,9 @@
<module>twilio</module>
<module>spring-boot-ctx-fluent</module>
<module>java-ee-8-security-api</module>
<module>spring-webflux-amqp</module>
<module>maven-archetype</module>
<module>spring-webflux-amqp</module>
<module>antlr</module>
<module>maven-archetype</module>
</modules>
<dependencies>