Refactor parsers

This commit is contained in:
2020-03-06 22:18:15 +01:00
parent 81b5ccee50
commit df4b923356
30 changed files with 168 additions and 154 deletions

View File

@@ -13,29 +13,28 @@ abstract class AbstractIterableParser(
private val createNode: (List<Node>, TokenPosition) -> Node
) : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val emptyIterableParser = allOf(listOf(terminal(beginTokenType), terminal(endTokenType))) { createNode(listOf(), it[0].position) }
val emptyIterableParser = allOf(
terminal(beginTokenType),
terminal(endTokenType)
) { createNode(listOf(), it[0].position) }
val nonEmptyIterableParser = allOf(
listOf(terminal(beginTokenType),
allOf(listOf(
itemParser,
optional(repeat(allOf(
listOf(
terminal(TokenType.COMMA),
itemParser
)
) { it[1] }) { list, position -> object : Node(list, position) {} }
))) { list ->
object : Node(listOf(list[0]) + list[1].children, TokenPosition.NONE) {} },
terminal(endTokenType)
)
terminal(beginTokenType),
allOf(
itemParser,
optional(repeat(allOf(
terminal(TokenType.COMMA),
itemParser
) { it[1] }) { list, position -> object : Node(list, position) {} }
)) { list ->
object : Node(listOf(list[0]) + list[1].children, TokenPosition.NONE) {}
},
terminal(endTokenType)
) { createNode(it[1].children.toList(), it[0].position) }
return oneOf(
listOf(
emptyIterableParser,
nonEmptyIterableParser
)
emptyIterableParser,
nonEmptyIterableParser
).parse(input)
}

View File

@@ -7,11 +7,11 @@ import dsl.token.model.enumeration.TokenType
class AssignmentOperatorParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
SimpleIdentifierParser(),
terminal(TokenType.ASSIGN),
assert(ExpressionParser(), "expression")
)) {
) {
AssignmentOperatorNode(it[0], it[1], it[2])
}.parse(input)
}

View File

@@ -7,23 +7,19 @@ import dsl.token.model.enumeration.TokenType
class AtomParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val parenthesesParser = allOf(
listOf(
terminal(TokenType.OPEN_PAREN),
ExpressionParser(),
terminal(TokenType.CLOSE_PAREN)
)
terminal(TokenType.OPEN_PAREN),
ExpressionParser(),
terminal(TokenType.CLOSE_PAREN)
) {
it[1]
}
val literalParser = oneOf(
listOf(
parenthesesParser,
ComplexIdentifierParser(),
ListParser(),
LiteralParser(),
MapParser()
)
parenthesesParser,
ComplexIdentifierParser(),
ListParser(),
LiteralParser(),
MapParser()
)
return literalParser.parse(input)

View File

@@ -5,10 +5,10 @@ import dsl.token.model.entity.TokenList
class ComplexIdentifierParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return oneOf(listOf(
return oneOf(
AssignmentOperatorParser(),
FunctionCallParser(),
SimpleIdentifierParser()
)).parse(input)
).parse(input)
}
}

View File

@@ -8,17 +8,17 @@ import dsl.token.model.enumeration.TokenType
class ConditionParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val ifStatementParser = allOf(listOf(
val ifStatementParser = allOf(
terminal(TokenType.IF),
terminal(TokenType.OPEN_PAREN),
SubexpressionParser(),
terminal(TokenType.CLOSE_PAREN),
StatementParser()
)) {
) {
ConditionNode(it[0], it[2], it[4], Node.NONE, Node.NONE)
}
val ifElseStatementParser = allOf(listOf(
val ifElseStatementParser = allOf(
terminal(TokenType.IF),
terminal(TokenType.OPEN_PAREN),
SubexpressionParser(),
@@ -26,13 +26,13 @@ class ConditionParser : Parser() {
StatementParser(),
terminal(TokenType.ELSE),
StatementParser()
)) {
) {
ConditionNode(it[0], it[2], it[4], it[5], it[6])
}
return oneOf(listOf(
return oneOf(
ifElseStatementParser,
ifStatementParser
)).parse(input)
).parse(input)
}
}

View File

@@ -5,9 +5,9 @@ import dsl.token.model.entity.TokenList
class ExpressionParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return oneOf(listOf(
return oneOf(
LoopParser(),
SubexpressionParser()
)).parse(input)
).parse(input)
}
}

