Edit Page

Grammar

Description

Notation

The notation used on this page corresponds to the ANTLR 4 notation with a few exceptions for better readability:

  • omitted lexer rule actions and commands,
  • omitted lexical modes.

Short description:

  • operator | denotes alternative,
  • operator * denotes iteration (zero or more),
  • operator + denotes iteration (one or more),
  • operator ? denotes option (zero or one),
  • operator .. denotes range (from left to right),
  • operator ~ denotes negation.

Grammar source files

Kotlin grammar source files (in ANTLR format) are located in the Kotlin specification repository:

The grammar on this page corresponds to the grammar files above.

Symbols and naming

Terminal symbol names start with an uppercase letter, e.g. Identifier.
Non-terminal symbol names start with a lowercase letter, e.g. kotlinFile.

Symbol definitions may be documented with attributes:

  • start attribute denotes a symbol that represents the whole source file (see kotlinFile and script),
  • helper attribute denotes a lexer fragment rule (used only inside other terminal symbols).

Also for better readability some simplifications are made:

  • lexer rules consisting of one string literal element are inlined to the use site,
  • new line tokens are excluded (new lines are not allowed in some places, see source grammar files for details).

Scope

The grammar corresponds to the latest stable version of the Kotlin compiler excluding lexer and parser rules for experimental features that are disabled by default.

Syntax grammar

General

Relevant pages: Packages

start
kotlinFile
start
script
shebangLine
(used by kotlinFile, script)
  : ShebangLine
  ;
fileAnnotation
(used by kotlinFile, script)
  : ('@' | AT_PRE_WS) 'file' ':' (('[' unescapedAnnotation+ ']') | unescapedAnnotation)
  ;

See Packages

packageHeader
(used by kotlinFile, script)
  : ('package' identifier semi?)?
  ;

See Imports

importList
(used by kotlinFile, script)
  : importHeader*
  ;
importHeader
(used by importList)
  : 'import' identifier (('.' '*') | importAlias)? semi?
  ;
importAlias
(used by importHeader)
  : 'as' simpleIdentifier
  ;
topLevelObject
(used by kotlinFile)
  : declaration semis?
  ;
typeAlias
(used by declaration)
  : modifiers? 'typealias' simpleIdentifier typeParameters? '=' type
  ;
classDeclaration
(used by declaration)
  : modifiers? ('class' | ('fun'? 'interface'))
    simpleIdentifier typeParameters?
    primaryConstructor?
    (':' delegationSpecifiers)?
    typeConstraints?
    (classBody | enumClassBody)?
  ;
primaryConstructor
(used by classDeclaration)
  : (modifiers? 'constructor')? classParameters
  ;
classParameters
(used by primaryConstructor)
  : '(' (classParameter (',' classParameter)* ','?)? ')'
  ;
classParameter
(used by classParameters)
  : modifiers? ('val' | 'var')? simpleIdentifier ':' type ('=' expression)?
  ;
delegationSpecifier
  : constructorInvocation
  | explicitDelegation
  | userType
  | functionType
  | 'suspend' functionType
  ;
constructorInvocation
  : userType valueArguments
  ;
annotatedDelegationSpecifier
explicitDelegation
  : (userType | functionType) 'by' expression
  ;
  : '<' typeParameter (',' typeParameter)* ','? '>'
  ;
typeParameter
(used by typeParameters)
  : typeParameterModifiers? simpleIdentifier (':' type)?
  ;
  : 'where' typeConstraint (',' typeConstraint)*
  ;
typeConstraint
(used by typeConstraints)
  : annotation* simpleIdentifier ':' type
  ;

Class members

classMemberDeclarations
  : (classMemberDeclaration semis?)*
  ;
classMemberDeclaration
anonymousInitializer
  : 'init' block
  ;
companionObject
  : modifiers? 'companion' 'data'? 'object'
    simpleIdentifier?
    (':' delegationSpecifiers)? classBody?
  ;
functionValueParameters
  : '(' (functionValueParameter (',' functionValueParameter)* ','?)? ')'
  ;
functionValueParameter
  : parameterModifiers? parameter ('=' expression)?
  ;
