Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/main/kotlin/parser/Expression.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,21 @@ data class IntExpression(
return "${indent(indent)}Int(${value.lexeme})"
}
}

// support arithmetic operation
data class BinaryExpression(
val left_operand: Expression,
val operator: Token,
val right_operand: Expression
) : Expression() {
override fun prettyPrint(indent: Int): String {
return buildString {
appendLine("${indent(indent)}BinaryExpression(operator=${operator.lexeme})")
appendLine("${indent(indent + 1)}left =")
append(left_operand.prettyPrint(indent + 2))
appendLine("${indent(indent + 1)}right =")
append(right_operand.prettyPrint(indent + 2))
append("${indent(indent)})")
}
}
}
59 changes: 49 additions & 10 deletions src/main/kotlin/parser/Parser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import lexer.TokenType
import org.example.Exceptions.SyntaxError

class Parser {
fun parseTokens(tokens: List<Token>): ASTNode {
val tokens = tokens.toMutableList()
fun parseTokens(incomingTokens: List<Token>): ASTNode {
val tokens = incomingTokens.toMutableList()
val ast = parseProgram(tokens)

val lastToken = tokens.removeFirst()
Expand Down Expand Up @@ -78,14 +78,53 @@ class Parser {
}

private fun parseExpression(tokens: MutableList<Token>): Expression {
val token = tokens.removeFirst()
if (token.type != TokenType.INT_LITERAL) {
throw SyntaxError(
line = token.line,
column = token.column,
message = "Expected token: ${TokenType.INT_LITERAL}, got ${token.type}"
)
return parseAddition(tokens)
}

private fun parseAddition(tokens: MutableList<Token>): Expression {
var left_operand = parseTerm(tokens)

while (check(TokenType.PLUS, tokens) || check(TokenType.MINUS, tokens)) {
var operator = tokens.removeFirst()
var right_operand = parseTerm(tokens)
left_operand = BinaryExpression(left_operand, operator, right_operand)
}
return left_operand
}

private fun parseTerm(tokens: MutableList<Token>): Expression {
var left_operand = parsePrimary(tokens)

while (check(TokenType.MULTIPLY, tokens) || check(TokenType.DIVIDE, tokens)) {
var operator = tokens.removeFirst()
var right_operand = parsePrimary(tokens)
left_operand = BinaryExpression(left_operand, operator, right_operand)
}
return left_operand
}

private fun parsePrimary(tokens: MutableList<Token>): Expression {
if (check(TokenType.INT_LITERAL, tokens)) {
return IntExpression(tokens.removeFirst())
}
return IntExpression(value = token)

if (check(TokenType.LEFT_PAREN, tokens)) {
expect(TokenType.LEFT_PAREN, tokens)
val expression = parseExpression(tokens)
expect(TokenType.RIGHT_PAREN, tokens)
return expression
}

val unexpectedToken = tokens.first()
throw SyntaxError(
line = unexpectedToken.line,
column = unexpectedToken.column,
message = "Unexpected token: ${unexpectedToken.type}"
)
}

private fun check(type: TokenType, tokens: MutableList<Token>): Boolean {
if (tokens.isEmpty()) return false
return tokens.first().type == type
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

import lexer.Lexer
import lexer.TokenType
package lexer
import org.junit.jupiter.api.Test
import kotlin.test.assertEquals

Expand Down
Loading