View File

@@ -16,16 +16,16 @@ class FactorParser : Parser() {
PowerOperatorNode(lhs, operator, rhs)
}
val notOperatorParser = allOf(listOf(
val notOperatorParser = allOf(
terminal(TokenType.NOT),
factorParser
)) {
) {
NotOperatorNode(it[0], it[1])
}
return oneOf(listOf(
return oneOf(
notOperatorParser,
factorParser
)).parse(input)
).parse(input)
}
}

View File

@@ -3,6 +3,7 @@ package dsl.ast.parser
import dsl.ast.model.node.FunctionCallArgumentsNode
import dsl.token.model.enumeration.TokenType
class FunctionCallArgumentsParser : AbstractIterableParser(TokenType.OPEN_PAREN, ExpressionParser(), TokenType.CLOSE_PAREN, {
list, tokenPosition -> FunctionCallArgumentsNode(list, tokenPosition)
})
class FunctionCallArgumentsParser :
AbstractIterableParser(TokenType.OPEN_PAREN, ExpressionParser(), TokenType.CLOSE_PAREN, { list, tokenPosition ->
FunctionCallArgumentsNode(list, tokenPosition)
})

View File

@@ -6,10 +6,10 @@ import dsl.token.model.entity.TokenList
class FunctionCallParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
SimpleIdentifierParser(),
FunctionCallArgumentsParser()
)) {
) {
FunctionCallNode(it[0], it[1])
}.parse(input)
}

View File

@@ -5,9 +5,9 @@ import dsl.token.model.entity.TokenList
class FunctionDefinitionArgumentParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return oneOf(listOf(
return oneOf(
OptionalFunctionDefinitionArgumentParser(),
RegularFunctionDefinitionArgumentParser()
)).parse(input)
).parse(input)
}
}

View File

@@ -3,6 +3,10 @@ package dsl.ast.parser
import dsl.ast.model.node.FunctionDefinitionArgumentsNode
import dsl.token.model.enumeration.TokenType
class FunctionDefinitionArgumentsParser : AbstractIterableParser(TokenType.OPEN_PAREN, FunctionDefinitionArgumentParser(), TokenType.CLOSE_PAREN, {
list, tokenPosition -> FunctionDefinitionArgumentsNode(list, tokenPosition)
})
class FunctionDefinitionArgumentsParser : AbstractIterableParser(
TokenType.OPEN_PAREN,
FunctionDefinitionArgumentParser(),
TokenType.CLOSE_PAREN,
{ list, tokenPosition ->
FunctionDefinitionArgumentsNode(list, tokenPosition)
})

View File

@@ -7,12 +7,12 @@ import dsl.token.model.enumeration.TokenType
class FunctionDefinitionParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
terminal(TokenType.FUNCTION),
assert(SimpleIdentifierParser(), "function/method name"),
assert(FunctionDefinitionArgumentsParser(), "function/method arguments list"),
assert(BlockParser(), "function/method body")
)) {
) {
FunctionDefinitionNode(it[1], it[2], it[3], it[0].position)
}.parse(input)
}

View File

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

View File

@@ -5,12 +5,12 @@ import dsl.token.model.entity.TokenList
class LiteralParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return oneOf(listOf(
return oneOf(
BoolLiteralParser(),
FloatLiteralParser(),
IntegerLiteralParser(),
NoteLiteralParser(),
StringLiteralParser()
)).parse(input)
).parse(input)
}
}

View File

