Contents
Notation
This section informally explains the grammar notation used below.
Symbols and naming
Terminal symbol names start with an uppercase letter, e.g. SimpleName
Nonterminal symbol names start with lowercase letter, e.g. kotlinFile
Each production starts with a colon (:)
Symbol definitions may have many productions and are terminated by a semicolon (;)
Symbol definitions may be prepended with attributes, e.g. start attribute denotes a start symbol
EBNF expressions
Operator | denotes alternative
Operator * denotes iteration (zero or more)
Operator + denotes iteration (one or more)
Operator ? denotes option (zero or one)
alpha{beta} denotes a nonempty beta-separated list of alpha's
Semicolons
Kotlin provides "semicolon inference": syntactically, subsentences (e.g., statements, declarations etc) are separated by
the pseudo-token SEMI, which stands for "semicolon or newline". In most cases, there's no need for semicolons in
Kotlin code.
Syntax
Relevant pages: [Namespaces]
start
kotlinFile
: preamble toplevelObject*
;
start
script
: preamble expression*
;
[Used by script, kotlinFile]
preamble
: packageHeader? import*
;
[Used by preamble]
packageHeader
: modifiers "package" SimpleName{"."} SEMI?
;
[Used by preamble, package]
import
: "import" ("package" ".")? SimpleName{"."} ("." "*" | "as" SimpleName)? SEMI?
;
See [Imports]
[Used by package, kotlinFile]
toplevelObject
: package
: class
: object
: function
: property
: typedef
;
[Used by toplevelObject]
package
: "package" SimpleName{"."} "{"
import*
toplevelObject*
"}"
;
See [Namespaces]
undocumented
[Used by memberDeclaration, declaration, toplevelObject]
typedef
: modifiers "type" SimpleName (typeParameters typeConstraints)? "=" type
;
Classes
[Used by memberDeclaration, declaration, toplevelObject]
class
: modifiers ("class" | "trait") SimpleName
typeParameters?
modifiers ("(" functionParameter{","} ")")?
(":" annotations delegationSpecifier{","})?
typeConstraints
(classBody? | enumClassBody)
;
[Used by objectLiteral, enumEntry, class, object]
classBody
: ("{" memberDeclaration "}")?
;
[Used by objectLiteral, class, object]
delegationSpecifier
: constructorInvocation
: userType
: explicitDelegation
;
[Used by delegationSpecifier]
explicitDelegation
: userType "by" expression
;
[Used by class, property, typedef, function]
typeParameters
: "<" typeParameter{","} ">"
;
[Used by typeParameters]
typeParameter
: modifiers SimpleName (":" userType)?
;
See Generic classes
[Used by class, property, typedef, function]
typeConstraints
: ("where" typeConstraint{","})?
;
[Used by typeConstraints]
typeConstraint
: annotations SimpleName ":" type
: annotations "class" "object" SimpleName ":" type
;
Class members
[Used by classBody]
memberDeclaration
: classObject
: object
: function
: property
: class
: typedef
: anonymousInitializer
;
[Used by memberDeclaration]
anonymousInitializer
: block
;
[Used by memberDeclaration]
classObject
: modifiers "class" object
;
See Class objects
[Used by function]
valueParameters
: "(" functionParameter{","}? ")"
;
[Used by valueParameters, class]
functionParameter
: modifiers ("val" | "var")? parameter ("=" expression)?
;
[Used by enumEntry]
initializer
: annotations "this" valueArguments
: annotations constructorInvocation
;
[Used by catchBlock, anonymousInitializer, functionBody, try, finallyBlock]
block
: "{" statements "}"
;
[Used by memberDeclaration, declaration, toplevelObject]
function
: modifiers "fun" typeParameters?
(type "." | annotations)?
SimpleName
typeParameters? valueParameters (":" type)?
typeConstraints
functionBody?
;
[Used by getter, setter, function]
functionBody
: block
: "=" expression
;
[Used by for, property, multipleVariableDeclarations]
variableDeclarationEntry
: SimpleName (":" type)?
;
[Used by for, property]
multipleVariableDeclarations
: "(" variableDeclarationEntry{","} ")"
;
[Used by memberDeclaration, declaration, toplevelObject]
property
: modifiers ("val" | "var")
typeParameters? (type "." | annotations)?
(multipleVariableDeclarations | variableDeclarationEntry)
typeConstraints
("=" expression SEMI?)?
(getter? setter? | setter? getter?) SEMI?
;
[Used by property]
getter
: modifiers "get"
: modifiers "get" "(" ")" (":" type)? functionBody
;
[Used by property]
setter
: modifiers "set"
: modifiers "set" "(" modifiers (SimpleName | parameter) ")" functionBody
;
[Used by functionType, tupleType, setter, functionParameter]
parameter
: SimpleName ":" type
;
[Used by memberDeclaration, declaration, toplevelObject, classObject]
object
: "object" SimpleName (":" delegationSpecifier{","})? classBody?
Enum classes
See Enum classes
[Used by class]
enumClassBody
: "{" enumEntry* "}"
;
[Used by enumClassBody]
enumEntry
: modifiers SimpleName (":" initializer{","})? classBody?
;
Types
See [Types]
[Used by isRHS, simpleUserType, getter, tupleType, atomicExpression, property, typeArguments, typedef, functionLiteral, function, parameter, functionType, variableDeclarationEntry, typeConstraint]
type
: annotations typeDescriptor
[Used by nullableType, typeDescriptor, type]
typeDescriptor
: "(" typeDescriptor ")"
: selfType
: functionType
: userType
: tupleType
: nullableType
;
[Used by typeDescriptor]
nullableType
: typeDescriptor "?"
[Used by typeDescriptor]
selfType
: "This"
;
[Used by typeParameter, catchBlock, typeDescriptor, delegationSpecifier, constructorInvocation, explicitDelegation]
userType
: ("namespace" ".")? simpleUserType{"."}
;
[Used by userType]
simpleUserType
: SimpleName ("<" (optionalProjection type | "*"){","} ">")?
;
[Used by simpleUserType]
optionalProjection
: varianceAnnotation
;
[Used by typeDescriptor]
functionType
: (type ".")? "(" (parameter | modifiers type){","} ")" "->" type?
;
[Used by typeDescriptor]
tupleType
: "#" "(" type{","}? ")"
: "#" "(" parameter{","} ")"
;
Control structures
[Used by atomicExpression]
if
: "if" "(" expression ")" expression SEMI? ("else" expression)?
;
[Used by atomicExpression]
try
: "try" block catchBlock* finallyBlock?
;
[Used by try]
catchBlock
: "catch" "(" annotations SimpleName ":" userType ")" block
;
[Used by try]
finallyBlock
: "finally" block
;
[Used by atomicExpression]
loop
: for
: while
: doWhile
;
[Used by loop]
for
: "for" "(" annotations ("val" | "var")? (multipleVariableDeclarations | variableDeclarationEntry) "in" expression ")" expression
;
[Used by loop]
while
: "while" "(" expression ")" expression
;
[Used by loop]
doWhile
: "do" expression "while" "(" expression ")"
;
Expressions
See Expressions
Precedence
| Precedence | Title | Symbols |
|---|---|---|
| Highest | Postfix | ++, --, ., ?., ? |
| Prefix | -, +, ++, --, !, @label, @, @@ | |
| Type RHS | :, as, as? | |
| Multiplicative | *, /, % | |
| Additive | +, - | |
| Range | .. | |
| Infix function | SimpleName | |
| Elvis | ?: | |
| Named checks | in, !in, is, !is | |
| Comparison | <, >, <=, >= | |
| Equality | ==, !== | |
| Conjunction | && | |
| Disjunction | || | |
| Lowest | Assignment | =, +=, -=, *=, /=, %= |
Rules
[Used by tupleLiteral, for, atomicExpression, longTemplate, whenCondition, functionBody, doWhile, property, script, explicitDelegation, jump, while, whenEntry, arrayAccess, statement, if, when, valueArguments, functionParameter]
expression
: disjunction (assignmentOperator disjunction)*
;
[Used by expression]
disjunction
: conjunction ("||" conjunction)*
;
[Used by disjunction]
conjunction
: equalityComparison ("&&" equalityComparison)*
;
[Used by conjunction]
equalityComparison
: comparison (equalityOperation comparison)*
;
[Used by equalityComparison]
comparison
: namedInfix (comparisonOperation namedInfix)*
;
[Used by comparison]
namedInfix
: elvisExpression (inOperation elvisExpression)*
: elvisExpression (isOperation isRHS)?
;
[Used by namedInfix]
elvisExpression
: infixFunctionCall ("?:" infixFunctionCall)*
;
[Used by elvisExpression]
infixFunctionCall
: rangeExpression (SimpleName rangeExpression)*
;
[Used by infixFunctionCall]
rangeExpression
: additiveExpression (".." additiveExpression)*
;
[Used by rangeExpression]
additiveExpression
: multiplicativeExpression (additiveOperation multiplicativeExpression)*
;
[Used by additiveExpression]
multiplicativeExpression
: typeRHS (multiplicativeOperation typeRHS)*
;
[Used by multiplicativeExpression]
typeRHS
: prefixUnaryExpression (typeOperation prefixUnaryExpression)*
;
[Used by typeRHS]
prefixUnaryExpression
: prefixUnaryOperation* postfixUnaryExpression
;
[Used by prefixUnaryExpression, postfixUnaryOperation]
postfixUnaryExpression
: atomicExpression postfixUnaryOperation*
;
[Used by postfixUnaryExpression]
atomicExpression
: "(" expression ")"
: literalConstant
: functionLiteral
: tupleLiteral
: "this" label?
: "super" ("<" type ">")? label?
: if
: when
: try
: objectLiteral
: jump
: loop
: SimpleName
: FieldName
: "namespace"
;
[Used by callSuffix, prefixUnaryOperation, atomicExpression, jump]
label
: "@"
: "@@"
: LabelName
;
[Used by atomicExpression]
literalConstant
: "true" | "false"
: stringTemplate
: NoEscapeString
: IntegerLiteral
: HexadecimalLiteral
: CharacterLiteral
: FloatLiteral
: "null"
;
[Used by literalConstant]
stringTemplate
: "\"" stringTemplateElement* "\""
;
[Used by stringTemplate]
stringTemplateElement
:
Undeclared! RegularStringPart
:
Undeclared! ShortTemplateEntrySTART (SimpleName | "this")
:
Undeclared! EscapeSequence
: longTemplate
;
[Used by stringTemplateElement]
longTemplate
: "${" expression "}"
;
[Used by namedInfix, whenCondition]
isRHS
: type
;
[Used by statement]
declaration
: function
: property
: class
: typedef
: object
;
[Used by statements]
statement
: declaration
: expression
;
[Used by multiplicativeExpression]
multiplicativeOperation
: "*" : "/" : "%"
;
[Used by additiveExpression]
additiveOperation
: "+" : "-"
;
[Used by namedInfix]
inOperation
: "in" : "!in"
;
[Used by typeRHS]
typeOperation
: "as" : "as?" : ":"
;
[Used by namedInfix]
isOperation
: "is" : "!is"
;
[Used by comparison]
comparisonOperation
: "<" : ">" : ">=" : "<="
;
[Used by equalityComparison]
equalityOperation
: "!=" : "=="
;
[Used by expression]
assignmentOperator
: "="
: "+=" : "-=" : "*=" : "/=" : "%="
;
[Used by prefixUnaryExpression]
prefixUnaryOperation
: "-" : "+"
: "++" : "--"
: "!"
: annotations
: label
;
[Used by postfixUnaryExpression]
postfixUnaryOperation
: "++" : "--" : "!!"
: callSuffix
: arrayAccess
: memberAccessOperation postfixUnaryExpression
;
[Used by constructorInvocation, postfixUnaryOperation]
callSuffix
: typeArguments? valueArguments (label? functionLiteral)
: typeArguments (label? functionLiteral)
;
[Used by postfixUnaryOperation]
memberAccessOperation
: "." : "?." : "?"
;
[Used by callSuffix, annotationEntry]
typeArguments
: "<" type{","} ">"
;
[Used by callSuffix, annotationEntry, initializer]
valueArguments
: "(" (SimpleName "=")? "*"? expression{","} ")"
;
[Used by atomicExpression]
jump
: "throw" expression
: "return" label? expression?
: "continue" label?
: "break" label?
;
[Used by atomicExpression]
tupleLiteral
: "#" "(" (((SimpleName "=")? expression){","})? ")"
;
[Used by callSuffix, atomicExpression]
functionLiteral
: "{" statements "}"
: "{" (modifiers SimpleName){","} "->" statements "}"
: "{" (type ".")? "(" (modifiers SimpleName (":" type)?){","} ")" (":" type)? "->" statements "}"
;
[Used by block, functionLiteral]
statements
: SEMI* statement{SEMI+} SEMI*
;
[Used by delegationSpecifier, initializer]
constructorInvocation
: userType callSuffix
;
[Used by postfixUnaryOperation]
arrayAccess
: "[" expression{","} "]"
;
[Used by atomicExpression]
objectLiteral
: "object" (":" delegationSpecifier{","})? classBody
;
Pattern matching
See Pattern matching
[Used by atomicExpression]
when
: "when" ("(" (modifiers "val" SimpleName "=")? expression ")")? "{"
whenEntry*
"}"
;
[Used by when]
whenEntry
: whenCondition{","} "=>" expression SEMI
: "else" "=>" expression SEMI
;
[Used by whenEntry]
whenCondition
: expression
: ("in" | "!in") expression
: ("is" | "!is") isRHS
;
Modifiers
[Used by typeParameter, getter, packageHeader, class, property, typedef, function, functionLiteral, functionType, when, setter, enumEntry, classObject, functionParameter]
modifiers
: modifier*
;
[Used by modifiers]
modifier
: classModifier
: accessModifier
: varianceAnnotation
: memberModifier
: parameterKind
: annotations
;
[Used by modifier]
classModifier
: "abstract"
: "final"
: "enum"
: "open"
: "attribute"
;
[Used by modifier]
memberModifier
: "override"
: "open"
: "final"
: "abstract"
;
[Used by modifier]
accessModifier
: "private"
: "protected"
: "public"
: "internal"
;
[Used by modifier, optionalProjection]
varianceAnnotation
: "in"
: "out"
;
[Used by modifier]
parameterKind
: "lazy"
: "out"
: "ref"
;
Annotations
[Used by modifier, catchBlock, prefixUnaryOperation, for, class, property, type, typeConstraint, function, initializer]
annotations
: annotation*
;
[Used by annotations]
annotation
: "[" annotationEntry+ "]"
: annotationEntry
;
[Used by annotation]
annotationEntry
: SimpleName{"."} typeArguments? valueArguments?
;
Lexical structure
helper
[Used by IntegerLiteral, HexDigit]
Digit
: ["0".."9"];
[Used by literalConstant]
IntegerLiteral
: Digit+?
[Used by literalConstant]
FloatLiteral
: <java double literal>;
helper
[Used by HexadecimalLiteral]
HexDigit
: Digit | ["A".."F", "a".."f"];
[Used by literalConstant]
HexadecimalLiteral
: "0x" HexDigit+;
[Used by literalConstant]
CharacterLiteral
: <character as in Java>;
See Basic types
StringWithTemplates
: <single-quoted string, $ can be escaped>;
[Used by literalConstant]
NoEscapeString
: <"""-quoted string>;
See String templates
[Used by whenEntry, if, statements, packageHeader, property, import]
SEMI
: <semicolon or newline>;
[Used by typeParameter, package, LabelName, packageHeader, object, function, parameter, FieldName, when, variableDeclarationEntry, setter, import, valueArguments, tupleLiteral, catchBlock, simpleUserType, atomicExpression, class, typedef, infixFunctionCall, functionLiteral, annotationEntry, enumEntry, stringTemplateElement, typeConstraint]
SimpleName
: <java identifier>
: "`" <java identifier> "`"
;
[Used by atomicExpression]
FieldName
: "$" SimpleName;
[Used by label]
LabelName
: "@" SimpleName;
See [Nonlocal returns and jumps]

19 Comments
comments.show.hideJul 25, 2011
B. K. Oxley (binkley)
annotationEntry
: SimpleName
typeArguments? valueArguments?
;
Do you have example annotations that are typed or take arguments? Apologies if I missed them in the rest of the wiki docs.
Jul 27, 2011
Andrey Breslav
Not yet. But this is coming soon.
Jul 26, 2011
Anonymous
Operator + denotes iteration (one or one)
Must be: one or more
Jul 27, 2011
Andrey Breslav
Thanks
Jul 28, 2011
Alexander Kiel
classBody should be ("{" SEMI* memberDeclaration{SEMI+}? SEMI* "}")? or maybe you could introduce a memberDeclarations production like statements.
Jul 29, 2011
Anonymous
Why optional semicolons, I know it's popular, but isn't it a bit “unscientific” with “some whitespace significance” (I have encountered some problems with automatic statement separation in Groovy) ? Wouldn't it be better to make up your mind and make it purely whitespace-driven (such as Python) or purely whitespace agnostic (such as C) ?
Jul 30, 2011
Andrey Breslav
Our motivation is basically that on the one hand, semicolons introduce unnecessary noise, and on the other hand, everybody likes to have their own convention about whitespace. The latter may be overrated, in fact. We'll think about it. Thank you.
Jul 30, 2011
Terence Parr
Hi. I'll add my vote for one way or the other. Optional stuff usually ends up causing trouble for beginners and/or tool builders ... I'll also point out that they are really good for error resynchronization during parsing, but you guys are experts at that given the quality of your recovery in intellij.
Jul 30, 2011
Alexander Kiel
typeRHS should be prefixUnaryExpression (typeOperation prefixUnaryExpression)*
postfixUnaryOperation should be memberAccessOperation postfixUnaryExpression
Aug 02, 2011
Andrey Breslav
Thanks
Aug 02, 2011
Alexander Kiel
If I look closer at the memberAccessOperation, I think it is more a binary operation and not an unary one. Am I right? So maybe it's not good to file it under postfixUnaryOperation.
Aug 03, 2011
Andrey Breslav
It's a matter of precedence: to put it somewhere else means to lower its precedence.
Aug 03, 2011
Alexander Kiel
According to the two examples taken from Object expressions and Declarations:
valadHoc=object{varx:Int=0vary:Int=0}valab=object:A(1),B("abc"){overridevaly=15}objectLiteral should be:
I think the same applies to object. It should be:
Aug 04, 2011
Andrey Breslav
Fixed. Thanks
Aug 04, 2011
Alexander Kiel
I think tupleLiteral should be:
to support the empty tuple (Unit).
Another point is that tuplePattern is defined as:
there is only one SimpleName possible where in tupleLiteral there is one SimpleName per expression. Maybe tuplePattern should be:
What is the SimpleName doing in tuples?
Aug 04, 2011
Andrey Breslav
Fixed. Thanks
Aug 04, 2011
Andrey Breslav
On the simple names: they are labels, so that you can say something like
valt=(a=5,b=6)print(t.a)The grammar for patterns is broken, you are right. I'll fix it.
Oct 08, 2011
Sergey Ignatov
Possible this is a mistake in the Precedence table:
Because in the grammar I see equalityOperation : "!=" : "==" : "===" : "!=="
Oct 09, 2011
Andrey Breslav
We should have removed === and !=== from the grammar.