Migrate loop parser to Kotlin

This commit is contained in:
2020-03-06 18:24:30 +01:00
parent 52dcaacb58
commit 984732bf26
14 changed files with 136 additions and 49 deletions

View File

@@ -2,5 +2,5 @@ import interpreter.Interpreter
fun main(args: Array<String>) {
val interpreter = Interpreter()
interpreter.run("if (true) { return 2; 2*2; { 3+3; 1*2**3.@c:14 == (2 > not false) } throw \"Hello, world\" } else { false }")
interpreter.run("{ [2, 3, 4] as (i, j, k) ^ { x y z } % i == 2 [1, xyz, [true, { 1 -> false, 2 -> { @c -> @d, @e -> false } }, [@c], 4, \"h\"]] 2 @c @d * 3.14 }")
}

View File

@@ -5,11 +5,7 @@ import dsl.ast.model.node.Node
data class ParserOutput private constructor(val result: ParsingResult, val node: Node) {
fun map(mapper: (Node) -> Node): ParserOutput {
if(result == ParsingResult.FAILED) {
throw RuntimeException("Mapping operation is not allowed for failed parsing output")
}
return ok(mapper(node))
return if(result == ParsingResult.OK) ok(mapper(node)) else fail()
}
companion object {

View File

@@ -0,0 +1,22 @@
package dsl.ast.model.node
class LoopNode(iterator: Node, parameters: Node, operator: Node, statement: Node, filter: Node): Node(4, operator.position) {
val iterator: Node
get() = children[0]
val parameters: Node
get() = children[1]
val statement: Node
get() = children[2]
val filter: Node
get() = children[3]
init {
children[0] = iterator
children[1] = parameters
children[2] = statement
children[3] = filter
}
}

View File

@@ -0,0 +1,5 @@
package dsl.ast.model.node
import dsl.token.model.entity.TokenPosition
class LoopParametersNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)

View File

@@ -11,7 +11,7 @@ class ConditionParser : Parser() {
val ifStatementParser = allOf(listOf(
terminal(TokenType.IF),
terminal(TokenType.OPEN_PAREN),
ExpressionParser(),
SubexpressionParser(),
terminal(TokenType.CLOSE_PAREN),
StatementParser()
)) {
@@ -21,7 +21,7 @@ class ConditionParser : Parser() {
val ifElseStatementParser = allOf(listOf(
terminal(TokenType.IF),
terminal(TokenType.OPEN_PAREN),
ExpressionParser(),
SubexpressionParser(),
terminal(TokenType.CLOSE_PAREN),
StatementParser(),
terminal(TokenType.ELSE),

View File

@@ -1,46 +1,13 @@
package dsl.ast.parser
import dsl.ast.model.entity.ParserOutput
import dsl.ast.model.node.LogicOperatorNode
import dsl.ast.model.node.RelationOperatorNode
import dsl.ast.model.node.SumOperatorNode
import dsl.token.model.entity.TokenList
import dsl.token.model.enumeration.TokenType
class ExpressionParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val expr1Parser = leftAssociativeOperator(
TermParser(),
listOf(TokenType.PLUS, TokenType.MINUS),
TermParser()
) {
lhs, operator, rhs -> SumOperatorNode(lhs, operator, rhs)
}
val expr2Parser = leftAssociativeOperator(
expr1Parser,
listOf(TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE),
expr1Parser
) {
lhs, operator, rhs -> RelationOperatorNode(lhs, operator, rhs)
}
val expr3Parser = leftAssociativeOperator(
expr2Parser,
listOf(TokenType.AND),
expr2Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
}
val expr4Parser = leftAssociativeOperator(
expr3Parser,
listOf(TokenType.OR),
expr3Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
}
return expr4Parser.parse(input)
return oneOf(listOf(
LoopParser(),
SubexpressionParser()
)).parse(input)
}
}

View File

@@ -3,6 +3,6 @@ package dsl.ast.parser
import dsl.ast.model.node.ListNode
import dsl.token.model.enumeration.TokenType
class ListParser : AbstractIterableParser(TokenType.OPEN_SQUARE, ExpressionParser(), TokenType.CLOSE_SQUARE, {
class ListParser : AbstractIterableParser(TokenType.OPEN_SQUARE, SubexpressionParser(), TokenType.CLOSE_SQUARE, {
list, tokenPosition -> ListNode(list, tokenPosition)
})

View File

@@ -0,0 +1,8 @@
package dsl.ast.parser
import dsl.ast.model.node.LoopParametersNode
import dsl.token.model.enumeration.TokenType
class LoopParametersParser : AbstractIterableParser(TokenType.OPEN_PAREN, IdentifierParser(), TokenType.CLOSE_PAREN, {
list, tokenPosition -> LoopParametersNode(list, tokenPosition)
})

View File

@@ -0,0 +1,34 @@
package dsl.ast.parser
import dsl.ast.model.entity.ParserOutput
import dsl.ast.model.node.LoopNode
import dsl.ast.model.node.LoopParametersNode
import dsl.token.model.entity.TokenList
import dsl.token.model.enumeration.TokenType
class LoopParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val loopParametersParser = allOf(listOf(
terminal(TokenType.AS),
oneOf(listOf(
mapNode(IdentifierParser()) { LoopParametersNode(listOf(it), it.position) },
LoopParametersParser()
))
)) { it[1] }
val loopFilterParser = allOf(listOf(
terminal(TokenType.PERCENT),
assert(SubexpressionParser(), "filter as bool expression")
)) { it[1] }
return allOf(listOf(
SubexpressionParser(),
optional(loopParametersParser),
terminal(TokenType.CARET),
StatementParser(),
optional(loopFilterParser)
)) {
LoopNode(it[0], it[1], it[2], it[3], it[4])
}.parse(input)
}
}

View File

@@ -15,7 +15,7 @@ class MapEntryParser : Parser() {
return allOf(listOf(
keyParser,
terminal(TokenType.ARROW),
assert(ExpressionParser(), "expression")
assert(SubexpressionParser(), "expression")
)) {
MapEntryNode(it[0], it[1], it[2])
}.parse(input)

View File

@@ -184,5 +184,14 @@ abstract class Parser {
}
}
}
fun mapNode(parser: Parser, mapper: (Node) -> Node) : Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return parser.parse(input).map(mapper)
}
}
}
}
}