@@ -3,6 +3,10 @@ package dsl.ast.parser
import dsl.ast.model.node.LoopParametersNode
import dsl.token.model.enumeration.TokenType
class LoopParametersParser : AbstractIterableParser(TokenType.OPEN_PAREN, SimpleIdentifierParser(), TokenType.CLOSE_PAREN, {
list, tokenPosition -> LoopParametersNode(list, tokenPosition)
})
class LoopParametersParser : AbstractIterableParser(
TokenType.OPEN_PAREN,
SimpleIdentifierParser(),
TokenType.CLOSE_PAREN,
{ list, tokenPosition ->
LoopParametersNode(list, tokenPosition)
})

View File

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

View File

@@ -7,16 +7,16 @@ import dsl.token.model.enumeration.TokenType
class MapEntryParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val keyParser = oneOf(listOf(
val keyParser = oneOf(
LiteralParser(),
SimpleIdentifierParser()
))
)
return allOf(listOf(
return allOf(
keyParser,
terminal(TokenType.ARROW),
assert(SubexpressionParser(), "expression")
)) {
) {
MapEntryNode(it[0], it[1], it[2])
}.parse(input)
}

View File

@@ -3,6 +3,7 @@ package dsl.ast.parser
import dsl.ast.model.node.MapNode
import dsl.token.model.enumeration.TokenType
class MapParser : AbstractIterableParser(TokenType.OPEN_CURLY, MapEntryParser(), TokenType.CLOSE_CURLY, {
list, tokenPosition -> MapNode(list, tokenPosition)
})
class MapParser :
AbstractIterableParser(TokenType.OPEN_CURLY, MapEntryParser(), TokenType.CLOSE_CURLY, { list, tokenPosition ->
MapNode(list, tokenPosition)
})

View File

@@ -7,15 +7,15 @@ import dsl.token.model.enumeration.TokenType
class OptionalFunctionDefinitionArgumentParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
SimpleIdentifierParser(),
optional(allOf(listOf(
optional(allOf(
terminal(TokenType.COLON),
TypeParser()
)){ it[1] }),
) { it[1] }),
terminal(TokenType.ASSIGN),
assert(ExpressionParser(), "expression")
)) {
) {
OptionalFunctionDefinitionArgumentNode(it[0], it[1], it[3])
}.parse(input)
}

View File

