Skip to content

Instantly share code, notes, and snippets.

@NathanPB
Created March 18, 2021 23:33
Show Gist options
  • Save NathanPB/b37a7a8e58af2eae97e5ba436aa3e322 to your computer and use it in GitHub Desktop.
Save NathanPB/b37a7a8e58af2eae97e5ba436aa3e322 to your computer and use it in GitHub Desktop.
import java.util.*
fun main(args: Array<String>) {
val scanner = Scanner(System.`in`)
val operators = listOf('^', '*', '/', '+', '-', '>', '<', '=', '#', '.', '|')
val operands = "[a-zA-Z0-9]+".toRegex()
abstract class Expression
class OperandExpression(val left: Expression, val operator: Char, val right: Expression) : Expression() {
override fun toString() = "exp($left $operator $right)"
}
class ConstantExpression(val value: String) : Expression() {
override fun toString() = value
}
fun parseExpression(expression: String) : Expression {
return if (expression.matches(operands)) {
ConstantExpression(expression)
} else {
if (expression.startsWith('(') && expression.endsWith(')')) {
val startIndex = expression.indexOf('(')
val (_, endIndex) = expression
.substring(startIndex)
.toCharArray()
.asList()
.foldRightIndexed(1 to -1) { index, char, acc ->
val (depth) = acc
if (depth > 0) {
when (char) {
'(' -> depth+1 to index
')' -> depth-1 to index
else -> depth to index
}
} else acc
}
parseExpression(expression.substring(startIndex+1, startIndex+endIndex))
} else {
var depth = 0
val index = expression.mapIndexedNotNull { index, it ->
if (it == '(') depth++
if (it == ')') depth--
if (depth == 0) {
val operator = operators.firstOrNull(it::equals)
if (operator != null) {
return@mapIndexedNotNull index as Int?
}
}
return@mapIndexedNotNull null as Int?
}.maxByOrNull { operators.indexOf(expression[it]) } ?: error("Syntactical Error")
val left = expression.take(index)
val right = expression.substring(index + 1)
if (left.isBlank() || right.isBlank()) {
error("Syntactical Error")
}
OperandExpression(parseExpression(left), expression[index], parseExpression(right))
}
}
}
while (scanner.hasNext()) {
val expression = scanner.nextLine().replace(" ", "")
try {
if (!expression.all { it == '(' || it == ')' || it in operators || it.toString().matches(operands) }) {
error("Lexical Error")
}
println(parseExpression(expression))
} catch (e: IllegalStateException) {
println(e.message)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment