diff options
author | Marvin Borner | 2019-08-17 17:53:59 +0200 |
---|---|---|
committer | Marvin Borner | 2019-08-17 17:53:59 +0200 |
commit | 75f8c215364a38ac0fc78510d1b11daa9d4f2318 (patch) | |
tree | 18c2e018b4cb210d8651a7f36b33e814c8227729 | |
parent | 21a6062aa909c3bb3347f837206fdd3d2fd01af2 (diff) |
Improved lexical analysis
-rw-r--r-- | src/runMain/kotlin/Lexical.kt | 18 | ||||
-rw-r--r-- | src/runMain/kotlin/Syntax.kt | 67 | ||||
-rw-r--r-- | src/runMain/kotlin/TokenType.kt | 4 |
3 files changed, 61 insertions, 28 deletions
diff --git a/src/runMain/kotlin/Lexical.kt b/src/runMain/kotlin/Lexical.kt index 4452235..4f6c419 100644 --- a/src/runMain/kotlin/Lexical.kt +++ b/src/runMain/kotlin/Lexical.kt @@ -19,14 +19,15 @@ class Lexical { buffer += source[i] val tokenType = getTokenType(buffer, if (source.length > i + 1) source[i + 1] else ' ') - if (tokenType != Skip && !statementEnd) { + if (tokenType != Skip) { val newToken = Token() newToken.content = buffer newToken.type = tokenType newToken.lineNumber = lineNumber currentStatement.add(newToken) buffer = "" - } else if (statementEnd) { + } + if (statementEnd) { statements.add(currentStatement.toMutableList()) currentStatement.clear() buffer = "" @@ -67,7 +68,10 @@ class Lexical { token in punctuation -> Punctuation - token in brackets -> Bracket + token in endOfStatement -> StatementEnd + + token in openedBrackets -> OpenedBracket + token in closedBrackets -> ClosedBracket token in classifier -> Classifier @@ -80,8 +84,10 @@ class Lexical { private val arithmetic = listOf("+", "-", "*", "/", "%") private val comparison = listOf("==", "!=", "<", "<=", ">", ">=") private val logical = listOf("&&", "||", "!") - private val punctuation = listOf(",", ":", ".", ";") - private val brackets = listOf("(", ")", "[", "]", "{", "}") // TODO: Use brackets for functions + private val punctuation = listOf(",", ":", ".") + private val endOfStatement = listOf(";") + private val openedBrackets = listOf("(", "[", "{") + private val closedBrackets = listOf(")", "]", "}") private val classifier = listOf("\"", "'") - private val emptiness = listOf(" ", "\t", "\n") + private val emptiness = listOf(" ", "\r", "\t", "\n") } diff --git a/src/runMain/kotlin/Syntax.kt b/src/runMain/kotlin/Syntax.kt index 8ba809c..54a0ebe 100644 --- a/src/runMain/kotlin/Syntax.kt +++ b/src/runMain/kotlin/Syntax.kt @@ -10,26 +10,11 @@ class Syntax { removePadding(statement) mergeStrings(statement) mergeTokens(statement) + checkFirst(statement) statement.forEach { println("${it.content} ${it.type}") } statement.forEachIndexed { j, token -> - if (statement.count { it.content == "(" } != statement.count { it.content == ")" }) - throw SyntaxError("Bracket", "Brackets are not even", token.lineNumber) - - when (token.type) { - Keyword -> allowNext(statement, j, listOf(Bracket)) - Function -> allowNext(statement, j, listOf(Bracket)) - Constant -> allowNext(statement, j, listOf(Comparison, Arithmetic, Logical, Bracket)) - Assignment -> allowNext(statement, j, listOf(Constant, Function, Variable)) - Arithmetic -> allowNext(statement, j, listOf(Constant, Function, Variable)) - Comparison -> allowNext(statement, j, listOf(Constant, Function, Variable)) - Logical -> allowNext(statement, j, listOf(Constant, Function, Variable)) - Variable -> allowNext(statement, j, listOf(Assignment, Bracket, Arithmetic, Logical, Comparison)) - Punctuation -> allowNext(statement, j, listOf(Constant)) - Bracket -> allowNext(statement, j, listOf(Constant, Keyword, Logical, Assignment, Variable)) - Classifier -> Unit - Empty -> Unit - Skip -> throw UnknownType(token.content) - } + checkBrackets(statement, token) + checkNext(statement, token, j) } } return true @@ -77,19 +62,59 @@ class Syntax { } /** + * Specifies which token types are allowed at the beginning of a statement + */ + private fun checkFirst(statement: MutableList<Token>) { + val token = statement[0] + if (token.type !in listOf(Keyword, Function, Variable)) + throw SyntaxError(token.type.toString().toLowerCase(), token.content, token.lineNumber) + } + + /** + * Checks whether the count of brackets is equal + */ + private fun checkBrackets(statement: MutableList<Token>, token: Token) { + if (statement.count { it.type == OpenedBracket } != statement.count { it.type == ClosedBracket }) + throw SyntaxError("Bracket", "Brackets are not even", token.lineNumber) + } + + /** + * Specifies and checks the tokens which are allowed to follow after [token] + */ + private fun checkNext(statement: MutableList<Token>, token: Token, index: Int) { + when (token.type) { + Keyword -> allowNext(statement, index, listOf(OpenedBracket)) + Function -> allowNext(statement, index, listOf(OpenedBracket)) + Constant -> allowNext(statement, index, listOf(Comparison, Arithmetic, Logical, ClosedBracket, StatementEnd)) + Assignment -> allowNext(statement, index, listOf(Constant, Function, Variable)) + Arithmetic -> allowNext(statement, index, listOf(Constant, Function, Variable)) + Comparison -> allowNext(statement, index, listOf(Constant, Function, Variable)) + Logical -> allowNext(statement, index, listOf(Constant, Function, Variable)) + Variable -> allowNext(statement, index, listOf(Assignment, ClosedBracket, Arithmetic, Logical, Comparison)) + Punctuation -> allowNext(statement, index, listOf(Constant)) + OpenedBracket -> allowNext(statement, index, listOf(Constant, Variable, ClosedBracket)) + ClosedBracket -> allowNext(statement, index, listOf(Arithmetic, Comparison, Logical, OpenedBracket, StatementEnd)) + Classifier -> Unit + Empty -> Unit + StatementEnd -> Unit + Skip -> throw UnknownType(token.content) + } + } + + /** * Throws [SyntaxError] if the next token is not in [allowed] */ - private fun allowNext(statement: MutableList<Token>, index: kotlin.Int, allowed: List<TokenType>) { + private fun allowNext(statement: MutableList<Token>, index: Int, allowed: List<TokenType>) { if (statement.size > index + 1 && nextNonEmpty(statement, index).type !in allowed) { val token = nextNonEmpty(statement, index) - throw SyntaxError(token.type.toString(), token.content, token.lineNumber) + throw SyntaxError(token.type.toString().toLowerCase(), token.content, token.lineNumber) } } /** * Finds the next non empty token by [index] */ - private fun nextNonEmpty(statement: MutableList<Token>, index: kotlin.Int): Token { + private fun nextNonEmpty(statement: MutableList<Token>, index: Int): Token { var i = index + 1 while (statement[i].type == Empty) i++ return statement[i] diff --git a/src/runMain/kotlin/TokenType.kt b/src/runMain/kotlin/TokenType.kt index 53e0ab2..f784cbb 100644 --- a/src/runMain/kotlin/TokenType.kt +++ b/src/runMain/kotlin/TokenType.kt @@ -11,7 +11,9 @@ enum class TokenType { Variable, Constant, Punctuation, - Bracket, + StatementEnd, + OpenedBracket, + ClosedBracket, Classifier, Empty, Skip |