1 Syntax error?

Maybe you haven’t understood what’s going on after reading our question, so I invite you to take a closer look:


      
  1. val list: ArrayList<String> = ArrayList(a)

  2.                          ^

Copy the code

What is the error? The > after the generic parameter.

It doesn’t make sense. There seems to be nothing wrong with it. Let’s look at the error message:

Huh? Say > that place needs a >? What the hell. Well, I guess I can guess why. The second half of the > estimate of the generic parameter is identified as >= in conjunction with the = used for the assignment.

We opened the PsiViewer, placed the cursor in the error position, and, yes, it was identified as >= (GTEQ).

2 analyze Kotlin’s analytical process

Kotlin’s parser does not recognize the following >= as >= because there are generics in front of it. Instead, Kotlin’s parser recognizes each character as a TOKEN, and then uses the parser to parse the syntax based on these tokens.

To verify this, it’s not that hard. Let’s go to Kotlin’s source code and find the lexer-related source code:

In the file kotlin.flex:


      
  1. "> ="         { return KtTokens.GTEQ      ; }

Copy the code

Not surprised. In fact, when compiled, kotlin. flex generates _jetlexer. Java. The KotlinLexer class is the entry point to the lexer.

Note that FlexAdapter is actually a parent of KotlinLexer.

Debugging runs the compiler, and my favorite way is to compile a script:

The script contains only the error we reported at the beginning of the code, so what happens?

Looking at the call stack, where the parser is called is actually during the construction of the PsiElement. Let’s look at the doParseContents method and see what it does:

Once the PsiElement construction is complete, the lexical analysis is practically done, and the subsequent KotlinParser is the parsing. It looks exactly like what we guessed.

Obviously, the two symbols have been forced to combine into >= before parsing, and there is no reparsing operation later.

3 Look at other languages

For similar syntax, we can compare Swfit with Scala.

Let’s start with Scala. Its parser is supposed to be extremely powerful because it allows all kinds of characters as operators.

Well, after all, their generic parameter wisely chose [] instead of <>, OK, you win.

So let’s look at Swift, which is more convincing:


      
  1. let ints: Array<Int> = [1. 2. 4]

  2. ints.forEach{item in print(item)}

Copy the code

See? They can tell! The e odd thing is that if you run this code with JetBrains’ AppCode, it will return an error and, well, it might be a sad story.

4 Some thoughts

In fact, from the previous discussion, we can see why Kotlin does not use >> and <<, but instead uses infix expressions such as SHR and SHR.

Okay, that’s not a big deal. The code discussed in this article is a bit of a pain in the ass:


      
  1. val list: ArrayList<String> = ArrayList(a)

Copy the code

I said why don’t you get rid of the previous type, isn’t type derivation enough?


      
  1. val list = ArrayList<String> ()

Copy the code

Or you can put a space between the >=, and nothing will happen.

And when it comes to infix expressions for shifts, one of the big shots in our group finally couldn’t resist speaking up for Kotlin:

It’s not a bad way to use infix. Because displacement is something that nobody uses at all, it’s much easier conceptually to just switch to one.

Also, I think Scala uses [] for generics much better than <>. I’ve seen people say the latter feels anti-human or strange to write, and I agree. I don’t think it’s a big deal that the >= compiler isn’t parsed. Many languages have similar defects, but it’s never a problem.


Welcome to Kotlin on wechat