aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarvin Borner2019-08-17 17:53:59 +0200
committerMarvin Borner2019-08-17 17:53:59 +0200
commit75f8c215364a38ac0fc78510d1b11daa9d4f2318 (patch)
tree18c2e018b4cb210d8651a7f36b33e814c8227729
parent21a6062aa909c3bb3347f837206fdd3d2fd01af2 (diff)
Improved lexical analysis
-rw-r--r--src/runMain/kotlin/Lexical.kt18
-rw-r--r--src/runMain/kotlin/Syntax.kt67
-rw-r--r--src/runMain/kotlin/TokenType.kt4
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