diff --git a/antlr/pom.xml b/antlr/pom.xml
new file mode 100644
index 0000000000..15fe79afca
--- /dev/null
+++ b/antlr/pom.xml
@@ -0,0 +1,66 @@
+
+ 4.0.0
+ antlr
+ antlr
+
+
+ com.baeldung
+ parent-modules
+ 1.0.0-SNAPSHOT
+
+
+
+
+
+ org.antlr
+ antlr4-maven-plugin
+ ${antlr.version}
+
+
+
+ antlr4
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ ${mojo.version}
+
+
+ generate-sources
+
+ add-source
+
+
+
+ ${basedir}/target/generated-sources/antlr4
+
+
+
+
+
+
+
+
+
+ org.antlr
+ antlr4-runtime
+ ${antlr.version}
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+
+ 1.8
+ 4.7.1
+ 4.12
+ 3.0.0
+
+
\ No newline at end of file
diff --git a/antlr/src/main/antlr4/com/baeldung/antlr/Java8.g4 b/antlr/src/main/antlr4/com/baeldung/antlr/Java8.g4
new file mode 100644
index 0000000000..5cde8f9ace
--- /dev/null
+++ b/antlr/src/main/antlr4/com/baeldung/antlr/Java8.g4
@@ -0,0 +1,1775 @@
+/*
+ * [The "BSD license"]
+ * Copyright (c) 2014 Terence Parr
+ * Copyright (c) 2014 Sam Harwell
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * A Java 8 grammar for ANTLR 4 derived from the Java Language Specification
+ * chapter 19.
+ *
+ * NOTE: This grammar results in a generated parser that is much slower
+ * than the Java 7 grammar in the grammars-v4/java directory. This
+ * one is, however, extremely close to the spec.
+ *
+ * You can test with
+ *
+ * $ antlr4 Java8.g4
+ * $ javac *.java
+ * $ grun Java8 compilationUnit *.java
+ *
+ * Or,
+~/antlr/code/grammars-v4/java8 $ java Test .
+/Users/parrt/antlr/code/grammars-v4/java8/./Java8BaseListener.java
+/Users/parrt/antlr/code/grammars-v4/java8/./Java8Lexer.java
+/Users/parrt/antlr/code/grammars-v4/java8/./Java8Listener.java
+/Users/parrt/antlr/code/grammars-v4/java8/./Java8Parser.java
+/Users/parrt/antlr/code/grammars-v4/java8/./Test.java
+Total lexer+parser dateTime 30844ms.
+ */
+grammar Java8;
+
+/*
+ * Productions from §3 (Lexical Structure)
+ */
+
+literal
+ : IntegerLiteral
+ | FloatingPointLiteral
+ | BooleanLiteral
+ | CharacterLiteral
+ | StringLiteral
+ | NullLiteral
+ ;
+
+/*
+ * Productions from §4 (Types, Values, and Variables)
+ */
+
+primitiveType
+ : annotation* numericType
+ | annotation* 'boolean'
+ ;
+
+numericType
+ : integralType
+ | floatingPointType
+ ;
+
+integralType
+ : 'byte'
+ | 'short'
+ | 'int'
+ | 'long'
+ | 'char'
+ ;
+
+floatingPointType
+ : 'float'
+ | 'double'
+ ;
+
+referenceType
+ : classOrInterfaceType
+ | typeVariable
+ | arrayType
+ ;
+
+classOrInterfaceType
+ : ( classType_lfno_classOrInterfaceType
+ | interfaceType_lfno_classOrInterfaceType
+ )
+ ( classType_lf_classOrInterfaceType
+ | interfaceType_lf_classOrInterfaceType
+ )*
+ ;
+
+classType
+ : annotation* Identifier typeArguments?
+ | classOrInterfaceType '.' annotation* Identifier typeArguments?
+ ;
+
+classType_lf_classOrInterfaceType
+ : '.' annotation* Identifier typeArguments?
+ ;
+
+classType_lfno_classOrInterfaceType
+ : annotation* Identifier typeArguments?
+ ;
+
+interfaceType
+ : classType
+ ;
+
+interfaceType_lf_classOrInterfaceType
+ : classType_lf_classOrInterfaceType
+ ;
+
+interfaceType_lfno_classOrInterfaceType
+ : classType_lfno_classOrInterfaceType
+ ;
+
+typeVariable
+ : annotation* Identifier
+ ;
+
+arrayType
+ : primitiveType dims
+ | classOrInterfaceType dims
+ | typeVariable dims
+ ;
+
+dims
+ : annotation* '[' ']' (annotation* '[' ']')*
+ ;
+
+typeParameter
+ : typeParameterModifier* Identifier typeBound?
+ ;
+
+typeParameterModifier
+ : annotation
+ ;
+
+typeBound
+ : 'extends' typeVariable
+ | 'extends' classOrInterfaceType additionalBound*
+ ;
+
+additionalBound
+ : '&' interfaceType
+ ;
+
+typeArguments
+ : '<' typeArgumentList '>'
+ ;
+
+typeArgumentList
+ : typeArgument (',' typeArgument)*
+ ;
+
+typeArgument
+ : referenceType
+ | wildcard
+ ;
+
+wildcard
+ : annotation* '?' wildcardBounds?
+ ;
+
+wildcardBounds
+ : 'extends' referenceType
+ | 'super' referenceType
+ ;
+
+/*
+ * Productions from §6 (Names)
+ */
+
+packageName
+ : Identifier
+ | packageName '.' Identifier
+ ;
+
+typeName
+ : Identifier
+ | packageOrTypeName '.' Identifier
+ ;
+
+packageOrTypeName
+ : Identifier
+ | packageOrTypeName '.' Identifier
+ ;
+
+expressionName
+ : Identifier
+ | ambiguousName '.' Identifier
+ ;
+
+methodName
+ : Identifier
+ ;
+
+ambiguousName
+ : Identifier
+ | ambiguousName '.' Identifier
+ ;
+
+/*
+ * Productions from §7 (Packages)
+ */
+
+compilationUnit
+ : packageDeclaration? importDeclaration* typeDeclaration* EOF
+ ;
+
+packageDeclaration
+ : packageModifier* 'package' packageName ';'
+ ;
+
+packageModifier
+ : annotation
+ ;
+
+importDeclaration
+ : singleTypeImportDeclaration
+ | typeImportOnDemandDeclaration
+ | singleStaticImportDeclaration
+ | staticImportOnDemandDeclaration
+ ;
+
+singleTypeImportDeclaration
+ : 'import' typeName ';'
+ ;
+
+typeImportOnDemandDeclaration
+ : 'import' packageOrTypeName '.' '*' ';'
+ ;
+
+singleStaticImportDeclaration
+ : 'import' 'static' typeName '.' Identifier ';'
+ ;
+
+staticImportOnDemandDeclaration
+ : 'import' 'static' typeName '.' '*' ';'
+ ;
+
+typeDeclaration
+ : classDeclaration
+ | interfaceDeclaration
+ | ';'
+ ;
+
+/*
+ * Productions from §8 (Classes)
+ */
+
+classDeclaration
+ : normalClassDeclaration
+ | enumDeclaration
+ ;
+
+normalClassDeclaration
+ : classModifier* 'class' Identifier typeParameters? superclass? superinterfaces? classBody
+ ;
+
+classModifier
+ : annotation
+ | 'public'
+ | 'protected'
+ | 'private'
+ | 'abstract'
+ | 'static'
+ | 'final'
+ | 'strictfp'
+ ;
+
+typeParameters
+ : '<' typeParameterList '>'
+ ;
+
+typeParameterList
+ : typeParameter (',' typeParameter)*
+ ;
+
+superclass
+ : 'extends' classType
+ ;
+
+superinterfaces
+ : 'implements' interfaceTypeList
+ ;
+
+interfaceTypeList
+ : interfaceType (',' interfaceType)*
+ ;
+
+classBody
+ : '{' classBodyDeclaration* '}'
+ ;
+
+classBodyDeclaration
+ : classMemberDeclaration
+ | instanceInitializer
+ | staticInitializer
+ | constructorDeclaration
+ ;
+
+classMemberDeclaration
+ : fieldDeclaration
+ | methodDeclaration
+ | classDeclaration
+ | interfaceDeclaration
+ | ';'
+ ;
+
+fieldDeclaration
+ : fieldModifier* unannType variableDeclaratorList ';'
+ ;
+
+fieldModifier
+ : annotation
+ | 'public'
+ | 'protected'
+ | 'private'
+ | 'static'
+ | 'final'
+ | 'transient'
+ | 'volatile'
+ ;
+
+variableDeclaratorList
+ : variableDeclarator (',' variableDeclarator)*
+ ;
+
+variableDeclarator
+ : variableDeclaratorId ('=' variableInitializer)?
+ ;
+
+variableDeclaratorId
+ : Identifier dims?
+ ;
+
+variableInitializer
+ : expression
+ | arrayInitializer
+ ;
+
+unannType
+ : unannPrimitiveType
+ | unannReferenceType
+ ;
+
+unannPrimitiveType
+ : numericType
+ | 'boolean'
+ ;
+
+unannReferenceType
+ : unannClassOrInterfaceType
+ | unannTypeVariable
+ | unannArrayType
+ ;
+
+unannClassOrInterfaceType
+ : ( unannClassType_lfno_unannClassOrInterfaceType
+ | unannInterfaceType_lfno_unannClassOrInterfaceType
+ )
+ ( unannClassType_lf_unannClassOrInterfaceType
+ | unannInterfaceType_lf_unannClassOrInterfaceType
+ )*
+ ;
+
+unannClassType
+ : Identifier typeArguments?
+ | unannClassOrInterfaceType '.' annotation* Identifier typeArguments?
+ ;
+
+unannClassType_lf_unannClassOrInterfaceType
+ : '.' annotation* Identifier typeArguments?
+ ;
+
+unannClassType_lfno_unannClassOrInterfaceType
+ : Identifier typeArguments?
+ ;
+
+unannInterfaceType
+ : unannClassType
+ ;
+
+unannInterfaceType_lf_unannClassOrInterfaceType
+ : unannClassType_lf_unannClassOrInterfaceType
+ ;
+
+unannInterfaceType_lfno_unannClassOrInterfaceType
+ : unannClassType_lfno_unannClassOrInterfaceType
+ ;
+
+unannTypeVariable
+ : Identifier
+ ;
+
+unannArrayType
+ : unannPrimitiveType dims
+ | unannClassOrInterfaceType dims
+ | unannTypeVariable dims
+ ;
+
+methodDeclaration
+ : methodModifier* methodHeader methodBody
+ ;
+
+methodModifier
+ : annotation
+ | 'public'
+ | 'protected'
+ | 'private'
+ | 'abstract'
+ | 'static'
+ | 'final'
+ | 'synchronized'
+ | 'native'
+ | 'strictfp'
+ ;
+
+methodHeader
+ : result methodDeclarator throws_?
+ | typeParameters annotation* result methodDeclarator throws_?
+ ;
+
+result
+ : unannType
+ | 'void'
+ ;
+
+methodDeclarator
+ : Identifier '(' formalParameterList? ')' dims?
+ ;
+
+formalParameterList
+ : receiverParameter
+ | formalParameters ',' lastFormalParameter
+ | lastFormalParameter
+ ;
+
+formalParameters
+ : formalParameter (',' formalParameter)*
+ | receiverParameter (',' formalParameter)*
+ ;
+
+formalParameter
+ : variableModifier* unannType variableDeclaratorId
+ ;
+
+variableModifier
+ : annotation
+ | 'final'
+ ;
+
+lastFormalParameter
+ : variableModifier* unannType annotation* '...' variableDeclaratorId
+ | formalParameter
+ ;
+
+receiverParameter
+ : annotation* unannType (Identifier '.')? 'this'
+ ;
+
+throws_
+ : 'throws' exceptionTypeList
+ ;
+
+exceptionTypeList
+ : exceptionType (',' exceptionType)*
+ ;
+
+exceptionType
+ : classType
+ | typeVariable
+ ;
+
+methodBody
+ : block
+ | ';'
+ ;
+
+instanceInitializer
+ : block
+ ;
+
+staticInitializer
+ : 'static' block
+ ;
+
+constructorDeclaration
+ : constructorModifier* constructorDeclarator throws_? constructorBody
+ ;
+
+constructorModifier
+ : annotation
+ | 'public'
+ | 'protected'
+ | 'private'
+ ;
+
+constructorDeclarator
+ : typeParameters? simpleTypeName '(' formalParameterList? ')'
+ ;
+
+simpleTypeName
+ : Identifier
+ ;
+
+constructorBody
+ : '{' explicitConstructorInvocation? blockStatements? '}'
+ ;
+
+explicitConstructorInvocation
+ : typeArguments? 'this' '(' argumentList? ')' ';'
+ | typeArguments? 'super' '(' argumentList? ')' ';'
+ | expressionName '.' typeArguments? 'super' '(' argumentList? ')' ';'
+ | primary '.' typeArguments? 'super' '(' argumentList? ')' ';'
+ ;
+
+enumDeclaration
+ : classModifier* 'enum' Identifier superinterfaces? enumBody
+ ;
+
+enumBody
+ : '{' enumConstantList? ','? enumBodyDeclarations? '}'
+ ;
+
+enumConstantList
+ : enumConstant (',' enumConstant)*
+ ;
+
+enumConstant
+ : enumConstantModifier* Identifier ('(' argumentList? ')')? classBody?
+ ;
+
+enumConstantModifier
+ : annotation
+ ;
+
+enumBodyDeclarations
+ : ';' classBodyDeclaration*
+ ;
+
+/*
+ * Productions from §9 (Interfaces)
+ */
+
+interfaceDeclaration
+ : normalInterfaceDeclaration
+ | annotationTypeDeclaration
+ ;
+
+normalInterfaceDeclaration
+ : interfaceModifier* 'interface' Identifier typeParameters? extendsInterfaces? interfaceBody
+ ;
+
+interfaceModifier
+ : annotation
+ | 'public'
+ | 'protected'
+ | 'private'
+ | 'abstract'
+ | 'static'
+ | 'strictfp'
+ ;
+
+extendsInterfaces
+ : 'extends' interfaceTypeList
+ ;
+
+interfaceBody
+ : '{' interfaceMemberDeclaration* '}'
+ ;
+
+interfaceMemberDeclaration
+ : constantDeclaration
+ | interfaceMethodDeclaration
+ | classDeclaration
+ | interfaceDeclaration
+ | ';'
+ ;
+
+constantDeclaration
+ : constantModifier* unannType variableDeclaratorList ';'
+ ;
+
+constantModifier
+ : annotation
+ | 'public'
+ | 'static'
+ | 'final'
+ ;
+
+interfaceMethodDeclaration
+ : interfaceMethodModifier* methodHeader methodBody
+ ;
+
+interfaceMethodModifier
+ : annotation
+ | 'public'
+ | 'abstract'
+ | 'default'
+ | 'static'
+ | 'strictfp'
+ ;
+
+annotationTypeDeclaration
+ : interfaceModifier* '@' 'interface' Identifier annotationTypeBody
+ ;
+
+annotationTypeBody
+ : '{' annotationTypeMemberDeclaration* '}'
+ ;
+
+annotationTypeMemberDeclaration
+ : annotationTypeElementDeclaration
+ | constantDeclaration
+ | classDeclaration
+ | interfaceDeclaration
+ | ';'
+ ;
+
+annotationTypeElementDeclaration
+ : annotationTypeElementModifier* unannType Identifier '(' ')' dims? defaultValue? ';'
+ ;
+
+annotationTypeElementModifier
+ : annotation
+ | 'public'
+ | 'abstract'
+ ;
+
+defaultValue
+ : 'default' elementValue
+ ;
+
+annotation
+ : normalAnnotation
+ | markerAnnotation
+ | singleElementAnnotation
+ ;
+
+normalAnnotation
+ : '@' typeName '(' elementValuePairList? ')'
+ ;
+
+elementValuePairList
+ : elementValuePair (',' elementValuePair)*
+ ;
+
+elementValuePair
+ : Identifier '=' elementValue
+ ;
+
+elementValue
+ : conditionalExpression
+ | elementValueArrayInitializer
+ | annotation
+ ;
+
+elementValueArrayInitializer
+ : '{' elementValueList? ','? '}'
+ ;
+
+elementValueList
+ : elementValue (',' elementValue)*
+ ;
+
+markerAnnotation
+ : '@' typeName
+ ;
+
+singleElementAnnotation
+ : '@' typeName '(' elementValue ')'
+ ;
+
+/*
+ * Productions from §10 (Arrays)
+ */
+
+arrayInitializer
+ : '{' variableInitializerList? ','? '}'
+ ;
+
+variableInitializerList
+ : variableInitializer (',' variableInitializer)*
+ ;
+
+/*
+ * Productions from §14 (Blocks and Statements)
+ */
+
+block
+ : '{' blockStatements? '}'
+ ;
+
+blockStatements
+ : blockStatement+
+ ;
+
+blockStatement
+ : localVariableDeclarationStatement
+ | classDeclaration
+ | statement
+ ;
+
+localVariableDeclarationStatement
+ : localVariableDeclaration ';'
+ ;
+
+localVariableDeclaration
+ : variableModifier* unannType variableDeclaratorList
+ ;
+
+statement
+ : statementWithoutTrailingSubstatement
+ | labeledStatement
+ | ifThenStatement
+ | ifThenElseStatement
+ | whileStatement
+ | forStatement
+ ;
+
+statementNoShortIf
+ : statementWithoutTrailingSubstatement
+ | labeledStatementNoShortIf
+ | ifThenElseStatementNoShortIf
+ | whileStatementNoShortIf
+ | forStatementNoShortIf
+ ;
+
+statementWithoutTrailingSubstatement
+ : block
+ | emptyStatement
+ | expressionStatement
+ | assertStatement
+ | switchStatement
+ | doStatement
+ | breakStatement
+ | continueStatement
+ | returnStatement
+ | synchronizedStatement
+ | throwStatement
+ | tryStatement
+ ;
+
+emptyStatement
+ : ';'
+ ;
+
+labeledStatement
+ : Identifier ':' statement
+ ;
+
+labeledStatementNoShortIf
+ : Identifier ':' statementNoShortIf
+ ;
+
+expressionStatement
+ : statementExpression ';'
+ ;
+
+statementExpression
+ : assignment
+ | preIncrementExpression
+ | preDecrementExpression
+ | postIncrementExpression
+ | postDecrementExpression
+ | methodInvocation
+ | classInstanceCreationExpression
+ ;
+
+ifThenStatement
+ : 'if' '(' expression ')' statement
+ ;
+
+ifThenElseStatement
+ : 'if' '(' expression ')' statementNoShortIf 'else' statement
+ ;
+
+ifThenElseStatementNoShortIf
+ : 'if' '(' expression ')' statementNoShortIf 'else' statementNoShortIf
+ ;
+
+assertStatement
+ : 'assert' expression ';'
+ | 'assert' expression ':' expression ';'
+ ;
+
+switchStatement
+ : 'switch' '(' expression ')' switchBlock
+ ;
+
+switchBlock
+ : '{' switchBlockStatementGroup* switchLabel* '}'
+ ;
+
+switchBlockStatementGroup
+ : switchLabels blockStatements
+ ;
+
+switchLabels
+ : switchLabel switchLabel*
+ ;
+
+switchLabel
+ : 'case' constantExpression ':'
+ | 'case' enumConstantName ':'
+ | 'default' ':'
+ ;
+
+enumConstantName
+ : Identifier
+ ;
+
+whileStatement
+ : 'while' '(' expression ')' statement
+ ;
+
+whileStatementNoShortIf
+ : 'while' '(' expression ')' statementNoShortIf
+ ;
+
+doStatement
+ : 'do' statement 'while' '(' expression ')' ';'
+ ;
+
+forStatement
+ : basicForStatement
+ | enhancedForStatement
+ ;
+
+forStatementNoShortIf
+ : basicForStatementNoShortIf
+ | enhancedForStatementNoShortIf
+ ;
+
+basicForStatement
+ : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statement
+ ;
+
+basicForStatementNoShortIf
+ : 'for' '(' forInit? ';' expression? ';' forUpdate? ')' statementNoShortIf
+ ;
+
+forInit
+ : statementExpressionList
+ | localVariableDeclaration
+ ;
+
+forUpdate
+ : statementExpressionList
+ ;
+
+statementExpressionList
+ : statementExpression (',' statementExpression)*
+ ;
+
+enhancedForStatement
+ : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statement
+ ;
+
+enhancedForStatementNoShortIf
+ : 'for' '(' variableModifier* unannType variableDeclaratorId ':' expression ')' statementNoShortIf
+ ;
+
+breakStatement
+ : 'break' Identifier? ';'
+ ;
+
+continueStatement
+ : 'continue' Identifier? ';'
+ ;
+
+returnStatement
+ : 'return' expression? ';'
+ ;
+
+throwStatement
+ : 'throw' expression ';'
+ ;
+
+synchronizedStatement
+ : 'synchronized' '(' expression ')' block
+ ;
+
+tryStatement
+ : 'try' block catches
+ | 'try' block catches? finally_
+ | tryWithResourcesStatement
+ ;
+
+catches
+ : catchClause catchClause*
+ ;
+
+catchClause
+ : 'catch' '(' catchFormalParameter ')' block
+ ;
+
+catchFormalParameter
+ : variableModifier* catchType variableDeclaratorId
+ ;
+
+catchType
+ : unannClassType ('|' classType)*
+ ;
+
+finally_
+ : 'finally' block
+ ;
+
+tryWithResourcesStatement
+ : 'try' resourceSpecification block catches? finally_?
+ ;
+
+resourceSpecification
+ : '(' resourceList ';'? ')'
+ ;
+
+resourceList
+ : resource (';' resource)*
+ ;
+
+resource
+ : variableModifier* unannType variableDeclaratorId '=' expression
+ ;
+
+/*
+ * Productions from §15 (Expressions)
+ */
+
+primary
+ : ( primaryNoNewArray_lfno_primary
+ | arrayCreationExpression
+ )
+ ( primaryNoNewArray_lf_primary
+ )*
+ ;
+
+primaryNoNewArray
+ : literal
+ | typeName ('[' ']')* '.' 'class'
+ | 'void' '.' 'class'
+ | 'this'
+ | typeName '.' 'this'
+ | '(' expression ')'
+ | classInstanceCreationExpression
+ | fieldAccess
+ | arrayAccess
+ | methodInvocation
+ | methodReference
+ ;
+
+primaryNoNewArray_lf_arrayAccess
+ :
+ ;
+
+primaryNoNewArray_lfno_arrayAccess
+ : literal
+ | typeName ('[' ']')* '.' 'class'
+ | 'void' '.' 'class'
+ | 'this'
+ | typeName '.' 'this'
+ | '(' expression ')'
+ | classInstanceCreationExpression
+ | fieldAccess
+ | methodInvocation
+ | methodReference
+ ;
+
+primaryNoNewArray_lf_primary
+ : classInstanceCreationExpression_lf_primary
+ | fieldAccess_lf_primary
+ | arrayAccess_lf_primary
+ | methodInvocation_lf_primary
+ | methodReference_lf_primary
+ ;
+
+primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary
+ :
+ ;
+
+primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary
+ : classInstanceCreationExpression_lf_primary
+ | fieldAccess_lf_primary
+ | methodInvocation_lf_primary
+ | methodReference_lf_primary
+ ;
+
+primaryNoNewArray_lfno_primary
+ : literal
+ | typeName ('[' ']')* '.' 'class'
+ | unannPrimitiveType ('[' ']')* '.' 'class'
+ | 'void' '.' 'class'
+ | 'this'
+ | typeName '.' 'this'
+ | '(' expression ')'
+ | classInstanceCreationExpression_lfno_primary
+ | fieldAccess_lfno_primary
+ | arrayAccess_lfno_primary
+ | methodInvocation_lfno_primary
+ | methodReference_lfno_primary
+ ;
+
+primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary
+ :
+ ;
+
+primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary
+ : literal
+ | typeName ('[' ']')* '.' 'class'
+ | unannPrimitiveType ('[' ']')* '.' 'class'
+ | 'void' '.' 'class'
+ | 'this'
+ | typeName '.' 'this'
+ | '(' expression ')'
+ | classInstanceCreationExpression_lfno_primary
+ | fieldAccess_lfno_primary
+ | methodInvocation_lfno_primary
+ | methodReference_lfno_primary
+ ;
+
+classInstanceCreationExpression
+ : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ | primary '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ ;
+
+classInstanceCreationExpression_lf_primary
+ : '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ ;
+
+classInstanceCreationExpression_lfno_primary
+ : 'new' typeArguments? annotation* Identifier ('.' annotation* Identifier)* typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ | expressionName '.' 'new' typeArguments? annotation* Identifier typeArgumentsOrDiamond? '(' argumentList? ')' classBody?
+ ;
+
+typeArgumentsOrDiamond
+ : typeArguments
+ | '<' '>'
+ ;
+
+fieldAccess
+ : primary '.' Identifier
+ | 'super' '.' Identifier
+ | typeName '.' 'super' '.' Identifier
+ ;
+
+fieldAccess_lf_primary
+ : '.' Identifier
+ ;
+
+fieldAccess_lfno_primary
+ : 'super' '.' Identifier
+ | typeName '.' 'super' '.' Identifier
+ ;
+
+arrayAccess
+ : ( expressionName '[' expression ']'
+ | primaryNoNewArray_lfno_arrayAccess '[' expression ']'
+ )
+ ( primaryNoNewArray_lf_arrayAccess '[' expression ']'
+ )*
+ ;
+
+arrayAccess_lf_primary
+ : ( primaryNoNewArray_lf_primary_lfno_arrayAccess_lf_primary '[' expression ']'
+ )
+ ( primaryNoNewArray_lf_primary_lf_arrayAccess_lf_primary '[' expression ']'
+ )*
+ ;
+
+arrayAccess_lfno_primary
+ : ( expressionName '[' expression ']'
+ | primaryNoNewArray_lfno_primary_lfno_arrayAccess_lfno_primary '[' expression ']'
+ )
+ ( primaryNoNewArray_lfno_primary_lf_arrayAccess_lfno_primary '[' expression ']'
+ )*
+ ;
+
+methodInvocation
+ : methodName '(' argumentList? ')'
+ | typeName '.' typeArguments? Identifier '(' argumentList? ')'
+ | expressionName '.' typeArguments? Identifier '(' argumentList? ')'
+ | primary '.' typeArguments? Identifier '(' argumentList? ')'
+ | 'super' '.' typeArguments? Identifier '(' argumentList? ')'
+ | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')'
+ ;
+
+methodInvocation_lf_primary
+ : '.' typeArguments? Identifier '(' argumentList? ')'
+ ;
+
+methodInvocation_lfno_primary
+ : methodName '(' argumentList? ')'
+ | typeName '.' typeArguments? Identifier '(' argumentList? ')'
+ | expressionName '.' typeArguments? Identifier '(' argumentList? ')'
+ | 'super' '.' typeArguments? Identifier '(' argumentList? ')'
+ | typeName '.' 'super' '.' typeArguments? Identifier '(' argumentList? ')'
+ ;
+
+argumentList
+ : expression (',' expression)*
+ ;
+
+methodReference
+ : expressionName '::' typeArguments? Identifier
+ | referenceType '::' typeArguments? Identifier
+ | primary '::' typeArguments? Identifier
+ | 'super' '::' typeArguments? Identifier
+ | typeName '.' 'super' '::' typeArguments? Identifier
+ | classType '::' typeArguments? 'new'
+ | arrayType '::' 'new'
+ ;
+
+methodReference_lf_primary
+ : '::' typeArguments? Identifier
+ ;
+
+methodReference_lfno_primary
+ : expressionName '::' typeArguments? Identifier
+ | referenceType '::' typeArguments? Identifier
+ | 'super' '::' typeArguments? Identifier
+ | typeName '.' 'super' '::' typeArguments? Identifier
+ | classType '::' typeArguments? 'new'
+ | arrayType '::' 'new'
+ ;
+
+arrayCreationExpression
+ : 'new' primitiveType dimExprs dims?
+ | 'new' classOrInterfaceType dimExprs dims?
+ | 'new' primitiveType dims arrayInitializer
+ | 'new' classOrInterfaceType dims arrayInitializer
+ ;
+
+dimExprs
+ : dimExpr dimExpr*
+ ;
+
+dimExpr
+ : annotation* '[' expression ']'
+ ;
+
+constantExpression
+ : expression
+ ;
+
+expression
+ : lambdaExpression
+ | assignmentExpression
+ ;
+
+lambdaExpression
+ : lambdaParameters '->' lambdaBody
+ ;
+
+lambdaParameters
+ : Identifier
+ | '(' formalParameterList? ')'
+ | '(' inferredFormalParameterList ')'
+ ;
+
+inferredFormalParameterList
+ : Identifier (',' Identifier)*
+ ;
+
+lambdaBody
+ : expression
+ | block
+ ;
+
+assignmentExpression
+ : conditionalExpression
+ | assignment
+ ;
+
+assignment
+ : leftHandSide assignmentOperator expression
+ ;
+
+leftHandSide
+ : expressionName
+ | fieldAccess
+ | arrayAccess
+ ;
+
+assignmentOperator
+ : '='
+ | '*='
+ | '/='
+ | '%='
+ | '+='
+ | '-='
+ | '<<='
+ | '>>='
+ | '>>>='
+ | '&='
+ | '^='
+ | '|='
+ ;
+
+conditionalExpression
+ : conditionalOrExpression
+ | conditionalOrExpression '?' expression ':' conditionalExpression
+ ;
+
+conditionalOrExpression
+ : conditionalAndExpression
+ | conditionalOrExpression '||' conditionalAndExpression
+ ;
+
+conditionalAndExpression
+ : inclusiveOrExpression
+ | conditionalAndExpression '&&' inclusiveOrExpression
+ ;
+
+inclusiveOrExpression
+ : exclusiveOrExpression
+ | inclusiveOrExpression '|' exclusiveOrExpression
+ ;
+
+exclusiveOrExpression
+ : andExpression
+ | exclusiveOrExpression '^' andExpression
+ ;
+
+andExpression
+ : equalityExpression
+ | andExpression '&' equalityExpression
+ ;
+
+equalityExpression
+ : relationalExpression
+ | equalityExpression '==' relationalExpression
+ | equalityExpression '!=' relationalExpression
+ ;
+
+relationalExpression
+ : shiftExpression
+ | relationalExpression '<' shiftExpression
+ | relationalExpression '>' shiftExpression
+ | relationalExpression '<=' shiftExpression
+ | relationalExpression '>=' shiftExpression
+ | relationalExpression 'instanceof' referenceType
+ ;
+
+shiftExpression
+ : additiveExpression
+ | shiftExpression '<' '<' additiveExpression
+ | shiftExpression '>' '>' additiveExpression
+ | shiftExpression '>' '>' '>' additiveExpression
+ ;
+
+additiveExpression
+ : multiplicativeExpression
+ | additiveExpression '+' multiplicativeExpression
+ | additiveExpression '-' multiplicativeExpression
+ ;
+
+multiplicativeExpression
+ : unaryExpression
+ | multiplicativeExpression '*' unaryExpression
+ | multiplicativeExpression '/' unaryExpression
+ | multiplicativeExpression '%' unaryExpression
+ ;
+
+unaryExpression
+ : preIncrementExpression
+ | preDecrementExpression
+ | '+' unaryExpression
+ | '-' unaryExpression
+ | unaryExpressionNotPlusMinus
+ ;
+
+preIncrementExpression
+ : '++' unaryExpression
+ ;
+
+preDecrementExpression
+ : '--' unaryExpression
+ ;
+
+unaryExpressionNotPlusMinus
+ : postfixExpression
+ | '~' unaryExpression
+ | '!' unaryExpression
+ | castExpression
+ ;
+
+postfixExpression
+ : ( primary
+ | expressionName
+ )
+ ( postIncrementExpression_lf_postfixExpression
+ | postDecrementExpression_lf_postfixExpression
+ )*
+ ;
+
+postIncrementExpression
+ : postfixExpression '++'
+ ;
+
+postIncrementExpression_lf_postfixExpression
+ : '++'
+ ;
+
+postDecrementExpression
+ : postfixExpression '--'
+ ;
+
+postDecrementExpression_lf_postfixExpression
+ : '--'
+ ;
+
+castExpression
+ : '(' primitiveType ')' unaryExpression
+ | '(' referenceType additionalBound* ')' unaryExpressionNotPlusMinus
+ | '(' referenceType additionalBound* ')' lambdaExpression
+ ;
+
+// LEXER
+
+// §3.9 Keywords
+
+ABSTRACT : 'abstract';
+ASSERT : 'assert';
+BOOLEAN : 'boolean';
+BREAK : 'break';
+BYTE : 'byte';
+CASE : 'case';
+CATCH : 'catch';
+CHAR : 'char';
+CLASS : 'class';
+CONST : 'const';
+CONTINUE : 'continue';
+DEFAULT : 'default';
+DO : 'do';
+DOUBLE : 'double';
+ELSE : 'else';
+ENUM : 'enum';
+EXTENDS : 'extends';
+FINAL : 'final';
+FINALLY : 'finally';
+FLOAT : 'float';
+FOR : 'for';
+IF : 'if';
+GOTO : 'goto';
+IMPLEMENTS : 'implements';
+IMPORT : 'import';
+INSTANCEOF : 'instanceof';
+INT : 'int';
+INTERFACE : 'interface';
+LONG : 'long';
+NATIVE : 'native';
+NEW : 'new';
+PACKAGE : 'package';
+PRIVATE : 'private';
+PROTECTED : 'protected';
+PUBLIC : 'public';
+RETURN : 'return';
+SHORT : 'short';
+STATIC : 'static';
+STRICTFP : 'strictfp';
+SUPER : 'super';
+SWITCH : 'switch';
+SYNCHRONIZED : 'synchronized';
+THIS : 'this';
+THROW : 'throw';
+THROWS : 'throws';
+TRANSIENT : 'transient';
+TRY : 'try';
+VOID : 'void';
+VOLATILE : 'volatile';
+WHILE : 'while';
+
+// §3.10.1 Integer Literals
+
+IntegerLiteral
+ : DecimalIntegerLiteral
+ | HexIntegerLiteral
+ | OctalIntegerLiteral
+ | BinaryIntegerLiteral
+ ;
+
+fragment
+DecimalIntegerLiteral
+ : DecimalNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+HexIntegerLiteral
+ : HexNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+OctalIntegerLiteral
+ : OctalNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+BinaryIntegerLiteral
+ : BinaryNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+IntegerTypeSuffix
+ : [lL]
+ ;
+
+fragment
+DecimalNumeral
+ : '0'
+ | NonZeroDigit (Digits? | Underscores Digits)
+ ;
+
+fragment
+Digits
+ : Digit (DigitsAndUnderscores? Digit)?
+ ;
+
+fragment
+Digit
+ : '0'
+ | NonZeroDigit
+ ;
+
+fragment
+NonZeroDigit
+ : [1-9]
+ ;
+
+fragment
+DigitsAndUnderscores
+ : DigitOrUnderscore+
+ ;
+
+fragment
+DigitOrUnderscore
+ : Digit
+ | '_'
+ ;
+
+fragment
+Underscores
+ : '_'+
+ ;
+
+fragment
+HexNumeral
+ : '0' [xX] HexDigits
+ ;
+
+fragment
+HexDigits
+ : HexDigit (HexDigitsAndUnderscores? HexDigit)?
+ ;
+
+fragment
+HexDigit
+ : [0-9a-fA-F]
+ ;
+
+fragment
+HexDigitsAndUnderscores
+ : HexDigitOrUnderscore+
+ ;
+
+fragment
+HexDigitOrUnderscore
+ : HexDigit
+ | '_'
+ ;
+
+fragment
+OctalNumeral
+ : '0' Underscores? OctalDigits
+ ;
+
+fragment
+OctalDigits
+ : OctalDigit (OctalDigitsAndUnderscores? OctalDigit)?
+ ;
+
+fragment
+OctalDigit
+ : [0-7]
+ ;
+
+fragment
+OctalDigitsAndUnderscores
+ : OctalDigitOrUnderscore+
+ ;
+
+fragment
+OctalDigitOrUnderscore
+ : OctalDigit
+ | '_'
+ ;
+
+fragment
+BinaryNumeral
+ : '0' [bB] BinaryDigits
+ ;
+
+fragment
+BinaryDigits
+ : BinaryDigit (BinaryDigitsAndUnderscores? BinaryDigit)?
+ ;
+
+fragment
+BinaryDigit
+ : [01]
+ ;
+
+fragment
+BinaryDigitsAndUnderscores
+ : BinaryDigitOrUnderscore+
+ ;
+
+fragment
+BinaryDigitOrUnderscore
+ : BinaryDigit
+ | '_'
+ ;
+
+// §3.10.2 Floating-Point Literals
+
+FloatingPointLiteral
+ : DecimalFloatingPointLiteral
+ | HexadecimalFloatingPointLiteral
+ ;
+
+fragment
+DecimalFloatingPointLiteral
+ : Digits '.' Digits? ExponentPart? FloatTypeSuffix?
+ | '.' Digits ExponentPart? FloatTypeSuffix?
+ | Digits ExponentPart FloatTypeSuffix?
+ | Digits FloatTypeSuffix
+ ;
+
+fragment
+ExponentPart
+ : ExponentIndicator SignedInteger
+ ;
+
+fragment
+ExponentIndicator
+ : [eE]
+ ;
+
+fragment
+SignedInteger
+ : Sign? Digits
+ ;
+
+fragment
+Sign
+ : [+-]
+ ;
+
+fragment
+FloatTypeSuffix
+ : [fFdD]
+ ;
+
+fragment
+HexadecimalFloatingPointLiteral
+ : HexSignificand BinaryExponent FloatTypeSuffix?
+ ;
+
+fragment
+HexSignificand
+ : HexNumeral '.'?
+ | '0' [xX] HexDigits? '.' HexDigits
+ ;
+
+fragment
+BinaryExponent
+ : BinaryExponentIndicator SignedInteger
+ ;
+
+fragment
+BinaryExponentIndicator
+ : [pP]
+ ;
+
+// §3.10.3 Boolean Literals
+
+BooleanLiteral
+ : 'true'
+ | 'false'
+ ;
+
+// §3.10.4 Character Literals
+
+CharacterLiteral
+ : '\'' SingleCharacter '\''
+ | '\'' EscapeSequence '\''
+ ;
+
+fragment
+SingleCharacter
+ : ~['\\\r\n]
+ ;
+
+// §3.10.5 String Literals
+
+StringLiteral
+ : '"' StringCharacters? '"'
+ ;
+
+fragment
+StringCharacters
+ : StringCharacter+
+ ;
+
+fragment
+StringCharacter
+ : ~["\\\r\n]
+ | EscapeSequence
+ ;
+
+// §3.10.6 Escape Sequences for Character and String Literals
+
+fragment
+EscapeSequence
+ : '\\' [btnfr"'\\]
+ | OctalEscape
+ | UnicodeEscape // This is not in the spec but prevents having to preprocess the input
+ ;
+
+fragment
+OctalEscape
+ : '\\' OctalDigit
+ | '\\' OctalDigit OctalDigit
+ | '\\' ZeroToThree OctalDigit OctalDigit
+ ;
+
+fragment
+ZeroToThree
+ : [0-3]
+ ;
+
+// This is not in the spec but prevents having to preprocess the input
+fragment
+UnicodeEscape
+ : '\\' 'u'+ HexDigit HexDigit HexDigit HexDigit
+ ;
+
+// §3.10.7 The Null Literal
+
+NullLiteral
+ : 'null'
+ ;
+
+// §3.11 Separators
+
+LPAREN : '(';
+RPAREN : ')';
+LBRACE : '{';
+RBRACE : '}';
+LBRACK : '[';
+RBRACK : ']';
+SEMI : ';';
+COMMA : ',';
+DOT : '.';
+
+// §3.12 Operators
+
+ASSIGN : '=';
+GT : '>';
+LT : '<';
+BANG : '!';
+TILDE : '~';
+QUESTION : '?';
+COLON : ':';
+EQUAL : '==';
+LE : '<=';
+GE : '>=';
+NOTEQUAL : '!=';
+AND : '&&';
+OR : '||';
+INC : '++';
+DEC : '--';
+ADD : '+';
+SUB : '-';
+MUL : '*';
+DIV : '/';
+BITAND : '&';
+BITOR : '|';
+CARET : '^';
+MOD : '%';
+ARROW : '->';
+COLONCOLON : '::';
+
+ADD_ASSIGN : '+=';
+SUB_ASSIGN : '-=';
+MUL_ASSIGN : '*=';
+DIV_ASSIGN : '/=';
+AND_ASSIGN : '&=';
+OR_ASSIGN : '|=';
+XOR_ASSIGN : '^=';
+MOD_ASSIGN : '%=';
+LSHIFT_ASSIGN : '<<=';
+RSHIFT_ASSIGN : '>>=';
+URSHIFT_ASSIGN : '>>>=';
+
+// §3.8 Identifiers (must appear after all keywords in the grammar)
+
+Identifier
+ : JavaLetter JavaLetterOrDigit*
+ ;
+
+fragment
+JavaLetter
+ : [a-zA-Z$_] // these are the "java letters" below 0x7F
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierStart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+fragment
+JavaLetterOrDigit
+ : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierPart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+//
+// Additional symbols not defined in the lexical specification
+//
+
+AT : '@';
+ELLIPSIS : '...';
+
+//
+// Whitespace and comments
+//
+
+WS : [ \t\r\n\u000C]+ -> skip
+ ;
+
+COMMENT
+ : '/*' .*? '*/' -> skip
+ ;
+
+LINE_COMMENT
+ : '//' ~[\r\n]* -> skip
+ ;
\ No newline at end of file
diff --git a/antlr/src/main/antlr4/com/baeldung/antlr/Log.g4 b/antlr/src/main/antlr4/com/baeldung/antlr/Log.g4
new file mode 100644
index 0000000000..3ecb966f50
--- /dev/null
+++ b/antlr/src/main/antlr4/com/baeldung/antlr/Log.g4
@@ -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';
\ No newline at end of file
diff --git a/antlr/src/main/java/com/baeldung/antlr/java/UppercaseMethodListener.java b/antlr/src/main/java/com/baeldung/antlr/java/UppercaseMethodListener.java
new file mode 100644
index 0000000000..5092359b72
--- /dev/null
+++ b/antlr/src/main/java/com/baeldung/antlr/java/UppercaseMethodListener.java
@@ -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 errors = new ArrayList();
+
+ @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 getErrors(){
+ return Collections.unmodifiableList(errors);
+ }
+}
diff --git a/antlr/src/main/java/com/baeldung/antlr/log/LogListener.java b/antlr/src/main/java/com/baeldung/antlr/log/LogListener.java
new file mode 100644
index 0000000000..1f6d91df95
--- /dev/null
+++ b/antlr/src/main/java/com/baeldung/antlr/log/LogListener.java
@@ -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 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 getEntries() {
+ return Collections.unmodifiableList(entries);
+ }
+}
diff --git a/antlr/src/main/java/com/baeldung/antlr/log/model/LogEntry.java b/antlr/src/main/java/com/baeldung/antlr/log/model/LogEntry.java
new file mode 100644
index 0000000000..2b406c4ae9
--- /dev/null
+++ b/antlr/src/main/java/com/baeldung/antlr/log/model/LogEntry.java
@@ -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;
+ }
+}
diff --git a/antlr/src/main/java/com/baeldung/antlr/log/model/LogLevel.java b/antlr/src/main/java/com/baeldung/antlr/log/model/LogLevel.java
new file mode 100644
index 0000000000..004d9c6e8c
--- /dev/null
+++ b/antlr/src/main/java/com/baeldung/antlr/log/model/LogLevel.java
@@ -0,0 +1,5 @@
+package com.baeldung.antlr.log.model;
+
+public enum LogLevel {
+ DEBUG, INFO, ERROR
+}
diff --git a/antlr/src/test/java/com/baeldung/antlr/JavaParserUnitTest.java b/antlr/src/test/java/com/baeldung/antlr/JavaParserUnitTest.java
new file mode 100644
index 0000000000..0d43e0f284
--- /dev/null
+++ b/antlr/src/test/java/com/baeldung/antlr/JavaParserUnitTest.java
@@ -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!"));
+ }
+}
diff --git a/antlr/src/test/java/com/baeldung/antlr/LogParserUnitTest.java b/antlr/src/test/java/com/baeldung/antlr/LogParserUnitTest.java
new file mode 100644
index 0000000000..d263c2bd19
--- /dev/null
+++ b/antlr/src/test/java/com/baeldung/antlr/LogParserUnitTest.java
@@ -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)));
+ }
+}
diff --git a/pom.xml b/pom.xml
index 1226dafdff..e1b85e27c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -266,8 +266,9 @@
twilio
spring-boot-ctx-fluent
java-ee-8-security-api
- spring-webflux-amqp
- maven-archetype
+ spring-webflux-amqp
+ antlr
+ maven-archetype