functionDeclaration
(used by declaration)
  : modifiers? 'fun' typeParameters?
    (receiverType '.')?
    simpleIdentifier functionValueParameters
    (':' type)? typeConstraints?
    functionBody?
  ;
  : block
  | '=' expression
  ;
multiVariableDeclaration
  : '(' variableDeclaration (',' variableDeclaration)* ','? ')'
  ;
propertyDeclaration
(used by declaration)
  : modifiers? ('val' | 'var') typeParameters?
    (receiverType '.')?
    (multiVariableDeclaration | variableDeclaration)
    typeConstraints?
    (('=' expression) | propertyDelegate)? ';'?
    ((getter? (semi? setter)?) | (setter? (semi? getter)?))
  ;
propertyDelegate
  : 'by' expression
  ;
getter
  : modifiers? 'get' ('(' ')' (':' type)? functionBody)?
  ;
setter
  : modifiers? 'set' ('(' functionValueParameterWithOptionalType ','? ')' (':' type)? functionBody)?
  ;
parametersWithOptionalType
(used by anonymousFunction)
  : '('
    (functionValueParameterWithOptionalType (',' functionValueParameterWithOptionalType)* ','?)? ')'
  ;
functionValueParameterWithOptionalType
parameterWithOptionalType
  : simpleIdentifier (':' type)?
  ;
  : simpleIdentifier ':' type
  ;
objectDeclaration
(used by declaration)
  : modifiers? 'object' simpleIdentifier (':' delegationSpecifiers)? classBody?
  ;
secondaryConstructor
  : modifiers? 'constructor' functionValueParameters
    (':' constructorDelegationCall)? block?
  ;
constructorDelegationCall
  : ('this' | 'super') valueArguments
  ;

Enum classes

See Enum classes

enumClassBody
(used by classDeclaration)
  : '{' enumEntries? (';' classMemberDeclarations)? '}'
  ;
enumEntries
(used by enumClassBody)
  : enumEntry (',' enumEntry)* ','?
  ;
enumEntry
(used by enumEntries)

Types

See Types

typeReference
  : userType
  | 'dynamic'
  ;
nullableType
(used by type, receiverType)
  : (typeReference | parenthesizedType) quest+
  ;
quest
(used by nullableType)
  : '?'
  | QUEST_WS
  ;
simpleUserType
(used by userType)
typeProjection
(used by typeArguments)
  : typeProjectionModifiers? type
  | '*'
  ;
typeProjectionModifiers
(used by typeProjection)
  : typeProjectionModifier+
  ;
typeProjectionModifier
  : varianceModifier
  | annotation
  ;
functionType
  : (receiverType '.')? functionTypeParameters '->' type
  ;
functionTypeParameters
(used by functionType)
  : '(' (parameter | type)? (',' (parameter | type))* ','? ')'
  ;
parenthesizedType
  : '(' type ')'
  ;
parenthesizedUserType
  : '(' (userType | parenthesizedUserType) ')'
  ;
definitelyNonNullableType
(used by type)

Statements

statements
(used by block, lambdaLiteral)
  : (statement (semis statement)*)? semis?
  ;
statement
  : (label | annotation)* (declaration | assignment | loopStatement | expression)
  ;
  : simpleIdentifier ('@' | AT_POST_WS)
  ;
  : block
  | statement
  ;
loopStatement
(used by statement)
  : forStatement
  | whileStatement
  | doWhileStatement
  ;
forStatement
(used by loopStatement)
  : 'for'
    '(' annotation* (variableDeclaration | multiVariableDeclaration) 'in' expression ')'
    controlStructureBody?
  ;
whileStatement
(used by loopStatement)
  : 'while' '(' expression ')' (controlStructureBody | ';')
  ;
doWhileStatement
(used by loopStatement)
  : 'do' controlStructureBody? 'while' '(' expression ')'
  ;
  : 
  ;

Expressions