View File

@@ -9,7 +9,7 @@ class ReturnParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
terminal(TokenType.RETURN),
optional(ExpressionParser())
optional(SubexpressionParser())
)) {
ReturnNode(it[1])
}.parse(input)

View File

@@ -0,0 +1,46 @@
package dsl.ast.parser
import dsl.ast.model.entity.ParserOutput
import dsl.ast.model.node.LogicOperatorNode
import dsl.ast.model.node.RelationOperatorNode
import dsl.ast.model.node.SumOperatorNode
import dsl.token.model.entity.TokenList
import dsl.token.model.enumeration.TokenType
class SubexpressionParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val expr1Parser = leftAssociativeOperator(
TermParser(),
listOf(TokenType.PLUS, TokenType.MINUS),
TermParser()
) {
lhs, operator, rhs -> SumOperatorNode(lhs, operator, rhs)
}
val expr2Parser = leftAssociativeOperator(
expr1Parser,
listOf(TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE),
expr1Parser
) {
lhs, operator, rhs -> RelationOperatorNode(lhs, operator, rhs)
}
val expr3Parser = leftAssociativeOperator(
expr2Parser,
listOf(TokenType.AND),
expr2Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
}
val expr4Parser = leftAssociativeOperator(
expr3Parser,
listOf(TokenType.OR),
expr3Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
}
return expr4Parser.parse(input)
}
}

View File

@@ -9,7 +9,7 @@ class ThrowParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
terminal(TokenType.THROW),
optional(ExpressionParser())
optional(SubexpressionParser())
)) {
ThrowNode(it[1])
}.parse(input)