test(lexer): add tokenizer tests
This commit is contained in:
1 parent
7735863cab
commit
6228dd1bf6
1 file changed
+86
@@ -0,0 +1,86 @@
|
||||
package lumen
|
||||
|
||||
import lumen.lexer.Lexer
|
||||
import lumen.lexer.TokenType
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFailsWith
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
class LexerTest {
|
||||
private fun types(source: String) = Lexer(source).scan().map { it.type }
|
||||
|
||||
@Test
|
||||
fun scansDeclaration() {
|
||||
assertEquals(
|
||||
listOf(TokenType.Let, TokenType.Identifier, TokenType.Assign, TokenType.IntLiteral, TokenType.Eof),
|
||||
types("let x = 42")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun distinguishesIntAndDouble() {
|
||||
val tokens = Lexer("3 3.14").scan()
|
||||
assertEquals(TokenType.IntLiteral, tokens[0].type)
|
||||
assertEquals(3L, tokens[0].intValue)
|
||||
assertEquals(TokenType.DoubleLiteral, tokens[1].type)
|
||||
assertEquals(3.14, tokens[1].doubleValue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decodesStringEscapes() {
|
||||
val token = Lexer("\"a\\nb\\t\\\"c\"").scan().first()
|
||||
assertEquals(TokenType.StringLiteral, token.type)
|
||||
assertEquals("a\nb\t\"c", token.stringValue)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun skipsLineAndBlockComments() {
|
||||
assertEquals(
|
||||
listOf(TokenType.IntLiteral, TokenType.Newline, TokenType.IntLiteral, TokenType.Eof),
|
||||
types("1 // trailing\n2")
|
||||
)
|
||||
assertEquals(
|
||||
listOf(TokenType.IntLiteral, TokenType.IntLiteral, TokenType.Eof),
|
||||
types("1 /* nested /* block */ still */ 2")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun emitsNewlineTokensButNotInsideGrouping() {
|
||||
assertEquals(
|
||||
listOf(TokenType.IntLiteral, TokenType.Newline, TokenType.IntLiteral, TokenType.Eof),
|
||||
types("1\n2")
|
||||
)
|
||||
assertEquals(
|
||||
listOf(TokenType.LeftParen, TokenType.IntLiteral, TokenType.RightParen, TokenType.Eof),
|
||||
types("(\n1\n)")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun scansOperators() {
|
||||
assertEquals(
|
||||
listOf(
|
||||
TokenType.EqualEqual, TokenType.BangEqual, TokenType.LessEqual, TokenType.GreaterEqual,
|
||||
TokenType.Less, TokenType.Greater, TokenType.Plus, TokenType.Minus,
|
||||
TokenType.Star, TokenType.Slash, TokenType.Percent, TokenType.Eof
|
||||
),
|
||||
types("== != <= >= < > + - * / %")
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun rejectsUnterminatedString() {
|
||||
assertFailsWith<LexError> { Lexer("\"open").scan() }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun recognizesKeywords() {
|
||||
val keywordTypes = types("fn if else while for in return and or not true false nil")
|
||||
assertTrue(keywordTypes.contains(TokenType.Fn))
|
||||
assertTrue(keywordTypes.contains(TokenType.While))
|
||||
assertTrue(keywordTypes.contains(TokenType.And))
|
||||
assertTrue(keywordTypes.contains(TokenType.Nil))
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user