Precedence Title Symbols
Highest Postfix ++, --, ., ?., ?
  Prefix -, +, ++, --, !, label
  Type RHS :, as, as?
  Multiplicative *, /, %
  Additive +, -
  Range ..
  Infix function simpleIdentifier
  Elvis ?:
  Named checks in, !in, is, !is
  Comparison <, >, <=, >=
  Equality ==, !=, ===, !==
  Conjunction &&
  Disjunction ||
  Spread operator *
Lowest Assignment =, +=, -=, *=, /=, %=
disjunction
(used by expression)
  : conjunction ('||' conjunction)*
  ;
conjunction
(used by disjunction)
  : equality ('&&' equality)*
  ;
equality
(used by conjunction)
genericCallLikeComparison
(used by comparison)
  : infixOperation callSuffix*
  ;
infixOperation
elvisExpression
(used by infixOperation)
elvis
(used by elvisExpression)
  : '?' ':'
  ;
infixFunctionCall
(used by elvisExpression)
rangeExpression
(used by infixFunctionCall)
  : additiveExpression (('..' | '..<') additiveExpression)*
  ;
multiplicativeExpression
(used by additiveExpression)
asExpression
prefixUnaryExpression
unaryPrefix
  : annotation
  | label
  | prefixUnaryOperator
  ;
postfixUnarySuffix
parenthesizedDirectlyAssignableExpression
  : '(' directlyAssignableExpression ')'
  ;
parenthesizedAssignableExpression
  : '(' assignableExpression ')'
  ;
assignableSuffix
  : typeArguments
  | indexingSuffix
  | navigationSuffix
  ;
indexingSuffix
  : '[' expression (',' expression)* ','? ']'
  ;
annotatedLambda
(used by callSuffix)
  : annotation* label? lambdaLiteral
  ;
  : '<' typeProjection (',' typeProjection)* ','? '>'
  ;
  : '(' (valueArgument (',' valueArgument)* ','?)? ')'
  ;
valueArgument
(used by valueArguments)
  : annotation? (simpleIdentifier '=')? '*'? expression
  ;
parenthesizedExpression
  : '(' expression ')'
  ;
collectionLiteral
(used by primaryExpression)
  : '[' (expression (',' expression)* ','?)? ']'
  ;
literalConstant
(used by primaryExpression)
  : BooleanLiteral
  | IntegerLiteral
  | HexLiteral
  | BinLiteral
  | CharacterLiteral
  | RealLiteral
  | 'null'
  | LongLiteral
  | UnsignedLiteral
  ;
stringLiteral
(used by primaryExpression)
lineStringLiteral
(used by stringLiteral)
  : '"' (lineStringContent | lineStringExpression)* '"'
  ;
multiLineStringLiteral
(used by stringLiteral)
  : '"""' (multiLineStringContent | multiLineStringExpression | '"')*
    TRIPLE_QUOTE_CLOSE
  ;
lineStringContent
(used by lineStringLiteral)
  : LineStrText
  | LineStrEscapedChar
  | LineStrRef
  ;
lineStringExpression
(used by lineStringLiteral)
  : '${' expression '}'
  ;
multiLineStringContent
  : MultiLineStrText
  | '"'
  | MultiLineStrRef
  ;
multiLineStringExpression
  : '${' expression '}'
  ;
lambdaLiteral
  : '{' (lambdaParameters? '->')? statements '}'
  ;
lambdaParameters
(used by lambdaLiteral)
  : lambdaParameter (',' lambdaParameter)* ','?
  ;
lambdaParameter
(used by lambdaParameters)
  : variableDeclaration
  | multiVariableDeclaration (':' type)?
  ;
anonymousFunction
(used by functionLiteral)
  : 'suspend'? 'fun' (type '.')?
    parametersWithOptionalType (':' type)?
    typeConstraints? functionBody?
  ;
functionLiteral
(used by primaryExpression)
  : lambdaLiteral
  | anonymousFunction
  ;
objectLiteral
(used by primaryExpression)
  : 'data'? 'object' (':' delegationSpecifiers)? classBody?
  ;
thisExpression
(used by primaryExpression)
  : 'this'
  | THIS_AT
  ;
superExpression
(used by primaryExpression)
  : 'super' ('<' type '>')? ('@' simpleIdentifier)?
  | SUPER_AT
  ;
