Extract SMNP core from 'app' module to 'core' module
This commit is contained in:
@@ -1,10 +1,5 @@
|
||||
dependencies {
|
||||
compile project(':api')
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
compile group: 'org.jetbrains.kotlin', name: 'kotlin-reflect', version: '1.3.61'
|
||||
compile group: 'org.pf4j', name: 'pf4j', version: '3.2.0'
|
||||
compile group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.13.1'
|
||||
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: '2.0.0-alpha1'
|
||||
compile project(':core')
|
||||
compile "com.xenomachina:kotlin-argparser:2.0.7"
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
package io.smnp.callable.function
|
||||
|
||||
import io.smnp.callable.util.FunctionEnvironmentProvider
|
||||
import io.smnp.callable.util.FunctionSignatureParser
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.evaluation.evaluator.BlockEvaluator
|
||||
import io.smnp.evaluation.model.exception.Return
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object CustomFunction {
|
||||
fun create(node: FunctionDefinitionNode): Function {
|
||||
val identifier = (node.identifier as IdentifierNode).token.rawValue
|
||||
|
||||
return object : Function(identifier) {
|
||||
override fun define(new: FunctionDefinitionTool) {
|
||||
val (_, argumentsNode, bodyNode) = node
|
||||
val signature = FunctionSignatureParser.parseSignature(argumentsNode as FunctionDefinitionArgumentsNode)
|
||||
val evaluator = BlockEvaluator(dedicatedScope = false)
|
||||
|
||||
new function signature body { env, args ->
|
||||
val boundArguments = FunctionEnvironmentProvider.provideEnvironment(argumentsNode, args, env)
|
||||
|
||||
try {
|
||||
env.pushScope(boundArguments.toMutableMap())
|
||||
evaluator.evaluate(bodyNode, env)
|
||||
} catch(value: Return) {
|
||||
return@body value.value
|
||||
} finally {
|
||||
env.popScope()
|
||||
}
|
||||
|
||||
Value.void()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.smnp.callable.method
|
||||
|
||||
import io.smnp.callable.util.FunctionEnvironmentProvider
|
||||
import io.smnp.callable.util.FunctionSignatureParser
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.evaluation.evaluator.BlockEvaluator
|
||||
import io.smnp.evaluation.model.exception.Return
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object CustomMethod {
|
||||
fun create(type: Matcher, node: FunctionDefinitionNode): Method {
|
||||
val identifier = (node.identifier as IdentifierNode).token.rawValue
|
||||
|
||||
return object : Method(type, identifier) {
|
||||
override fun define(new: MethodDefinitionTool) {
|
||||
val (_, argumentsNode, bodyNode) = node
|
||||
val signature = FunctionSignatureParser.parseSignature(argumentsNode as FunctionDefinitionArgumentsNode)
|
||||
val evaluator = BlockEvaluator(dedicatedScope = false)
|
||||
|
||||
new method signature body { env, obj, args ->
|
||||
val boundArguments =
|
||||
FunctionEnvironmentProvider.provideEnvironment(argumentsNode, args, env).toMutableMap()
|
||||
boundArguments["this"] = obj
|
||||
|
||||
try {
|
||||
env.pushScope(boundArguments)
|
||||
evaluator.evaluate(bodyNode, env)
|
||||
} catch (value: Return) {
|
||||
return@body value.value
|
||||
} finally {
|
||||
env.popScope()
|
||||
}
|
||||
|
||||
Value.void()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package io.smnp.callable.util
|
||||
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.ast.model.node.OptionalFunctionDefinitionArgumentNode
|
||||
import io.smnp.dsl.ast.model.node.RegularFunctionDefinitionArgumentNode
|
||||
import io.smnp.environment.Environment
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.evaluation.evaluator.ExpressionEvaluator
|
||||
import io.smnp.type.model.Value
|
||||
|
||||
object FunctionEnvironmentProvider {
|
||||
private val evaluator = ExpressionEvaluator()
|
||||
|
||||
fun provideEnvironment(
|
||||
signature: FunctionDefinitionArgumentsNode,
|
||||
actualArgs: List<Value>,
|
||||
environment: Environment
|
||||
): Map<String, Value> {
|
||||
return signature.items.mapIndexed { index, node ->
|
||||
when (node) {
|
||||
is RegularFunctionDefinitionArgumentNode -> regularArgument(node, actualArgs, index)
|
||||
is OptionalFunctionDefinitionArgumentNode -> optionalArgument(node, environment, actualArgs, index)
|
||||
else -> throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
}.toMap()
|
||||
}
|
||||
|
||||
private fun regularArgument(
|
||||
node: RegularFunctionDefinitionArgumentNode,
|
||||
actualArgs: List<Value>,
|
||||
index: Int
|
||||
) = (node.identifier as IdentifierNode).token.rawValue to actualArgs[index]
|
||||
|
||||
private fun optionalArgument(
|
||||
node: OptionalFunctionDefinitionArgumentNode,
|
||||
environment: Environment,
|
||||
actualArgs: List<Value>,
|
||||
index: Int
|
||||
) = (node.identifier as IdentifierNode).token.rawValue to
|
||||
if (index < actualArgs.size) actualArgs[index]
|
||||
else evaluator.evaluate(node.defaultValue, environment).value
|
||||
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
package io.smnp.callable.util
|
||||
|
||||
import io.smnp.callable.signature.Signature
|
||||
import io.smnp.dsl.ast.model.node.*
|
||||
import io.smnp.error.InvalidSignatureException
|
||||
import io.smnp.error.ShouldNeverReachThisLineException
|
||||
import io.smnp.type.enumeration.DataType
|
||||
import io.smnp.type.matcher.Matcher
|
||||
import io.smnp.type.matcher.Matcher.Companion.anyType
|
||||
import io.smnp.type.matcher.Matcher.Companion.listOfMatchers
|
||||
import io.smnp.type.matcher.Matcher.Companion.mapOfMatchers
|
||||
import io.smnp.type.matcher.Matcher.Companion.ofType
|
||||
import io.smnp.type.matcher.Matcher.Companion.oneOf
|
||||
import io.smnp.type.matcher.Matcher.Companion.optional
|
||||
|
||||
object FunctionSignatureParser {
|
||||
private data class SignatureMetadata(val hasRegular: Boolean, val hasOptional: Boolean, val hasVararg: Boolean)
|
||||
|
||||
fun parseSignature(signature: FunctionDefinitionArgumentsNode): Signature {
|
||||
val (_, _, hasVararg) = assertArgumentsPositions(signature)
|
||||
assertArgumentsNames(signature)
|
||||
|
||||
val matchers = signature.items.map {
|
||||
when (it) {
|
||||
is RegularFunctionDefinitionArgumentNode -> matcherForUnionTypeNode(it.type as UnionTypeNode)
|
||||
is OptionalFunctionDefinitionArgumentNode -> optional(matcherForUnionTypeNode(it.type as UnionTypeNode))
|
||||
else -> throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
}
|
||||
|
||||
return if (hasVararg) Signature.vararg(
|
||||
matchers.last(),
|
||||
*matchers.dropLast(1).toTypedArray()
|
||||
) else Signature.simple(*matchers.toTypedArray())
|
||||
}
|
||||
|
||||
private fun assertArgumentsNames(signature: FunctionDefinitionArgumentsNode) {
|
||||
signature.items.groupingBy {
|
||||
when (it) {
|
||||
is RegularFunctionDefinitionArgumentNode -> (it.identifier as IdentifierNode).token.rawValue
|
||||
is OptionalFunctionDefinitionArgumentNode -> (it.identifier as IdentifierNode).token.rawValue
|
||||
else -> throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
}.eachCount().forEach {
|
||||
if (it.value > 1) {
|
||||
throw InvalidSignatureException("Duplicated argument name of '${it.key}'")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun assertArgumentsPositions(signature: FunctionDefinitionArgumentsNode): SignatureMetadata {
|
||||
val firstOptional = signature.items.indexOfFirst { it is OptionalFunctionDefinitionArgumentNode }
|
||||
val lastRegular = signature.items.indexOfLast { it is RegularFunctionDefinitionArgumentNode }
|
||||
val vararg =
|
||||
signature.items.indexOfFirst { it is RegularFunctionDefinitionArgumentNode && it.vararg != Node.NONE }
|
||||
|
||||
val metadata = SignatureMetadata(
|
||||
lastRegular != -1,
|
||||
firstOptional != -1,
|
||||
vararg != -1
|
||||
)
|
||||
|
||||
if (metadata.hasVararg && metadata.hasOptional) {
|
||||
throw InvalidSignatureException("Optional arguments and vararg cannot be mixed in same signature")
|
||||
}
|
||||
|
||||
if (metadata.hasRegular && metadata.hasOptional && firstOptional < lastRegular) {
|
||||
throw InvalidSignatureException("Optional arguments should be at the very end of arguments list")
|
||||
}
|
||||
|
||||
if (metadata.hasVararg && vararg != signature.items.size - 1) {
|
||||
throw InvalidSignatureException("Vararg arguments should be at the very end of arguments list")
|
||||
}
|
||||
|
||||
return metadata
|
||||
}
|
||||
|
||||
private fun matcherForUnionTypeNode(unionTypeNode: UnionTypeNode): Matcher {
|
||||
if (unionTypeNode.items.isEmpty()) {
|
||||
return anyType()
|
||||
}
|
||||
|
||||
if (unionTypeNode.items.size == 1) {
|
||||
return matcherForSingleTypeNode(
|
||||
unionTypeNode.items[0] as SingleTypeNode
|
||||
)
|
||||
}
|
||||
|
||||
return oneOf(*unionTypeNode.items.map {
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
}.toTypedArray())
|
||||
}
|
||||
|
||||
fun matcherForSingleTypeNode(singleTypeNode: SingleTypeNode): Matcher {
|
||||
// TODO
|
||||
val type = DataType.valueOf((singleTypeNode.type as IdentifierNode).token.rawValue.toUpperCase())
|
||||
if (singleTypeNode.specifiers == Node.NONE) {
|
||||
return ofType(type)
|
||||
} else if (type == DataType.LIST && singleTypeNode.specifiers.children.size == 1) {
|
||||
return listSpecifier(singleTypeNode.specifiers.children[0] as TypeSpecifierNode)
|
||||
} else if (type == DataType.MAP && singleTypeNode.specifiers.children.size == 2) {
|
||||
return mapSpecifier(
|
||||
singleTypeNode.specifiers.children[0] as TypeSpecifierNode,
|
||||
singleTypeNode.specifiers.children[1] as TypeSpecifierNode
|
||||
)
|
||||
}
|
||||
|
||||
throw ShouldNeverReachThisLineException()
|
||||
}
|
||||
|
||||
private fun listSpecifier(listSpecifierNode: TypeSpecifierNode): Matcher {
|
||||
val types = mutableListOf<Matcher>()
|
||||
|
||||
if (listSpecifierNode.items.isEmpty()) {
|
||||
types.add(anyType())
|
||||
}
|
||||
|
||||
listSpecifierNode.items.forEach { types.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
|
||||
return listOfMatchers(*types.toTypedArray())
|
||||
}
|
||||
|
||||
private fun mapSpecifier(keySpecifierNode: TypeSpecifierNode, valueSpecifierNode: TypeSpecifierNode): Matcher {
|
||||
val keys = mutableListOf<Matcher>()
|
||||
val values = mutableListOf<Matcher>()
|
||||
|
||||
if (keySpecifierNode.items.isEmpty()) {
|
||||
keys.add(anyType())
|
||||
}
|
||||
|
||||
if (valueSpecifierNode.items.isEmpty()) {
|
||||
values.add(anyType())
|
||||
}
|
||||
|
||||
keySpecifierNode.items.forEach { keys.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
valueSpecifierNode.items.forEach { values.add(
|
||||
matcherForSingleTypeNode(
|
||||
it as SingleTypeNode
|
||||
)
|
||||
) }
|
||||
|
||||
return mapOfMatchers(keys, values)
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.entity
|
||||
|
||||
import io.smnp.dsl.ast.model.enumeration.ParsingResult
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
|
||||
class ParserOutput private constructor(val result: ParsingResult, val node: Node) {
|
||||
fun map(mapper: (Node) -> Node): ParserOutput {
|
||||
return if(result == ParsingResult.OK) ok(mapper(node)) else fail()
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun ok(node: Node): ParserOutput {
|
||||
return ParserOutput(ParsingResult.OK, node)
|
||||
}
|
||||
|
||||
fun fail(): ParserOutput {
|
||||
return ParserOutput(ParsingResult.FAILED, Node.NONE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.enumeration
|
||||
|
||||
enum class ParsingResult {
|
||||
OK,
|
||||
FAILED
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
abstract class AbstractIterableNode(items: List<Node>, position: TokenPosition) : Node(items, position) {
|
||||
val items: List<Node>
|
||||
get() = children
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class AccessOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class AssignmentOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,11 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
abstract class AtomAbstractNode(val token: Token) : Node(1, token.position) {
|
||||
override fun pretty(prefix: String, last: Boolean, first: Boolean) {
|
||||
println(prefix + (if (first) "" else if (last) "└─" else "├─") + this::class.simpleName + " " + position)
|
||||
println(prefix + (if (last) " " else "│ ") + "└ " + token)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
abstract class BinaryOperatorAbstractNode(lhs: Node, operator: Node, rhs: Node) : Node(3, operator.position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
operator fun component3() = children[2]
|
||||
|
||||
val lhs: Node
|
||||
get() = children[0]
|
||||
|
||||
val operator: Node
|
||||
get() = children[1]
|
||||
|
||||
val rhs: Node
|
||||
get() = children[2]
|
||||
|
||||
init {
|
||||
children[0] = lhs
|
||||
children[1] = operator
|
||||
children[2] = rhs
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class BlockNode(begin: Node, statements: List<Node>, end: Node) : Node(statements, begin.position) {
|
||||
val statements: List<Node>
|
||||
get() = children
|
||||
|
||||
init {
|
||||
children = statements.toMutableList()
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class BoolLiteralNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,22 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class ConditionNode(trueBranchToken: Node, condition: Node, trueBranch: Node, falseBranchToken: Node, falseBranch: Node) : Node(3, trueBranchToken.position) {
|
||||
operator fun component1(): Node = children[0]
|
||||
operator fun component2(): Node = children[1]
|
||||
operator fun component3(): Node = children[2]
|
||||
|
||||
val condition: Node
|
||||
get() = children[0]
|
||||
|
||||
val trueBranch: Node
|
||||
get() = children[1]
|
||||
|
||||
val falseBranch: Node
|
||||
get() = children[2]
|
||||
|
||||
init {
|
||||
children[0] = condition
|
||||
children[1] = trueBranch
|
||||
children[2] = falseBranch
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class ExtendNode(type: Node, functions: Node, position: TokenPosition) : Node(2, position) {
|
||||
operator fun component1(): Node = children[0]
|
||||
operator fun component2(): Node = children[1]
|
||||
|
||||
val type: Node
|
||||
get() = children[0]
|
||||
|
||||
val functions: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = type
|
||||
children[1] = functions
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class FloatLiteralNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class FunctionCallArgumentsNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class FunctionCallNode(identifier: Node, arguments: Node) : Node(2, identifier.position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
|
||||
val identifier: Node
|
||||
get() = children[0]
|
||||
|
||||
val arguments: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = identifier
|
||||
children[1] = arguments
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class FunctionDefinitionArgumentsNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class FunctionDefinitionNode(identifier: Node, arguments: Node, body: Node, position: TokenPosition) : Node(3, position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
operator fun component3() = children[2]
|
||||
|
||||
val identifier: Node
|
||||
get() = children[0]
|
||||
|
||||
val arguments: Node
|
||||
get() = children[1]
|
||||
|
||||
val body: Node
|
||||
get() = children[2]
|
||||
|
||||
init {
|
||||
children[0] = identifier
|
||||
children[1] = arguments
|
||||
children[2] = body
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class IdentifierNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,8 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class ImportNode(path: List<Node>, position: TokenPosition) : Node(path, position) {
|
||||
val path: List<Node>
|
||||
get() = children
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class IntegerLiteralNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class ListNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class LogicOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class LoopNode(iterator: Node, parameters: Node, operator: Node, statement: Node, filter: Node): Node(4, operator.position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
operator fun component3() = children[2]
|
||||
operator fun component4() = children[3]
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class LoopParametersNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class MapEntryNode(key: Node, operator: Node, value: Node) : Node(2, operator.position) {
|
||||
val key: Node
|
||||
get() = children[0]
|
||||
|
||||
val value: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = key
|
||||
children[1] = value
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class MapNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class MeasureNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class MinusOperatorNode(operator: Node, operand: Node) : UnaryOperatorAbstractNode(operator, operand)
|
||||
@@ -1,35 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
abstract class Node(numberOfChildren: Int, val position: TokenPosition) {
|
||||
var children: MutableList<Node> = MutableList(numberOfChildren) { NONE }
|
||||
protected set
|
||||
|
||||
constructor(children: List<Node>, position: TokenPosition) : this(children.size, position) {
|
||||
this.children = children.toMutableList()
|
||||
}
|
||||
|
||||
operator fun get(index: Int) = children[index]
|
||||
|
||||
operator fun set(index: Int, value: Node) {
|
||||
children[index] = value
|
||||
}
|
||||
|
||||
open fun pretty(prefix: String = "", last: Boolean = true, first: Boolean = true) {
|
||||
var newPrefix = prefix
|
||||
var newLast = last
|
||||
val nodeName = this::class.simpleName ?: "<anonymous>"
|
||||
|
||||
println(newPrefix + (if (first) "" else if (newLast) "└─" else "├─") + nodeName + " " + position)
|
||||
newPrefix += if (newLast) " " else "│ "
|
||||
for ((index, child) in children.withIndex()) {
|
||||
newLast = index == children.size - 1
|
||||
child.pretty(newPrefix, newLast, false)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NONE = NoneNode()
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class NoneNode : Node(0,
|
||||
TokenPosition.NONE
|
||||
)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class NotOperatorNode(operator: Node, operand: Node) : UnaryOperatorAbstractNode(operator, operand)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class NoteLiteralNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,18 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class OptionalFunctionDefinitionArgumentNode(identifier: Node, type: Node, defaultValue: Node) : Node(3, identifier.position) {
|
||||
val identifier: Node
|
||||
get() = children[0]
|
||||
|
||||
val type: Node
|
||||
get() = children[1]
|
||||
|
||||
val defaultValue: Node
|
||||
get() = children[2]
|
||||
|
||||
init {
|
||||
children[0] = identifier
|
||||
children[1] = type
|
||||
children[2] = defaultValue
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class PowerOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class ProductOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,18 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class RegularFunctionDefinitionArgumentNode(identifier: Node, type: Node, vararg: Node) : Node(3, identifier.position) {
|
||||
val identifier
|
||||
get() = children[0]
|
||||
|
||||
val type
|
||||
get() = children[1]
|
||||
|
||||
val vararg
|
||||
get() = children[2]
|
||||
|
||||
init {
|
||||
children[0] = identifier
|
||||
children[1] = type
|
||||
children[2] = vararg
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class RelationOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class ReturnNode(value: Node) : Node(1, value.position) {
|
||||
operator fun component1() = children[0]
|
||||
|
||||
val value: Node
|
||||
get() = children[0]
|
||||
|
||||
init {
|
||||
children[0] = value
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class RootNode(nodes: List<Node>, position: TokenPosition) : Node(nodes, position)
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class SingleTypeNode(type: Node, specifiers: Node) : Node(2, type.position) {
|
||||
val type: Node
|
||||
get() = children[0]
|
||||
|
||||
val specifiers: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = type
|
||||
children[1] = specifiers
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class StaffNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class StringLiteralNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,3 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class SumOperatorNode(lhs: Node, operator: Node, rhs: Node) : BinaryOperatorAbstractNode(lhs, operator, rhs)
|
||||
@@ -1,10 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class ThrowNode(value: Node) : Node(1, value.position) {
|
||||
val value: Node
|
||||
get() = children[0]
|
||||
|
||||
init {
|
||||
children[0] = value
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
class TimeSignatureNode(numerator: Node, denominator: Node) : Node(2, numerator.position) {
|
||||
val numerator: Node
|
||||
get() = children[0]
|
||||
|
||||
val denominator: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = numerator
|
||||
children[1] = denominator
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
|
||||
class TokenNode(token: Token) : AtomAbstractNode(token)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class TypeSpecifierNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class TypeSpecifiersNode(specifiers: List<Node>, position: TokenPosition) : Node(specifiers, position)
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
abstract class UnaryOperatorAbstractNode(operator: Node, operand: Node) : Node(2, operator.position) {
|
||||
operator fun component1() = children[0]
|
||||
operator fun component2() = children[1]
|
||||
|
||||
val operator: Node
|
||||
get() = children[0]
|
||||
|
||||
val operand: Node
|
||||
get() = children[1]
|
||||
|
||||
init {
|
||||
children[0] = operator
|
||||
children[1] = operand
|
||||
}
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
package io.smnp.dsl.ast.model.node
|
||||
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
|
||||
class UnionTypeNode(items: List<Node>, position: TokenPosition) : AbstractIterableNode(items, position)
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
abstract class AbstractIterableParser(
|
||||
private val beginTokenType: TokenType,
|
||||
private val itemParser: Parser,
|
||||
private val endTokenType: TokenType,
|
||||
private val separator: TokenType = TokenType.COMMA,
|
||||
private val createNode: (List<Node>, TokenPosition) -> Node
|
||||
) : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val emptyIterableParser = allOf(
|
||||
terminal(beginTokenType),
|
||||
terminal(endTokenType)
|
||||
) { (beginToken) -> createNode(listOf(), beginToken.position) }
|
||||
|
||||
val nonEmptyIterableParser = allOf(
|
||||
terminal(beginTokenType),
|
||||
allOf(
|
||||
itemParser,
|
||||
optional(repeat(allOf(
|
||||
terminal(separator),
|
||||
itemParser
|
||||
) { (_, item) -> item }) { list, position -> object : Node(list, position) {} }
|
||||
)) { (firstItem, otherAggregatedItems) ->
|
||||
object : Node(listOf(firstItem) + otherAggregatedItems.children, TokenPosition.NONE) {}
|
||||
},
|
||||
terminal(endTokenType)
|
||||
) { (beginToken, aggregatedItems) -> createNode(aggregatedItems.children.toList(), beginToken.position) }
|
||||
|
||||
return oneOf(
|
||||
emptyIterableParser,
|
||||
nonEmptyIterableParser
|
||||
).parse(input)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.AssignmentOperatorNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class AssignmentOperatorParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
SimpleIdentifierParser(),
|
||||
terminal(TokenType.ASSIGN),
|
||||
assert(ExpressionParser(), "expression")
|
||||
) { (target, assignToken, value) -> AssignmentOperatorNode(target, assignToken, value) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class AtomParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val parenthesesParser = allOf(
|
||||
terminal(TokenType.OPEN_PAREN),
|
||||
ExpressionParser(),
|
||||
terminal(TokenType.CLOSE_PAREN)
|
||||
) { (_, expression) -> expression }
|
||||
|
||||
val literalParser = oneOf(
|
||||
parenthesesParser,
|
||||
ComplexIdentifierParser(),
|
||||
StaffParser(),
|
||||
ListParser(),
|
||||
LiteralParser(),
|
||||
MapParser()
|
||||
)
|
||||
|
||||
return literalParser.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.BlockNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class BlockParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return loop(
|
||||
terminal(TokenType.OPEN_CURLY),
|
||||
assert(StatementParser(), "statement or }"),
|
||||
terminal(TokenType.CLOSE_CURLY)
|
||||
) { begin, list, end ->
|
||||
BlockNode(begin, list, end)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.BoolLiteralNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class BoolLiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return terminal(TokenType.BOOL) { BoolLiteralNode(it) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class ComplexIdentifierParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return oneOf(
|
||||
AssignmentOperatorParser(),
|
||||
FunctionCallParser(),
|
||||
SimpleIdentifierParser()
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.ConditionNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ConditionParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val ifStatementParser = allOf(
|
||||
terminal(TokenType.IF),
|
||||
terminal(TokenType.OPEN_PAREN),
|
||||
assert(SubexpressionParser(), "expression"),
|
||||
terminal(TokenType.CLOSE_PAREN),
|
||||
assert(StatementParser(), "statement")
|
||||
) { (ifToken, _, condition, _, trueBranch) ->
|
||||
ConditionNode(ifToken, condition, trueBranch, Node.NONE, Node.NONE)
|
||||
}
|
||||
|
||||
val ifElseStatementParser = allOf(
|
||||
terminal(TokenType.IF),
|
||||
terminal(TokenType.OPEN_PAREN),
|
||||
assert(SubexpressionParser(), "expression"),
|
||||
terminal(TokenType.CLOSE_PAREN),
|
||||
assert(StatementParser(), "statement"),
|
||||
terminal(TokenType.ELSE),
|
||||
assert(StatementParser(), "statement")
|
||||
) { (ifToken, _, condition, _, trueBranch, elseToken, falseBranch) ->
|
||||
ConditionNode(ifToken, condition, trueBranch, elseToken, falseBranch)
|
||||
}
|
||||
|
||||
return oneOf(
|
||||
ifElseStatementParser,
|
||||
ifStatementParser
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
// It is required for destructing list of nodes in ifElseStatementParser object
|
||||
private operator fun <E> List<E>.component6() = this[5];
|
||||
private operator fun <E> List<E>.component7() = this[6];
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class ExpressionParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return oneOf(
|
||||
LoopParser(),
|
||||
SubexpressionParser()
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.BlockNode
|
||||
import io.smnp.dsl.ast.model.node.ExtendNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ExtendParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val simpleExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
terminal(TokenType.WITH),
|
||||
assert(
|
||||
mapNode(FunctionDefinitionParser()) { BlockNode(Node.NONE, listOf(it), Node.NONE) },
|
||||
"method definition"
|
||||
)
|
||||
) { (extendToken, targetType, _, method) ->
|
||||
ExtendNode(targetType, method, extendToken.position)
|
||||
}
|
||||
|
||||
val complexExtendParser = allOf(
|
||||
terminal(TokenType.EXTEND),
|
||||
assert(SingleTypeParser(), "type to be extended"),
|
||||
assert(
|
||||
loop(
|
||||
terminal(TokenType.OPEN_CURLY),
|
||||
assert(FunctionDefinitionParser(), "method definition or }"),
|
||||
terminal(TokenType.CLOSE_CURLY)
|
||||
) { begin, methods, end ->
|
||||
BlockNode(begin, methods, end)
|
||||
}, "block with methods' definitions or 'with' keyword with single method definition"
|
||||
)
|
||||
) { (extendToken, targetType, methods) ->
|
||||
ExtendNode(targetType, methods, extendToken.position)
|
||||
}
|
||||
|
||||
return oneOf(
|
||||
simpleExtendParser,
|
||||
complexExtendParser
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.NotOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.PowerOperatorNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class FactorParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val factorParser = leftAssociativeOperator(
|
||||
UnitParser(),
|
||||
listOf(TokenType.DOUBLE_ASTERISK),
|
||||
assert(UnitParser(), "expression")
|
||||
) { lhs, operator, rhs -> PowerOperatorNode(lhs, operator, rhs) }
|
||||
|
||||
val notOperatorParser = allOf(
|
||||
terminal(TokenType.NOT),
|
||||
assert(factorParser, "expression")
|
||||
) { (notToken, expression) -> NotOperatorNode(notToken, expression) }
|
||||
|
||||
return oneOf(
|
||||
notOperatorParser,
|
||||
factorParser
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.FloatLiteralNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class FloatLiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return terminal(TokenType.FLOAT) { FloatLiteralNode(it) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.FunctionCallArgumentsNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class FunctionCallArgumentsParser :
|
||||
AbstractIterableParser(
|
||||
TokenType.OPEN_PAREN,
|
||||
ExpressionParser(),
|
||||
TokenType.CLOSE_PAREN,
|
||||
createNode = { list, tokenPosition ->
|
||||
FunctionCallArgumentsNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,14 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.FunctionCallNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class FunctionCallParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
SimpleIdentifierParser(),
|
||||
FunctionCallArgumentsParser()
|
||||
) { (identifier, arguments) -> FunctionCallNode(identifier, arguments) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class FunctionDefinitionArgumentParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return assert(oneOf(
|
||||
OptionalFunctionDefinitionArgumentParser(),
|
||||
RegularFunctionDefinitionArgumentParser()
|
||||
), "optional or regular argument definition").parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionArgumentsNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class FunctionDefinitionArgumentsParser : AbstractIterableParser(
|
||||
TokenType.OPEN_PAREN,
|
||||
FunctionDefinitionArgumentParser(),
|
||||
TokenType.CLOSE_PAREN,
|
||||
createNode = { list, tokenPosition ->
|
||||
FunctionDefinitionArgumentsNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.FunctionDefinitionNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class FunctionDefinitionParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
terminal(TokenType.FUNCTION),
|
||||
assert(SimpleIdentifierParser(), "function/method name"),
|
||||
assert(FunctionDefinitionArgumentsParser(), "function/method arguments list"),
|
||||
assert(BlockParser(), "function/method body")
|
||||
) { (functionToken, identifier, arguments, body) ->
|
||||
FunctionDefinitionNode(identifier, arguments, body, functionToken.position)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.ImportNode
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ImportParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val pathParser = allOf(
|
||||
SimpleIdentifierParser(),
|
||||
optional(repeat(allOf(
|
||||
terminal(TokenType.DOT),
|
||||
SimpleIdentifierParser()
|
||||
) { (_, child) -> child }) { segments, position ->
|
||||
object : Node(segments, position) {}
|
||||
})) { (firstSegment, otherSegments) ->
|
||||
object : Node(listOf(firstSegment) + otherSegments.children, firstSegment.position) {}
|
||||
}
|
||||
|
||||
|
||||
return allOf(
|
||||
terminal(TokenType.IMPORT),
|
||||
assert(pathParser, "module canonical name")
|
||||
) { (import, path) ->
|
||||
ImportNode(path.children, import.position)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.IntegerLiteralNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class IntegerLiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return terminal(TokenType.INTEGER) { IntegerLiteralNode(it) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.ListNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ListParser : AbstractIterableParser(
|
||||
TokenType.OPEN_SQUARE,
|
||||
assert(ExpressionParser(), "expression"),
|
||||
TokenType.CLOSE_SQUARE,
|
||||
createNode = { list, tokenPosition ->
|
||||
ListNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class LiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return oneOf(
|
||||
BoolLiteralParser(),
|
||||
FloatLiteralParser(),
|
||||
IntegerLiteralParser(),
|
||||
NoteLiteralParser(),
|
||||
StringLiteralParser()
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.LoopParametersNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class LoopParametersParser : AbstractIterableParser(
|
||||
TokenType.OPEN_PAREN,
|
||||
assert(SimpleIdentifierParser(), "identifier"),
|
||||
TokenType.CLOSE_PAREN,
|
||||
createNode = { list, tokenPosition ->
|
||||
LoopParametersNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,34 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.LoopNode
|
||||
import io.smnp.dsl.ast.model.node.LoopParametersNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class LoopParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val loopParametersParser = allOf(
|
||||
terminal(TokenType.AS),
|
||||
assert(oneOf(
|
||||
mapNode(SimpleIdentifierParser()) { LoopParametersNode(listOf(it), it.position) },
|
||||
LoopParametersParser()
|
||||
), "loop parameters")
|
||||
) { (_, parameters) -> parameters }
|
||||
|
||||
val loopFilterParser = allOf(
|
||||
terminal(TokenType.PERCENT),
|
||||
assert(SubexpressionParser(), "filter as bool expression")
|
||||
) { (_, filter) -> filter }
|
||||
|
||||
return allOf(
|
||||
SubexpressionParser(),
|
||||
optional(loopParametersParser),
|
||||
terminal(TokenType.CARET),
|
||||
assert(StatementParser(), "statement"),
|
||||
optional(loopFilterParser)
|
||||
) { (iterator, parameters, caretToken, statement, filter) ->
|
||||
LoopNode(iterator, parameters, caretToken, statement, filter)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.MapEntryNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class MapEntryParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val keyParser = oneOf(
|
||||
LiteralParser(),
|
||||
SimpleIdentifierParser()
|
||||
)
|
||||
|
||||
return allOf(
|
||||
keyParser,
|
||||
terminal(TokenType.ARROW),
|
||||
assert(SubexpressionParser(), "expression")
|
||||
) { (key, arrowToken, value) -> MapEntryNode(key, arrowToken, value) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.MapNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class MapParser :
|
||||
AbstractIterableParser(
|
||||
TokenType.OPEN_CURLY,
|
||||
MapEntryParser(),
|
||||
TokenType.CLOSE_CURLY,
|
||||
createNode = { list, tokenPosition ->
|
||||
MapNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.MeasureNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class MeasureParser : Parser() {
|
||||
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return repeat(
|
||||
oneOf(
|
||||
TimeSignatureParser(),
|
||||
ExpressionParser()
|
||||
)
|
||||
) { items, position -> MeasureNode(items, position) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.NoteLiteralNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class NoteLiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return terminal(TokenType.NOTE) { NoteLiteralNode(it) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.OptionalFunctionDefinitionArgumentNode
|
||||
import io.smnp.dsl.ast.model.node.UnionTypeNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class OptionalFunctionDefinitionArgumentParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
SimpleIdentifierParser(),
|
||||
optional(allOf(
|
||||
terminal(TokenType.COLON),
|
||||
assert(TypeParser(), "type name")
|
||||
) { (_, type) -> type }) { UnionTypeNode(emptyList(), TokenPosition.NONE) },
|
||||
terminal(TokenType.ASSIGN),
|
||||
assert(ExpressionParser(), "expression")
|
||||
) { (identifier, type, _, defaultValue) ->
|
||||
OptionalFunctionDefinitionArgumentNode(identifier, type, defaultValue)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.enumeration.ParsingResult
|
||||
import io.smnp.dsl.ast.model.node.Node
|
||||
import io.smnp.dsl.ast.model.node.TokenNode
|
||||
import io.smnp.dsl.token.model.entity.Token
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
import io.smnp.error.InvalidSyntaxException
|
||||
import io.smnp.error.PositionException
|
||||
|
||||
abstract class Parser {
|
||||
fun parse(input: TokenList): ParserOutput {
|
||||
val snapshot = input.snapshot()
|
||||
val output = tryToParse(input)
|
||||
if (output.result == ParsingResult.FAILED) {
|
||||
input.restore(snapshot)
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
protected abstract fun tryToParse(input: TokenList): ParserOutput
|
||||
|
||||
companion object {
|
||||
|
||||
// a -> A
|
||||
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) {
|
||||
val token = input.current
|
||||
input.ahead()
|
||||
return ParserOutput.ok(createNode(token))
|
||||
}
|
||||
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// oneOf -> a | b | c | ...
|
||||
fun oneOf(vararg parsers: Parser): Parser {
|
||||
return object : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
if (parsers.isEmpty()) {
|
||||
throw RuntimeException("Provide one parser at least")
|
||||
}
|
||||
|
||||
for (parser in parsers) {
|
||||
val output = parser.parse(input)
|
||||
if (output.result == ParsingResult.OK) {
|
||||
return output
|
||||
}
|
||||
}
|
||||
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// a -> A | B | C | ...
|
||||
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(vararg parsers: Parser, createNode: (List<Node>) -> Node): Parser {
|
||||
return object : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
if (parsers.isEmpty()) {
|
||||
throw RuntimeException("Provide one parser at least")
|
||||
}
|
||||
|
||||
val nodes = mutableListOf<Node>()
|
||||
|
||||
for (parser in parsers) {
|
||||
val output = parser.parse(input)
|
||||
|
||||
if (output.result == ParsingResult.FAILED) {
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
|
||||
nodes += output.node
|
||||
}
|
||||
|
||||
return ParserOutput.ok(createNode(nodes))
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// leftAssociative -> left | left OP right
|
||||
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.toTypedArray())
|
||||
var lhs = lhsParser.parse(input)
|
||||
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
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
lhs = ParserOutput.ok(createNode(lhs.node, op.node, rhs.node))
|
||||
op = opParser.parse(input)
|
||||
}
|
||||
return lhs
|
||||
}
|
||||
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// repeat -> item*
|
||||
fun repeat(itemParser: Parser, createNode: (List<Node>, TokenPosition) -> Node): Parser {
|
||||
return object : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val items = mutableListOf<Node>()
|
||||
while (true) {
|
||||
val output = itemParser.parse(input)
|
||||
if (output.result == ParsingResult.OK) {
|
||||
items += output.node
|
||||
} else if (items.isEmpty()) {
|
||||
return ParserOutput.fail()
|
||||
} else {
|
||||
return ParserOutput.ok(createNode(items, items.first().position))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// loop -> begin item* end
|
||||
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) {
|
||||
val end = endParser.parse(input)
|
||||
if (end.result == ParsingResult.OK) {
|
||||
return ParserOutput.ok(createNode(begin.node, items, end.node))
|
||||
}
|
||||
val item = itemParser.parse(input)
|
||||
if (item.result == ParsingResult.FAILED) {
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
items += item.node
|
||||
}
|
||||
}
|
||||
|
||||
return ParserOutput.fail()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
fun assert(parser: Parser, expected: String): Parser {
|
||||
return object : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val output = parser.parse(input)
|
||||
|
||||
if (output.result == ParsingResult.FAILED) {
|
||||
throw PositionException(InvalidSyntaxException("Expected $expected, got '${input.current.rawValue}'"), input.currentPos())
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// optional -> a?
|
||||
fun optional(parser: Parser, createFallbackNode: () -> Node = { Node.NONE }): 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(createFallbackNode())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun mapNode(parser: Parser, mapper: (Node) -> Node): Parser {
|
||||
return object : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return parser.parse(input).map(mapper)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.RegularFunctionDefinitionArgumentNode
|
||||
import io.smnp.dsl.ast.model.node.UnionTypeNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.entity.TokenPosition
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class RegularFunctionDefinitionArgumentParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
optional(terminal(TokenType.DOTS)),
|
||||
SimpleIdentifierParser(),
|
||||
optional(allOf(
|
||||
terminal(TokenType.COLON),
|
||||
assert(TypeParser(), "type name")
|
||||
) { (_, type) -> type }) { UnionTypeNode(emptyList(), TokenPosition.NONE) }
|
||||
) { (vararg, identifier, type) ->
|
||||
RegularFunctionDefinitionArgumentNode(identifier, type, vararg)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.ReturnNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ReturnParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
terminal(TokenType.RETURN),
|
||||
optional(assert(ExpressionParser(), "expression"))
|
||||
) { (_, value) ->
|
||||
ReturnNode(value)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.RootNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class RootParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return assert(repeat(
|
||||
oneOf(
|
||||
allOf(ImportParser(), optional(terminal(TokenType.SEMICOLON))) { (import, _) -> import },
|
||||
FunctionDefinitionParser(),
|
||||
ExtendParser(),
|
||||
StatementParser()
|
||||
)
|
||||
) { list, tokenPosition ->
|
||||
RootNode(list, tokenPosition)
|
||||
}, "import statement, function definition, extend statement or any other statement").parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.IdentifierNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class SimpleIdentifierParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val identifierParser = terminal(TokenType.IDENTIFIER) { IdentifierNode(it) }
|
||||
|
||||
return oneOf(
|
||||
identifierParser
|
||||
).parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.SingleTypeNode
|
||||
import io.smnp.dsl.ast.model.node.TypeSpecifiersNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class SingleTypeParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
SimpleIdentifierParser(),
|
||||
optional(repeat(TypeSpecifierParser()) { list, tokenPosition -> TypeSpecifiersNode(list, tokenPosition) })
|
||||
) { (identifier, specifiers) -> SingleTypeNode(identifier, specifiers) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.StaffNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class StaffParser : AbstractIterableParser(
|
||||
TokenType.DOLLAR,
|
||||
MeasureParser(),
|
||||
TokenType.DOUBLE_PIPE,
|
||||
TokenType.PIPE,
|
||||
{ items, position -> StaffNode(items, position) }
|
||||
)
|
||||
@@ -1,20 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class StatementParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
oneOf(
|
||||
ConditionParser(),
|
||||
ExpressionParser(),
|
||||
BlockParser(),
|
||||
ReturnParser(),
|
||||
ThrowParser()
|
||||
),
|
||||
optional(terminal(TokenType.SEMICOLON))
|
||||
) { (statement) -> statement }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.StringLiteralNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class StringLiteralParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return terminal(TokenType.STRING) { StringLiteralNode(it) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.LogicOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.RelationOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.SumOperatorNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class SubexpressionParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val expr1Parser = leftAssociativeOperator(
|
||||
TermParser(),
|
||||
listOf(TokenType.PLUS, TokenType.MINUS),
|
||||
assert(TermParser(), "expression")
|
||||
) { lhs, operator, rhs ->
|
||||
SumOperatorNode(lhs, operator, rhs)
|
||||
}
|
||||
|
||||
val expr2Parser = leftAssociativeOperator(
|
||||
expr1Parser,
|
||||
listOf(TokenType.RELATION, TokenType.OPEN_ANGLE, TokenType.CLOSE_ANGLE),
|
||||
assert(expr1Parser, "expression")
|
||||
) { lhs, operator, rhs ->
|
||||
RelationOperatorNode(lhs, operator, rhs)
|
||||
}
|
||||
|
||||
val expr3Parser = leftAssociativeOperator(
|
||||
expr2Parser,
|
||||
listOf(TokenType.AND),
|
||||
assert(expr2Parser, "expression")
|
||||
) { lhs, operator, rhs ->
|
||||
LogicOperatorNode(lhs, operator, rhs)
|
||||
}
|
||||
|
||||
val expr4Parser = leftAssociativeOperator(
|
||||
expr3Parser,
|
||||
listOf(TokenType.OR),
|
||||
assert(expr3Parser, "expression")
|
||||
) { lhs, operator, rhs ->
|
||||
LogicOperatorNode(lhs, operator, rhs)
|
||||
}
|
||||
|
||||
return expr4Parser.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.ProductOperatorNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class TermParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return leftAssociativeOperator(
|
||||
FactorParser(),
|
||||
listOf(TokenType.ASTERISK, TokenType.SLASH),
|
||||
assert(FactorParser(), "expression")
|
||||
) { lhs, operator, rhs ->
|
||||
ProductOperatorNode(lhs, operator, rhs)
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.ThrowNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class ThrowParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
terminal(TokenType.THROW),
|
||||
optional(SubexpressionParser())
|
||||
) { (_, value) -> ThrowNode(value) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.TimeSignatureNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class TimeSignatureParser : Parser() {
|
||||
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return allOf(
|
||||
IntegerLiteralParser(),
|
||||
terminal(TokenType.SLASH),
|
||||
IntegerLiteralParser()
|
||||
) { (numerator, _, denominator) -> TimeSignatureNode(numerator, denominator) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.SingleTypeNode
|
||||
import io.smnp.dsl.ast.model.node.UnionTypeNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
|
||||
class TypeParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
return mapNode(oneOf(
|
||||
SingleTypeParser(),
|
||||
UnionTypeParser()
|
||||
)) {
|
||||
node -> if(node is SingleTypeNode) UnionTypeNode(listOf(node), node.position) else node
|
||||
}.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.TypeSpecifierNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class TypeSpecifierParser :
|
||||
AbstractIterableParser(
|
||||
TokenType.OPEN_ANGLE,
|
||||
SingleTypeParser(),
|
||||
TokenType.CLOSE_ANGLE,
|
||||
createNode = { list, tokenPosition ->
|
||||
TypeSpecifierNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,12 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.node.UnionTypeNode
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class UnionTypeParser : AbstractIterableParser(
|
||||
TokenType.OPEN_ANGLE,
|
||||
SingleTypeParser(),
|
||||
TokenType.CLOSE_ANGLE,
|
||||
createNode = { list, tokenPosition ->
|
||||
UnionTypeNode(list, tokenPosition)
|
||||
})
|
||||
@@ -1,27 +0,0 @@
|
||||
package io.smnp.dsl.ast.parser
|
||||
|
||||
import io.smnp.dsl.ast.model.entity.ParserOutput
|
||||
import io.smnp.dsl.ast.model.node.AccessOperatorNode
|
||||
import io.smnp.dsl.ast.model.node.MinusOperatorNode
|
||||
import io.smnp.dsl.token.model.entity.TokenList
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
class UnitParser : Parser() {
|
||||
override fun tryToParse(input: TokenList): ParserOutput {
|
||||
val minusOperatorParser = allOf(
|
||||
terminal(TokenType.MINUS),
|
||||
assert(AtomParser(), "expression")
|
||||
) { (minusToken, expression) -> MinusOperatorNode(minusToken, expression) }
|
||||
|
||||
val atom2 = oneOf(
|
||||
minusOperatorParser,
|
||||
AtomParser()
|
||||
)
|
||||
|
||||
return leftAssociativeOperator(
|
||||
atom2,
|
||||
listOf(TokenType.DOT),
|
||||
assert(atom2, "property or method call")
|
||||
) { lhs, operator, rhs -> AccessOperatorNode(lhs, operator, rhs) }.parse(input)
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.smnp.dsl.token.model.entity
|
||||
|
||||
import io.smnp.dsl.token.model.enumeration.TokenType
|
||||
|
||||
data class Token(val type: TokenType, val value: Any, val rawValue: String, val position: TokenPosition) {
|
||||
constructor(type: TokenType, value: String, position: TokenPosition): this(type, value, value, position)
|
||||
|
||||
fun mapValue(mapper: (Any) -> Any): Token {
|
||||
return Token(type, mapper(value), rawValue, position)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val NONE = Token(TokenType.NONE, "", TokenPosition.NONE)
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "($type, »$rawValue«, $position)"
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package io.smnp.dsl.token.model.entity
|
||||
|
||||
class TokenList(val tokens: List<Token>, val lines: List<String>) {
|
||||
private var cursor = 0
|
||||
private var snap = 0
|
||||
|
||||
operator fun get(index: Int): Token {
|
||||
return tokens[index]
|
||||
}
|
||||
|
||||
val current: Token
|
||||
get() {
|
||||
if (!hasCurrent()) {
|
||||
throw RuntimeException("Cursor points to not existing token! Cursor = ${cursor}, length = ${tokens.size}")
|
||||
}
|
||||
|
||||
return tokens[cursor]
|
||||
}
|
||||
|
||||
fun currentPos(): TokenPosition {
|
||||
return current.position
|
||||
}
|
||||
|
||||
fun hasCurrent(): Boolean {
|
||||
return cursor < tokens.size
|
||||
}
|
||||
|
||||
fun hasMore(count: Int = 1): Boolean {
|
||||
return cursor + count < tokens.size
|
||||
}
|
||||
|
||||
fun next(number: Int = 1): Token {
|
||||
return tokens[cursor + number]
|
||||
}
|
||||
|
||||
fun prev(number: Int = 1): Token {
|
||||
return tokens[cursor - number]
|
||||
}
|
||||
|
||||
fun ahead() {
|
||||
cursor += 1
|
||||
}
|
||||
|
||||
fun snapshot(): Int {
|
||||
return cursor
|
||||
}
|
||||
|
||||
fun restore(snapshot: Int) {
|
||||
cursor = snapshot
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
cursor = 0
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
val currentStr = if(hasCurrent()) "current: ${cursor} -> ${current}" else "<all tokens consumed>"
|
||||
return "size: ${tokens.size}\n${currentStr}\nall: ${tokens}"
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user