简体   繁体   中英

How kotlin compiler understands the end of statement if semicolon is optional in kotlin?

In java we use semicolon, on the basis on semicolon compiler understands an end of a statement.

Whereas Kotlin also uses JVM How the compiler understands this is the end of statement without semicolon in Kotlin ?

As stated here ,

In Kotlin, semicolons are optional, and therefore line breaks are significant.

this essentially means kotlinc can identify the end of a statment in same manner as javac does, only difference is the character that marks the end of statement, where javac looks for ; , kotlinc would look for a \\n (line break).

Please note that use of semicolon is required when declaring an enum class in kotlin.

for example following code will not compile if you omit the semicolon

enum class Fruit(val price: Double) {
    MANGO(100.0);

    fun printPrice(){
        print(price)
    }
} 

Supplementary Answer

Kotlin lexer parser is smart enough in token-zing the plain text code based on the line breaks through the TruncatedSemanticWhitespaceAwarePsiBuilder interface .

This line break recognition is done without having to insert (or replace them with semicolons). Check the discussion here

SemanticWhitespaceAwarePsiBuilderImpl is a an implementation to this interface which has newlineBeforeCurrentToken() method that gives some clue on how that works:

@Override
public boolean newlineBeforeCurrentToken() {
    if (!newlinesEnabled.peek()) return false;

    if (eof()) return true;

    // TODO: maybe, memoize this somehow?
    for (int i = 1; i <= getCurrentOffset(); i++) {
        IElementType previousToken = rawLookup(-i);

        if (previousToken == KtTokens.BLOCK_COMMENT
                || previousToken == KtTokens.DOC_COMMENT
                || previousToken == KtTokens.EOL_COMMENT
                || previousToken == SHEBANG_COMMENT) {
            continue;
        }

        if (previousToken != TokenType.WHITE_SPACE) {
            break;
        }

        int previousTokenStart = rawTokenTypeStart(-i);
        int previousTokenEnd = rawTokenTypeStart(-i + 1);

        assert previousTokenStart >= 0;
        assert previousTokenEnd < getOriginalText().length();

        for (int j = previousTokenStart; j < previousTokenEnd; j++) {
            if (getOriginalText().charAt(j) == '\n') {
                return true;
            }
        }
    }

    return false;
}

And this is called whenever a token needs to be checked:

private boolean tokenMatches(IElementType token, IElementType expectation) {
    if (token == expectation) return true;
    if (expectation == EOL_OR_SEMICOLON) {
        if (eof()) return true;
        if (token == SEMICOLON) return true;
        if (myBuilder.newlineBeforeCurrentToken()) return true;
    }
    return false;
}

So, newlineBeforeCurrentToken() parses character by character and compares it to a line break, and eventually returns true to indicate that it's a complete statement.

Semicolons add no human-valuable meaning to the code. Life's too short to bother with them. This is only one (admittedly minor) of many examples of non-essential complexity in Java that is removed by more modern JVM languages.

In Kotlin, Semicolons are optional, but line breaks are significant.

The Kotlin compiler usually recognizes the end of a statement even without an explicit ; - for example by a line break.

Imporatant If you want to note several statements in a single line, they are separated with ;. For Example :

    val a = 42 ; println(a)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM