Created
March 18, 2021 23:33
-
-
Save NathanPB/b37a7a8e58af2eae97e5ba436aa3e322 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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