ifExpression
(used by primaryExpression)
  : 'if' '(' expression ')'
    (controlStructureBody | (controlStructureBody? ';'? 'else' (controlStructureBody | ';')) | ';')
  ;
whenSubject
(used by whenExpression)
  : '(' (annotation* 'val' variableDeclaration '=')? expression ')'
  ;
whenExpression
(used by primaryExpression)
  : 'when' whenSubject? '{' whenEntry* '}'
  ;
whenEntry
(used by whenExpression)
  : whenCondition (',' whenCondition)* ','? '->' controlStructureBody semi?
  | 'else' '->' controlStructureBody semi?
  ;
whenCondition
(used by whenEntry)
  : expression
  | rangeTest
  | typeTest
  ;
rangeTest
(used by whenCondition)
  : inOperator expression
  ;
typeTest
(used by whenCondition)
  : isOperator type
  ;
tryExpression
(used by primaryExpression)
  : 'try' block ((catchBlock+ finallyBlock?) | finallyBlock)
  ;
catchBlock
(used by tryExpression)
  : 'catch' '(' annotation* simpleIdentifier ':' type ','? ')' block
  ;
finallyBlock
(used by tryExpression)
  : 'finally' block
  ;
jumpExpression
(used by primaryExpression)
  : 'throw' expression
  | ('return' | RETURN_AT) expression?
  | 'continue'
  | CONTINUE_AT
  | 'break'
  | BREAK_AT
  ;
callableReference
(used by primaryExpression)
  : receiverType? '::' (simpleIdentifier | 'class')
  ;
assignmentAndOperator
(used by assignment)
  : '+='
  | '-='
  | '*='
  | '/='
  | '%='
  ;
equalityOperator
(used by equality)
  : '!='
  | '!=='
  | '=='
  | '==='
  ;
comparisonOperator
(used by comparison)
  : '<'
  | '>'
  | '<='
  | '>='
  ;
inOperator
  : 'in'
  | NOT_IN
  ;
isOperator
  : 'is'
  | NOT_IS
  ;
additiveOperator
(used by additiveExpression)
  : '+'
  | '-'
  ;
multiplicativeOperator
  : '*'
  | '/'
  | '%'
  ;
asOperator
(used by asExpression)
  : 'as'
  | 'as?'
  ;
prefixUnaryOperator
(used by unaryPrefix)
  : '++'
  | '--'
  | '-'
  | '+'
  | excl
  ;
postfixUnaryOperator
(used by postfixUnarySuffix)
  : '++'
  | '--'
  | '!' excl
  ;
  : '!'
  | EXCL_WS
  ;
memberAccessOperator
(used by navigationSuffix)
  : '.'
  | safeNav
  | '::'
  ;
safeNav
  : '?' '.'
  ;

Modifiers

typeModifiers
  : typeModifier+
  ;
typeModifier
(used by typeModifiers)
  : annotation
  | 'suspend'
  ;
classModifier
(used by modifier)
  : 'enum'
  | 'sealed'
  | 'annotation'
  | 'data'
  | 'inner'
  | 'value'
  ;
memberModifier
(used by modifier)
  : 'override'
  | 'lateinit'
  ;
visibilityModifier
(used by modifier)
  : 'public'
  | 'private'
  | 'internal'
  | 'protected'
  ;
varianceModifier
  : 'in'
  | 'out'
  ;
typeParameterModifiers
(used by typeParameter)
  : typeParameterModifier+
  ;
typeParameterModifier
  : reificationModifier
  | varianceModifier
  | annotation
  ;
functionModifier
(used by modifier)
  : 'tailrec'
  | 'operator'
  | 'infix'
  | 'inline'
  | 'external'
  | 'suspend'
  ;
propertyModifier
(used by modifier)
  : 'const'
  ;
inheritanceModifier
(used by modifier)
  : 'abstract'
  | 'final'
  | 'open'
  ;
parameterModifier
  : 'vararg'
  | 'noinline'
  | 'crossinline'
  ;
reificationModifier
  : 'reified'
  ;
platformModifier
(used by modifier)
  : 'expect'
  | 'actual'
  ;

Annotations

singleAnnotation
(used by annotation)
multiAnnotation
(used by annotation)
  : (annotationUseSiteTarget | '@' | AT_PRE_WS) '[' unescapedAnnotation+ ']'
  ;
annotationUseSiteTarget
  : ('@' | AT_PRE_WS)
    ('field' | 'property' | 'get' | 'set' | 'receiver' | 'param' | 'setparam' | 'delegate') ':'
  ;
unescapedAnnotation
  : constructorInvocation
  | userType
  ;

Identifiers

  : Identifier
  | 'abstract'
  | 'annotation'
  | 'by'
  | 'catch'
  | 'companion'
  | 'constructor'
  | 'crossinline'
  | 'data'
  | 'dynamic'
  | 'enum'
  | 'external'
  | 'final'
  | 'finally'
  | 'get'
  | 'import'
  | 'infix'
  | 'init'
  | 'inline'
  | 'inner'
  | 'internal'
  | 'lateinit'
  | 'noinline'
  | 'open'
  | 'operator'
  | 'out'
  | 'override'
  | 'private'
  | 'protected'
  | 'public'
  | 'reified'
  | 'sealed'
  | 'tailrec'
  | 'set'
  | 'vararg'
  | 'where'
  | 'field'
  | 'property'
  | 'receiver'
  | 'param'
  | 'setparam'
  | 'delegate'
  | 'file'
  | 'expect'
  | 'actual'
  | 'const'
  | 'suspend'
  | 'value'
  ;
identifier
  : simpleIdentifier ('.' simpleIdentifier)*
  ;

Lexical grammar

General

ShebangLine
(used by shebangLine)
  : '#!' ~[\r\n]*
  ;
DelimitedComment
  : ('/*' (DelimitedComment | .)*? '*/') 
  ;
LineComment
(used by Hidden)
  : ('//' ~[\r\n]*) 
  ;
WS
(used by Hidden)
  : [\u0020\u0009\u000C] 
  ;
helper
  : DelimitedComment
  | LineComment
  | WS
  ;

Separators and operations

RESERVED
  : '...'
  ;
EXCL_WS
(used by excl)
  : '!' Hidden
  ;
DOUBLE_ARROW
  : '=>'
  ;
DOUBLE_SEMICOLON
  : ';;'
  ;
HASH
  : '#'
  ;
AT_POST_WS
(used by label)
  : '@' Hidden
  ;
AT_BOTH_WS
  : Hidden '@' Hidden
  ;
QUEST_WS
(used by quest)
  : '?' Hidden
  ;
SINGLE_QUOTE
  : '\''
  ;

Keywords

RETURN_AT
(used by jumpExpression)
  : 'return@' Identifier
  ;
CONTINUE_AT
(used by jumpExpression)
  : 'continue@' Identifier
  ;
BREAK_AT
(used by jumpExpression)
  : 'break@' Identifier
  ;
THIS_AT
(used by thisExpression)
  : 'this@' Identifier
  ;
SUPER_AT
(used by superExpression)
  : 'super@' Identifier
  ;
TYPEOF
  : 'typeof'
  ;
NOT_IS
(used by isOperator)
  : '!is' Hidden
  ;
NOT_IN
(used by inOperator)
  : '!in' Hidden
  ;

Literals

helper
  : '0'..'9'
  ;
helper
DecDigitNoZero
(used by IntegerLiteral)
  : '1'..'9'
  ;
helper
DecDigitOrSeparator
  : DecDigit
  | '_'
  ;
helper
DecDigits
helper
DoubleExponent
(used by DoubleLiteral)
  : [eE] [+-]? DecDigits
  ;
RealLiteral
(used by literalConstant)
  : FloatLiteral
  | DoubleLiteral
  ;
FloatLiteral
(used by RealLiteral)
  : DoubleLiteral [fF]
  | DecDigits [fF]
  ;
DoubleLiteral
helper
  : [0-9a-fA-F]
  ;
helper
HexDigitOrSeparator
(used by HexLiteral)
  : HexDigit
  | '_'
  ;
  : '0' [xX] HexDigit HexDigitOrSeparator* HexDigit
  | '0' [xX] HexDigit
  ;
helper
BinDigit
  : [01]
  ;
helper
BinDigitOrSeparator
(used by BinLiteral)
  : BinDigit
  | '_'
  ;
  : '0' [bB] BinDigit BinDigitOrSeparator* BinDigit
  | '0' [bB] BinDigit
  ;
UnsignedLiteral
(used by literalConstant)
  : (IntegerLiteral | HexLiteral | BinLiteral) [uU] [lL]?
  ;
LongLiteral
(used by literalConstant)
  : (IntegerLiteral | HexLiteral | BinLiteral) [lL]
  ;
BooleanLiteral
(used by literalConstant)
  : 'true'
  | 'false'
  ;
CharacterLiteral
(used by literalConstant)
  : '\'' (EscapeSeq | ~[\n\r'\\]) '\''
  ;

Identifiers

helper
UnicodeDigit
(used by Identifier)
  : UNICODE_CLASS_ND
  ;
  : (Letter | '_') (Letter | '_' | UnicodeDigit)*
  | '`' ~([\r\n] | '`')+ '`'
  ;

Depending on the target and publicity of the declaration, the set of allowed symbols in identifiers is different. This rule contains the union of allowed symbols from all targets. Thus, the code for any target can be parsed using the grammar.

The allowed symbols in identifiers corresponding to the target and publicity of the declaration are given below.

Kotlin/JVM (any declaration publicity)
~ ( [\r\n] | '`' | '.' | ';' | ':' | '\' | '/' | '[' | ']' | '<' | '>' )
Kotlin/Android (any declaration publicity)

The allowed symbols are different from allowed symbols for Kotlin/JVM and correspond to the Dalvik Executable format.

Kotlin/JS (private declarations)
~ ( [\r\n] | '`' )
Kotlin/JS (public declarations)

The allowed symbols for public declarations correspond to the ECMA specification (section 7.6) except that ECMA reserved words is allowed.

Kotlin/Native (any declaration publicity)
~ ( [\r\n] | '`' )


IdentifierOrSoftKey
(used by FieldIdentifier)
  : Identifier
  | 'abstract'
  | 'annotation'
  | 'by'
  | 'catch'
  | 'companion'
  | 'constructor'
  | 'crossinline'
  | 'data'
  | 'dynamic'
  | 'enum'
  | 'external'
  | 'final'
  | 'finally'
  | 'import'
  | 'infix'
  | 'init'
  | 'inline'
  | 'inner'
  | 'internal'
  | 'lateinit'
  | 'noinline'
  | 'open'
  | 'operator'
  | 'out'
  | 'override'
  | 'private'
  | 'protected'
  | 'public'
  | 'reified'
  | 'sealed'
  | 'tailrec'
  | 'vararg'
  | 'where'
  | 'get'
  | 'set'
  | 'field'
  | 'property'
  | 'receiver'
  | 'param'
  | 'setparam'
  | 'delegate'
  | 'file'
  | 'expect'
  | 'actual'
  | 'value'
  | 'const'
  | 'suspend'
  ;
FieldIdentifier
  : '$' IdentifierOrSoftKey
  ;
helper
UniCharacterLiteral
  : '\\' 'u' HexDigit HexDigit HexDigit HexDigit
  ;
helper
EscapedIdentifier
  : '\\' ('t' | 'b' | 'r' | 'n' | '\'' | '"' | '\\' | '$')
  ;
helper
EscapeSeq
(used by CharacterLiteral)

Characters

helper
Letter
(used by Identifier)

Strings

LineStrRef
(used by lineStringContent)
  : FieldIdentifier
  ;
LineStrText
(used by lineStringContent)
  : ~('\\' | '"' | '$')+
  | '$'
  ;
LineStrEscapedChar
(used by lineStringContent)
TRIPLE_QUOTE_CLOSE
  : ('"'? '"""') 
  ;
MultiLineStrRef
  : FieldIdentifier
  ;
MultiLineStrText
  : ~('"' | '$')+
  | '$'
  ;
ErrorCharacter
  : .
  ;