@@ -13,7 +13,7 @@ abstract class Parser {
fun parse(input: TokenList): ParserOutput {
val snapshot = input.snapshot()
val output = tryToParse(input)
if(output.result == ParsingResult.FAILED) {
if (output.result == ParsingResult.FAILED) {
input.restore(snapshot)
}
@@ -28,7 +28,7 @@ abstract class Parser {
fun terminal(terminal: TokenType, createNode: (Token) -> Node = { TokenNode(it) }): Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
if(input.hasCurrent() && input.current.type == terminal) {
if (input.hasCurrent() && input.current.type == terminal) {
val token = input.current
input.ahead()
return ParserOutput.ok(createNode(token))
@@ -40,16 +40,16 @@ abstract class Parser {
}
// oneOf -> a | b | c | ...
fun oneOf(parsers: List<Parser>): Parser {
fun oneOf(vararg parsers: Parser): Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
if(parsers.isEmpty()) {
if (parsers.isEmpty()) {
throw RuntimeException("Provide one parser at least")
}
for (parser in parsers) {
val output = parser.parse(input)
if(output.result == ParsingResult.OK) {
if (output.result == ParsingResult.OK) {
return output
}
}
@@ -60,15 +60,15 @@ abstract class Parser {
}
// a -> A | B | C | ...
fun terminals(terminals: List<TokenType>, createNode: (Token) -> Node = { TokenNode(it) }): Parser {
return oneOf(terminals.map { terminal(it, createNode) })
fun terminals(vararg terminals: TokenType, createNode: (Token) -> Node = { TokenNode(it) }): Parser {
return oneOf(*terminals.map { terminal(it, createNode) }.toTypedArray())
}
// allOf -> a b c ...
fun allOf(parsers: List<Parser>, createNode: (List<Node>) -> Node): Parser {
fun allOf(vararg parsers: Parser, createNode: (List<Node>) -> Node): Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
if(parsers.isEmpty()) {
if (parsers.isEmpty()) {
throw RuntimeException("Provide one parser at least")
}
@@ -91,16 +91,21 @@ abstract class Parser {
}
// leftAssociative -> left | left OP right
fun leftAssociativeOperator(lhsParser: Parser, allowedOperators: List<TokenType>, rhsParser: Parser, createNode: (lhs: Node, operator: Node, rhs: Node) -> Node): Parser {
fun leftAssociativeOperator(
lhsParser: Parser,
allowedOperators: List<TokenType>,
rhsParser: Parser,
createNode: (lhs: Node, operator: Node, rhs: Node) -> Node
): Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val opParser = terminals(allowedOperators)
val opParser = terminals(*allowedOperators.toTypedArray())
var lhs = lhsParser.parse(input)
if(lhs.result == ParsingResult.OK) {
if (lhs.result == ParsingResult.OK) {
var op = opParser.parse(input)
while (op.result == ParsingResult.OK) {
val rhs = rhsParser.parse(input)
if(rhs.result == ParsingResult.FAILED) { // Todo: Not sure if it should be here
if (rhs.result == ParsingResult.FAILED) { // Todo: Not sure if it should be here
return ParserOutput.fail()
}
lhs = ParserOutput.ok(createNode(lhs.node, op.node, rhs.node))
@@ -120,11 +125,11 @@ abstract class Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val items = mutableListOf<Node>()
while(true) {
while (true) {
val output = itemParser.parse(input)
if(output.result == ParsingResult.OK) {
if (output.result == ParsingResult.OK) {
items += output.node
} else if(items.isEmpty()) {
} else if (items.isEmpty()) {
return ParserOutput.fail()
} else {
return ParserOutput.ok(createNode(items, items.first().position))
@@ -136,19 +141,24 @@ abstract class Parser {
}
// loop -> begin item* end
fun loop(beginParser: Parser, itemParser: Parser, endParser: Parser, createNode: (Node, List<Node>, Node) -> Node): Parser {
fun loop(
beginParser: Parser,
itemParser: Parser,
endParser: Parser,
createNode: (Node, List<Node>, Node) -> Node
): Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val items = mutableListOf<Node>()
val begin = beginParser.parse(input)
if(begin.result == ParsingResult.OK) {
while(true) {
if (begin.result == ParsingResult.OK) {
while (true) {
val end = endParser.parse(input)
if(end.result == ParsingResult.OK) {
if (end.result == ParsingResult.OK) {
return ParserOutput.ok(createNode(begin.node, items, end.node))
}
val item = itemParser.parse(input)
if(item.result == ParsingResult.FAILED) {
if (item.result == ParsingResult.FAILED) {
return ParserOutput.fail()
}
items += item.node
@@ -180,12 +190,12 @@ abstract class Parser {
return object : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val output = parser.parse(input)
return if(output.result == ParsingResult.OK) output else ParserOutput.ok(Node.NONE)
return if (output.result == ParsingResult.OK) output else ParserOutput.ok(Node.NONE)
}
}
}
fun mapNode(parser: Parser, mapper: (Node) -> Node) : 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

@@ -7,14 +7,14 @@ import dsl.token.model.enumeration.TokenType
class RegularFunctionDefinitionArgumentParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
optional(terminal(TokenType.DOTS)),
SimpleIdentifierParser(),
optional(allOf(listOf(
optional(allOf(
terminal(TokenType.COLON),
TypeParser()
)){ it[1] })
)) {
) { it[1] })
) {
RegularFunctionDefinitionArgumentNode(it[1], it[2], it[0])
}.parse(input)
}

View File

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

View File

@@ -9,8 +9,8 @@ class SimpleIdentifierParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val identifierParser = terminal(TokenType.IDENTIFIER) { IdentifierNode(it) }
return oneOf(listOf(
return oneOf(
identifierParser
)).parse(input)
).parse(input)
}
}

View File

@@ -7,18 +7,14 @@ import dsl.token.model.enumeration.TokenType
class StatementParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(
listOf(
oneOf(
listOf(
ConditionParser(),
ExpressionParser(),
BlockParser(),
ReturnParser(),
ThrowParser()
)
),
optional(terminal(TokenType.SEMICOLON))
)
oneOf(
ConditionParser(),
ExpressionParser(),
BlockParser(),
ReturnParser(),
ThrowParser()
),
optional(terminal(TokenType.SEMICOLON))
) {
it[0]
}.parse(input)

View File

@@ -13,32 +13,32 @@ class SubexpressionParser : Parser() {
TermParser(),
listOf(TokenType.PLUS, TokenType.MINUS),
TermParser()
) {
lhs, operator, rhs -> SumOperatorNode(lhs, operator, rhs)
) { 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)
) { lhs, operator, rhs ->
RelationOperatorNode(lhs, operator, rhs)
}
val expr3Parser = leftAssociativeOperator(
expr2Parser,
listOf(TokenType.AND),
expr2Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
) { lhs, operator, rhs ->
LogicOperatorNode(lhs, operator, rhs)
}
val expr4Parser = leftAssociativeOperator(
expr3Parser,
listOf(TokenType.OR),
expr3Parser
) {
lhs, operator, rhs -> LogicOperatorNode(lhs, operator, rhs)
) { lhs, operator, rhs ->
LogicOperatorNode(lhs, operator, rhs)
}
return expr4Parser.parse(input)

View File

@@ -11,8 +11,8 @@ class TermParser : Parser() {
FactorParser(),
listOf(TokenType.ASTERISK, TokenType.SLASH),
FactorParser()
) {
lhs, operator, rhs -> ProductOperatorNode(lhs, operator, rhs)
) { lhs, operator, rhs ->
ProductOperatorNode(lhs, operator, rhs)
}.parse(input)
}
}

View File

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

View File

@@ -7,10 +7,10 @@ import dsl.token.model.entity.TokenList
class TypeParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
return allOf(listOf(
return allOf(
SimpleIdentifierParser(),
optional(repeat(TypeSpecifierParser()) { list, tokenPosition -> TypeSpecifiersNode(list, tokenPosition) })
)) {
optional(repeat(TypeSpecifierParser()) { list, tokenPosition -> TypeSpecifiersNode(list, tokenPosition) })
) {
TypeNode(it[0], it[1])
}.parse(input)
}

View File

@@ -3,6 +3,7 @@ package dsl.ast.parser
import dsl.ast.model.node.TypeSpecifierNode
import dsl.token.model.enumeration.TokenType
class TypeSpecifierParser : AbstractIterableParser(TokenType.OPEN_ANGLE, TypeParser(), TokenType.CLOSE_ANGLE, {
list, tokenPosition -> TypeSpecifierNode(list, tokenPosition)
})
class TypeSpecifierParser :
AbstractIterableParser(TokenType.OPEN_ANGLE, TypeParser(), TokenType.CLOSE_ANGLE, { list, tokenPosition ->
TypeSpecifierNode(list, tokenPosition)
})

View File

@@ -9,21 +9,19 @@ import dsl.token.model.enumeration.TokenType
class UnitParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput {
val minusOperatorParser = allOf(
listOf(
terminal(TokenType.MINUS),
assert(AtomParser(), "atom")
)
terminal(TokenType.MINUS),
assert(AtomParser(), "atom")
) {
MinusOperatorNode(it[0], it[1])
}
val atom2 = oneOf(listOf(
val atom2 = oneOf(
minusOperatorParser,
AtomParser()
))
)
return leftAssociativeOperator(atom2, listOf(TokenType.DOT), assert(atom2, "atom")) {
lhs, operator, rhs -> AccessOperatorNode(lhs, operator, rhs)
return leftAssociativeOperator(atom2, listOf(TokenType.DOT), assert(atom2, "atom")) { lhs, operator, rhs ->
AccessOperatorNode(lhs, operator, rhs)
}.parse(input)
}
}