-
Notifications
You must be signed in to change notification settings - Fork 42
/
ArithmeticsEvaluator.kt
45 lines (37 loc) · 1.55 KB
/
ArithmeticsEvaluator.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.example
import com.github.h0tk3y.betterParse.combinators.*
import com.github.h0tk3y.betterParse.grammar.Grammar
import com.github.h0tk3y.betterParse.grammar.parseToEnd
import com.github.h0tk3y.betterParse.grammar.parser
import com.github.h0tk3y.betterParse.lexer.literalToken
import com.github.h0tk3y.betterParse.lexer.regexToken
import com.github.h0tk3y.betterParse.parser.Parser
import kotlin.math.pow
class ArithmeticsEvaluator : Grammar<Int>() {
val num by regexToken("-?\\d+")
val lpar by literalToken("(")
val rpar by literalToken(")")
val mul by literalToken("*")
val pow by literalToken("^")
val div by literalToken("/")
val minus by literalToken("-")
val plus by literalToken("+")
val ws by regexToken("\\s+", ignore = true)
val number by num use { text.toInt() }
val term: Parser<Int> by number or
(skip(minus) and parser(::term) map { -it }) or
(skip(lpar) and parser(::rootParser) and skip(rpar))
val powChain by leftAssociative(term, pow) { a, _, b -> a.toDouble().pow(b.toDouble()).toInt() }
val divMulChain by leftAssociative(powChain, div or mul use { type }) { a, op, b ->
if (op == div) a / b else a * b
}
val subSumChain by leftAssociative(divMulChain, plus or minus use { type }) { a, op, b ->
if (op == plus) a + b else a - b
}
override val rootParser: Parser<Int> by subSumChain
}
fun main(args: Array<String>) {
val expr = "1 + 2 * (3 - 1^1) - 2^2^2 * (1 + 1)"
val result = ArithmeticsEvaluator().parseToEnd(expr)
println(result)
}