1+ package com.github.murzagalin.evaluator.ast
2+
3+ import com.github.murzagalin.evaluator.Token
4+
5+
6+ /* the parser uses these rules
7+
8+ * expression -> ternary_if
9+ * ternary_if -> logic_or ( "?" ternary_if ":" ternary_if )?
10+ * logic_or -> logic_and ( ( "or" | "||" ) logic_and )*
11+ * logic_and -> equality ( ( "and" | "&&" ) equality )*
12+ * equality -> comparison ( ( "!=" | "==" ) comparison )*
13+ * comparison -> term ( ( ">" | ">=" | "<" | "<=" ) term )*
14+ * term -> factor ( ( "-" | "+" ) factor )*
15+ * factor -> unary ( ( "/" | "*" | "%") unary )*
16+ * unary -> ( "!" | "-" | "+" ) unary | exponent
17+ * exponent -> identifier ( "^" unary )*
18+ - identifier -> function | variable | number | boolean
19+
20+ function -> name "(" ( arguments )* ")"
21+ arguments -> expression ( ',' expression )*
22+ * variable -> name
23+ * name -> CHAR ( CHAR | DIGIT )*
24+ * boolean -> "true" | "false" | "TRUE" | "FALSE"
25+ * number -> DIGIT ( DIGIT )*
26+ */
27+
28+ class Parser {
29+
30+ private val equalityTokens = setOf (Token .Operator .Equal , Token .Operator .NotEqual )
31+
32+ private val comparisonTokens = setOf (
33+ Token .Operator .GreaterThan ,
34+ Token .Operator .GreaterEqualThan ,
35+ Token .Operator .LessThan ,
36+ Token .Operator .LessEqualThan
37+ )
38+
39+ private val termTokens = setOf (Token .Operator .Plus , Token .Operator .Minus )
40+
41+ private val factorTokens = setOf (Token .Operator .Division , Token .Operator .Multiplication , Token .Operator .Modulo )
42+
43+ private val unaryTokens = setOf (Token .Operator .UnaryPlus , Token .Operator .UnaryMinus , Token .Operator .Not )
44+
45+ private var ix = 0
46+
47+ fun parse (tokens : List <Token >): Expression {
48+ ix = 0
49+ return expression(tokens)
50+ }
51+
52+ fun expression (tokens : List <Token >): Expression {
53+ return ternaryIf(tokens)
54+ }
55+
56+ private fun ternaryIf (tokens : List <Token >): Expression {
57+ val first = logicOr(tokens)
58+
59+ if (ix < tokens.size && tokens[ix] is Token .Operator .TernaryIf ) {
60+ ix++
61+ val second = ternaryIf(tokens)
62+ require(tokens[ix++ ] is Token .Operator .TernaryElse ) { " ':' expected in ternary-if-else expression" }
63+ val third = ternaryIf(tokens)
64+
65+ return Expression .Ternary (Token .Operator .TernaryIfElse , first, second, third)
66+ }
67+
68+ return first
69+ }
70+
71+ private fun logicOr (tokens : List <Token >): Expression {
72+ var left = logicAnd(tokens)
73+
74+ while (ix < tokens.size && tokens[ix] is Token .Operator .Or ) {
75+ ix++
76+ val right = logicAnd(tokens)
77+ left = Expression .Binary (Token .Operator .Or , left, right)
78+ }
79+
80+ return left
81+ }
82+
83+ private fun logicAnd (tokens : List <Token >): Expression {
84+ var left = equality(tokens)
85+
86+ while (ix < tokens.size && tokens[ix] is Token .Operator .And ) {
87+ ix++
88+ val right = equality(tokens)
89+ left = Expression .Binary (Token .Operator .And , left, right)
90+ }
91+
92+ return left
93+ }
94+
95+ private fun equality (tokens : List <Token >): Expression {
96+ var left = comparison(tokens)
97+
98+ while (ix < tokens.size && tokens[ix] in equalityTokens) {
99+ val operator = tokens[ix++ ]
100+ val right = comparison(tokens)
101+ left = Expression .Binary (operator as Token .Operator , left, right)
102+ }
103+
104+ return left
105+ }
106+
107+ private fun comparison (tokens : List <Token >): Expression {
108+ var left = term(tokens)
109+
110+ while (ix < tokens.size && tokens[ix] in comparisonTokens) {
111+ val operator = tokens[ix++ ]
112+ val right = term(tokens)
113+ left = Expression .Binary (operator as Token .Operator , left, right)
114+ }
115+
116+ return left
117+ }
118+
119+ private fun term (tokens : List <Token >): Expression {
120+ var left = factor(tokens)
121+
122+ while (ix < tokens.size && tokens[ix] in termTokens) {
123+ val operator = tokens[ix++ ]
124+ val right = factor(tokens)
125+ left = Expression .Binary (operator as Token .Operator , left, right)
126+ }
127+
128+ return left
129+ }
130+
131+ private fun factor (tokens : List <Token >): Expression {
132+ var left = unary(tokens)
133+
134+ while (ix < tokens.size && tokens[ix] in factorTokens) {
135+ val operator = tokens[ix++ ]
136+ val right = unary(tokens)
137+ left = Expression .Binary (operator as Token .Operator , left, right)
138+ }
139+
140+ return left
141+ }
142+
143+ private fun unary (tokens : List <Token >): Expression {
144+ return if (ix < tokens.size && tokens[ix] in unaryTokens) {
145+ val unaryToken = tokens[ix++ ]
146+
147+ Expression .Unary (unaryToken as Token .Operator , unary(tokens))
148+ } else {
149+ exponent(tokens)
150+ }
151+ }
152+
153+ private fun exponent (tokens : List <Token >): Expression {
154+ var identifier = identifier(tokens)
155+
156+ if (ix < tokens.size && tokens[ix] is Token .Operator .Power ) {
157+ ix++
158+ identifier = Expression .Binary (Token .Operator .Power , identifier, unary(tokens))
159+ }
160+
161+ return identifier
162+ }
163+
164+ private fun identifier (tokens : List <Token >): Expression {
165+ require(tokens.size > ix) { " Expression expected" }
166+
167+ return when (val token = tokens[ix++ ]) {
168+ is Token .Operand -> Expression .Terminal (token)
169+ is Token .Bracket .Left -> {
170+ val result = expression(tokens)
171+ require(tokens[ix++ ] is Token .Bracket .Right ) { " ')' expected after expression" }
172+ result
173+ }
174+ else -> throw IllegalArgumentException (" Expression expected" )
175+ }
176+ }
177+ }
0 commit comments