All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.agl.syntaxAnalyser.SyntaxAnalyserSimpleStreamPushAbstract.kt Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2023 Dr. David H. Akehurst (http://dr.david.h.akehurst.net)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *          http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package net.akehurst.language.agl.syntaxAnalyser

import net.akehurst.language.agl.api.runtime.Rule
import net.akehurst.language.agl.collections.toSeparatedList
import net.akehurst.language.agl.runtime.structure.RulePosition
import net.akehurst.language.agl.runtime.structure.RuntimeRule
import net.akehurst.language.agl.runtime.structure.RuntimeRuleRhsEmbedded
import net.akehurst.language.agl.runtime.structure.RuntimeRuleRhsListSeparated
import net.akehurst.language.agl.sppt.TreeDataComplete
import net.akehurst.language.agl.util.Debug
import net.akehurst.language.api.analyser.ScopeModel
import net.akehurst.language.api.asm.AsmElementPath
import net.akehurst.language.api.asm.AsmElementSimple
import net.akehurst.language.api.grammar.GrammarItem
import net.akehurst.language.api.grammarTypeModel.GrammarTypeNamespace
import net.akehurst.language.api.processor.LanguageIssue
import net.akehurst.language.api.processor.SentenceContext
import net.akehurst.language.api.sppt.Sentence
import net.akehurst.language.api.sppt.SpptDataNode
import net.akehurst.language.api.sppt.SpptDataNodeInfo
import net.akehurst.language.api.sppt.SpptWalker
import net.akehurst.language.collections.mutableStackOf
import net.akehurst.language.typemodel.api.*
import net.akehurst.language.typemodel.simple.SimpleTypeModelStdLib

abstract class SyntaxAnalyserSimpleStreamPushAbstract(
    val grammarNamespaceQualifiedName: String,
    val typeModel: TypeModel,
    val scopeModel: ScopeModel
) : SyntaxAnalyserFromTreeDataAbstract() {

    companion object {
        private const val ns = "net.akehurst.language.agl.syntaxAnalyser"
        const val CONFIGURATION_KEY_AGL_SCOPE_MODEL = "$ns.scope.model"

        val PropertyDeclaration.isTheSingleProperty get() = this.owner.property.size == 1

        val Rule.hasOnyOneRhsItem get() = this.rhsItems.size == 1 && this.rhsItems[0].size == 1
    }

    abstract fun startAsm()
    abstract fun finishAsm()

    abstract fun primitive(type: PrimitiveType, value: String?)

    abstract fun startList()
    abstract fun finishList()

    abstract fun startListSeparated()
    abstract fun finishListSeparated()

    abstract fun listElement()

    abstract fun startAsmElement(path: AsmElementPath, type: DataType)
    abstract fun finishAsmElement(path: AsmElementPath, type: DataType)

    abstract fun startTuple()
    abstract fun finishTuple(path: AsmElementPath)

    abstract fun startProperty(declaration: PropertyDeclaration, isRef: Boolean)
    abstract fun finishProperty(declaration: PropertyDeclaration, isRef: Boolean)

    private fun findTypeUsageForRule(ruleName: String): TypeInstance? {
        val ns = this.typeModel.namespace[grammarNamespaceQualifiedName] as GrammarTypeNamespace?
        return ns?.findTypeUsageForRule(ruleName)
    }

    override fun clear() {
        super.clear()
    }

    override fun configure(configurationContext: SentenceContext, configuration: Map): List {
        return emptyList()
    }

    override fun walkTree(sentence: Sentence, treeData: TreeDataComplete, skipDataAsTree: Boolean) {
        val syntaxAnalyserStack = mutableStackOf(this)
        val downStack = mutableStackOf() //when null don't use branch
        val stack = mutableStackOf()
        val walker = object : SpptWalker {
            override fun beginTree() {
                syntaxAnalyserStack.peek().startAsm()
            }

            override fun endTree() {
                syntaxAnalyserStack.peek().finishAsm()
            }

            override fun leaf(nodeInfo: SpptDataNodeInfo) {
                val type = SimpleTypeModelStdLib.String.type as PrimitiveType
                syntaxAnalyserStack.peek().createPrimitiveValue(sentence, type, nodeInfo)
                stack.push(ChildData(nodeInfo, null))
            }

            override fun beginBranch(nodeInfo: SpptDataNodeInfo) {
                val parentDownData = downStack.peekOrNull()
                val p = when {
                    downStack.isEmpty -> AsmElementPath.ROOT
                    null == parentDownData -> AsmElementPath.ROOT.plus("")  // property unused
                    else -> syntaxAnalyserStack.peek().pathFor(parentDownData.path, parentDownData.typeUse.forChildren.type, nodeInfo)
                }
                val tu = when {
                    downStack.isEmpty -> {
                        val typeUse = syntaxAnalyserStack.peek().findTypeUsageForRule(nodeInfo.node.rule.tag)
                            ?: error("Type not found for ${nodeInfo.node.rule.tag}")
                        typeUse
                    }

                    else -> syntaxAnalyserStack.peek().typeForNode(parentDownData?.typeUse?.forChildren, nodeInfo)
                }
                val tuc = resolveCompressed(tu, nodeInfo)
                val dd = when {
                    tuc.forNode.type == typeModel.NothingType -> null //could test for NothingType instead of null when used
                    else -> DownData(p, tuc)
                }
                downStack.push(dd)
                when (tuc.forNode.type) {
                    is PrimitiveType -> Unit
                    is UnnamedSuperTypeType -> Unit
                    is CollectionType -> when (tuc.forNode.type) {
                        SimpleTypeModelStdLib.List -> startList()
                        SimpleTypeModelStdLib.ListSeparated -> startListSeparated()
                        else -> error("Should not happen")
                    }

                    is TupleType -> startTuple()
                    is DataType -> startAsmElement(p, tuc.forNode.type as DataType)
                    else -> when (tuc.forNode.type) {
                        typeModel.NothingType -> Unit
                        typeModel.AnyType -> Unit
                        else -> error("Shold not happen")
                    }
                }
            }

            override fun endBranch(nodeInfo: SpptDataNodeInfo) {
                val opt = nodeInfo.alt.option
                val numChildren = nodeInfo.numChildrenAlternatives[opt]!!
                val children = stack.pop(numChildren)
                val adjChildren = children.reversed()
                val downData = downStack.pop()
                val value = when {
                    null == downData -> null //branch not used for element property value, push null for correct num children on stack
                    //nodeInfo.node.rule.isOptional -> {
                    //TODO("this currently causes issues")
                    //    (children[0] as ChildData).value
                    //}

                    else -> syntaxAnalyserStack.peek().createValueFromBranch(sentence, downData, nodeInfo, adjChildren)
                }
                value?.let { locationMap[it] = sentence.locationFor(nodeInfo.node) }
                stack.push(ChildData(nodeInfo, value))
                // path = path.parent!!
            }

            override fun beginEmbedded(nodeInfo: SpptDataNodeInfo) {
                val embeddedRhs = (nodeInfo.node.rule as RuntimeRule).rhs as RuntimeRuleRhsEmbedded
                val embRuleName = embeddedRhs.embeddedStartRule.tag
                val embGrmName = embeddedRhs.embeddedRuntimeRuleSet.qualifiedName
                val embSyntaxAnalyser =
                    embeddedSyntaxAnalyser[embGrmName] as SyntaxAnalyserSimpleStreamPushAbstract?
                        ?: error("Embedded SyntaxAnalyser not found for '$embGrmName' in SyntaxAnalyser for '${grammarNamespaceQualifiedName}'")
                syntaxAnalyserStack.push(embSyntaxAnalyser)
                val parentDownData = downStack.peek()!!
                val p = syntaxAnalyserStack.peek().pathFor(parentDownData.path, parentDownData.typeUse.forChildren.type, nodeInfo)
                val tu = syntaxAnalyserStack.peek().findTypeUsageForRule(embRuleName)
                    ?: error("Type not found for $embRuleName")
                val tuc = resolveCompressed(tu, nodeInfo)
                val dd = when {
                    tuc.forNode.type == typeModel.NothingType -> null //could test for NothingType instead of null when used
                    else -> DownData(p, tuc)
                }
                downStack.push(dd)
            }

            override fun endEmbedded(nodeInfo: SpptDataNodeInfo) {
                val embSyntaxAnalyser = syntaxAnalyserStack.pop()
                //value?.let { locationMap[it] = nodeInfo.node.locationIn(sentence) }
                stack.push(ChildData(nodeInfo, null))
            }

            override fun skip(startPosition: Int, nextInputPosition: Int) {
                // do nothing
            }

            override fun error(msg: String, path: () -> List) {
                TODO("not implemented")
            }

        }
        treeData.traverseTreeDepthFirst(walker, false)
    }

    private fun pathFor(parentPath: AsmElementPath, parentType: TypeDefinition, nodeInfo: SpptDataNodeInfo): AsmElementPath {
        return when (parentType) {
            is PrimitiveType -> parentPath
            is UnnamedSuperTypeType -> parentPath
            is CollectionType -> parentPath.plus(nodeInfo.child.index.toString())
            is TupleType -> {
                val prop = parentType.getPropertyByIndex(nodeInfo.child.propertyIndex)
                prop?.let { parentPath.plus(prop.name) } ?: parentPath.plus("")
            }

            is DataType -> {
                when {
                    parentType.subtypes.isNotEmpty() -> parentPath
                    else -> {
                        val prop = parentType.getPropertyByIndex(nodeInfo.child.propertyIndex)
                        prop?.let { parentPath.plus(prop.name) } ?: parentPath.plus("")
                    }
                }
            }

            else -> when (parentType) {
                typeModel.NothingType -> parentPath.plus("")
                typeModel.AnyType -> TODO()
                else -> error("Shold not happen")
            }
        }
    }

    private fun typeForNode(parentTypeUsage: TypeInstance?, nodeInfo: SpptDataNodeInfo): TypeInstance {
        return when {
            null == parentTypeUsage -> typeModel.NothingType.instance() // property unused
            parentTypeUsage.isNullable -> typeForParentOptional(parentTypeUsage, nodeInfo)
            nodeInfo.node.rule.isEmbedded -> typeForEmbedded(parentTypeUsage, nodeInfo)
            else -> {
                val parentType = parentTypeUsage.type
                when (parentType) {
                    is PrimitiveType -> parentTypeUsage
                    is UnnamedSuperTypeType -> typeForParentUnnamedSuperType(parentTypeUsage, nodeInfo)
                    is CollectionType -> when (parentType) {
                        SimpleTypeModelStdLib.List -> typeForParentListSimple(parentTypeUsage, nodeInfo)
                        SimpleTypeModelStdLib.ListSeparated -> typeForParentListSeparated(parentTypeUsage, nodeInfo)
                        else -> error("Should not happen")
                    }

                    is TupleType -> typeForParentTuple(parentType, nodeInfo)
                    is DataType -> typeForParentElement(parentType, nodeInfo)
                    else -> when (parentType) {
                        typeModel.NothingType -> typeModel.NothingType.instance()
                        typeModel.AnyType -> TODO()
                        else -> error("Shold not happen")
                    }
                }
            }
        }
    }

    private fun typeForParentOptional(parentTypeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        // nodes map to runtime-rules, not user-rules
        // if user-rule only had one optional item, then runtime-rule is 'compressed, i.e. no pseudo rule for the option
        if (Debug.CHECK) check(parentTypeUsage.isNullable)
        return parentTypeUsage.notNullable()
    }

    private fun typeForEmbedded(parentTypeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        // need to skip over the embedded node and use type of its child
        if (Debug.CHECK) check(nodeInfo.node.rule.isEmbedded)
        val type = parentTypeUsage.type
        return when (type) {
            is DataType -> {
                val prop = type.getPropertyByIndex(nodeInfo.child.propertyIndex)
                prop?.typeInstance ?: typeModel.NothingType.instance()
            }

            else -> parentTypeUsage
        }
    }

    private fun typeForParentListSimple(parentTypeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        // nodes map to runtime-rules, not user-rules
        // if user-rule only had one list item, then runtime-rule is 'compressed, i.e. no pseudo rule for the list
        if (Debug.CHECK) check(parentTypeUsage.type == SimpleTypeModelStdLib.List)
        val itemTypeUse = parentTypeUsage.typeArguments[0]
        return itemTypeUse
    }

    private fun typeForParentListSeparated(parentTypeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        // nodes map to runtime-rules, not user-rules
        // if user-rule only had one slist item, then runtime-rule is 'compressed, i.e. no pseudo rule for the slist
        if (Debug.CHECK) check(parentTypeUsage.type == SimpleTypeModelStdLib.ListSeparated)
        val index = nodeInfo.child.index % 2
        val childTypeUse = parentTypeUsage.typeArguments[index]
        return childTypeUse
    }

    private fun typeForParentUnnamedSuperType(parentTypeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        if (Debug.CHECK) check(parentTypeUsage.isNullable)
        val tu = (parentTypeUsage.type as UnnamedSuperTypeType).subtypes[nodeInfo.parentAlt.option]
        return tu
    }

    private fun typeForParentTuple(parentType: TupleType, nodeInfo: SpptDataNodeInfo): TypeInstance {
        val prop = parentType.getPropertyByIndex(nodeInfo.child.propertyIndex)
        return typeForProperty(prop, nodeInfo)
    }

    private fun typeForParentElement(parentType: DataType, nodeInfo: SpptDataNodeInfo): TypeInstance {
        return when {
            parentType.subtypes.isNotEmpty() -> {
                val t = parentType.subtypes[nodeInfo.parentAlt.option]
                return t
            }

            else -> {
                val prop = parentType.getPropertyByIndex(nodeInfo.child.propertyIndex)
                typeForProperty(prop, nodeInfo)
            }
        }
    }

    private fun resolveElementSubtype(typeUse: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        val type = typeUse.type
        return when {
            type is DataType && type.subtypes.isNotEmpty() -> {
                val t = type.subtypes[nodeInfo.alt.option]
                t
            }

            else -> typeUse
        }
    }

    private fun typeForProperty(prop: PropertyDeclaration?, nodeInfo: SpptDataNodeInfo): TypeInstance {
        return when {
            null == prop -> typeModel.NothingType.instance() // property unused
            prop.typeInstance.isNullable -> prop.typeInstance//typeForOptional(propTypeUse, nodeInfo)
            else -> {
                val propType = prop.typeInstance.type
                when (propType) {
                    is PrimitiveType -> (prop.typeInstance)
                    is UnnamedSuperTypeType -> {
                        val tu = resolveUnnamedSuperTypeSubtype(prop.typeInstance, nodeInfo)
                        when (tu.type) {
                            is TupleType -> (tu)
                            else -> (prop.typeInstance)
                        }
                        //NodeTypes(tu)
                        //NodeTypes(prop.typeUse)//typeForUnnamedSuperType(propTypeUse, nodeInfo)
                    }

                    is CollectionType -> (prop.typeInstance)
                    is TupleType -> (prop.typeInstance)
                    is DataType -> (prop.typeInstance)
                    else -> when (propType) {
                        typeModel.NothingType -> typeModel.NothingType.instance()
                        typeModel.AnyType -> TODO()
                        else -> error("Shold not happen")
                    }
                }
            }
        }
    }

    private fun resolveCompressed(typeUsage: TypeInstance, nodeInfo: SpptDataNodeInfo): NodeTypes {
        val type = typeUsage.type
        return when {
            type is StructuredType && nodeInfo.node.rule.isOptional && nodeInfo.node.rule.hasOnyOneRhsItem && nodeInfo.node.rule.rhsItems[0][0].isTerminal -> {
                NodeTypes(typeUsage, SimpleTypeModelStdLib.String)
            }

            type is DataType && type.property.size == 1 -> {
                // special cases where PT is compressed for lists (and optionals)
                when {
                    type.property.values.first().typeInstance.isNullable -> NodeTypes(typeUsage, type.property.values.first().typeInstance)
                    nodeInfo.node.rule.isOptional -> NodeTypes(typeUsage)
                    nodeInfo.node.rule.isList -> NodeTypes(typeUsage, type.property.values.first().typeInstance)
                    else -> NodeTypes(typeUsage)
                }
            }

            type is UnnamedSuperTypeType -> when {
                // special cases where PT is compressed for choice of concats
                nodeInfo.node.rule.isChoice -> when {
                    type.subtypes[nodeInfo.alt.option].type is TupleType -> NodeTypes(typeUsage, type.subtypes[nodeInfo.alt.option])
                    else -> NodeTypes(typeUsage)
                }

                else -> NodeTypes(typeUsage)
            }

            else -> NodeTypes(typeUsage)
        }
    }

    private fun resolveUnnamedSuperTypeSubtype(typeUse: TypeInstance, nodeInfo: SpptDataNodeInfo): TypeInstance {
        val type = typeUse.type
        return when {
            type is UnnamedSuperTypeType -> when {
                nodeInfo.node.rule.isChoice && type.subtypes.isNotEmpty() -> {
                    val t = type.subtypes[nodeInfo.alt.option]
                    t
                }

                else -> typeUse
            }

            else -> typeUse
        }
    }

    private fun createValueFromBranch(sentence: Sentence, downData: DownData, target: SpptDataNodeInfo, children: List): Any? {
        val targetType = findTypeUsageForRule(target.node.rule.tag)

        return when {
            downData.typeUse.forNode.isNullable && target.node.rule.isOptional -> {
                val child = children[0]
                when {
                    null == child.value -> null
                    else -> {
                        val nonOptChildren = listOf(ChildData(child.nodeInfo, child.value))
                        child.value
                    }
                }
            }

            target.node.rule.isEmbedded -> children[0].value
            else -> {
                val type = downData.typeUse.forNode.type
                when (type) {
                    is PrimitiveType -> {
                        createPrimitiveValue(sentence, SimpleTypeModelStdLib.String.type as PrimitiveType, target)
                    }

                    is UnnamedSuperTypeType -> {
                        val actualType = type.subtypes[target.alt.option].type
                        when (actualType) {
                            is TupleType -> createValueFor(sentence, actualType, downData.path, ChildData(target, children))
                            else -> children[0].value
                        }

                    }

                    is CollectionType -> when (type) {
                        SimpleTypeModelStdLib.List -> {
                            when {
                                null != targetType && targetType.type != SimpleTypeModelStdLib.List && targetType.type is DataType -> {
                                    finishList()
                                    val elType = targetType.type as DataType
                                    val propDecl = elType.property.values.first()
                                    setPropertyOrReferenceFromDeclaration(elType, propDecl)
                                    finishAsmElement(downData.path, elType)
                                }

                                else -> finishList()
                            }
                        }

                        SimpleTypeModelStdLib.ListSeparated -> {
                            when {
                                null != targetType && targetType.type != SimpleTypeModelStdLib.ListSeparated && targetType.type is DataType -> {
                                    finishListSeparated()
                                    val elType = targetType.type as DataType
                                    val propDecl = elType.property.values.first()
                                    setPropertyOrReferenceFromDeclaration(elType, propDecl)
                                    finishAsmElement(downData.path, elType)
                                }

                                else -> finishListSeparated()
                            }
                        }

                        else -> error("Should not happen")
                    }

                    is TupleType -> {
                        createTupleFrom(sentence, type, downData.path, ChildData(target, children))
                    }

                    is DataType -> {
                        if (type.subtypes.isNotEmpty()) {
                            // ???
                        } else {
                            for (propDecl in type.property.values) {
                                val propType = propDecl.typeInstance.type
                                when (propType) {
                                    is PrimitiveType -> {
                                        val childData = children[propDecl.index]
                                        createPrimitiveValue(sentence, SimpleTypeModelStdLib.String.type as PrimitiveType, childData.nodeInfo)
                                    }

                                    is CollectionType -> when (propType) {
                                        SimpleTypeModelStdLib.List -> {
                                            when {
                                                target.node.rule.isListSimple && target.node.option == RulePosition.OPTION_MULTI_EMPTY -> emptyList()
                                                target.node.rule.isList -> createList(target, children.map { it.value })
                                                else -> {
                                                    val childData = children[propDecl.index]
                                                    when {
                                                        childData.nodeInfo.node.rule.isList -> when {
                                                            null == childData.value -> emptyList()
                                                            childData.value is List<*> -> createList(childData.nodeInfo, childData.value as List)
                                                            childData.value is AsmElementSimple -> childData.value.properties.values.first().value as List
                                                            else -> listOf(childData.value)
                                                        }

                                                        else -> error("Internal Error: cannot create a ListSimple from '$childData'")
                                                    }
                                                }
                                            }
                                        }

                                        SimpleTypeModelStdLib.ListSeparated -> {
                                            val childData = children[propDecl.index]
                                            when {
                                                childData.nodeInfo.node.rule.isEmptyTerminal -> emptyList()
                                                target.node.rule.isList -> children.map { it.value }.toSeparatedList()
                                                childData.nodeInfo.node.rule.isList -> when {
                                                    childData.value is List<*> -> childData.value
                                                    childData.value is AsmElementSimple -> childData.value.properties.values.first().value as List
                                                    else -> TODO()
                                                }

                                                else -> error("Internal Error: cannot create a ListSeparated from '$childData'")
                                            }
                                        }

                                        else -> error("Should not happen")
                                    }

                                    else -> {
                                        //nothing to do
                                    }
                                }
                                setPropertyOrReferenceFromDeclaration(type, propDecl)
                            }
                            finishAsmElement(downData.path, type)
                        }
                    }

                    else -> when (type) {
                        typeModel.NothingType -> error("Internal Error: items should not have type 'NothingType'")
                        typeModel.AnyType -> {
                            TODO()
                            /*
                    val actualType = this.findTypeForRule(target.name) ?: error("Internal Error: cannot find actual type for ${target.name}")
                    when (actualType.type) {
                        is AnyType -> {// when {
                            //must be a choice in a group
                            val choice = _mapToGrammar(target.runtimeRuleSetNumber, target.runtimeRuleNumber) as Choice
                            when (choice.alternative.size) {
                                1 -> {
                                    val ch = target.children[0]
                                    val childType = this.findTypeForRule(ch.name) ?: error("Internal Error: cannot find type for ${ch.name}")
                                    val chPath = path
                                    //val childsScope = scope
                                    createValue(ch, chPath, childType)//, childsScope)
                                }

                                else -> {
                                    TODO()
                                }
                            }
                            //else -> error("Internal Error: cannot find actual type for ${target.name}")
                        }

                        else -> createValue(target, path, actualType)//, scope)
                    }
                     */
                        }

                        else -> error("Shold not happen")
                    }
                }
            }
        }
    }

    private fun createValueFor(sentence: Sentence, type: TypeDefinition, path: AsmElementPath, childData: ChildData): Any? = when (type) {
        is PrimitiveType -> createPrimitiveValue(sentence, SimpleTypeModelStdLib.String.type as PrimitiveType, childData.nodeInfo)
        is UnnamedSuperTypeType -> TODO()
        is CollectionType -> TODO()
        is TupleType -> createTupleFrom(sentence, type, path, childData)
        is DataType -> createElementFrom(sentence, type, path, childData.value as List)
        else -> when (type) {
            typeModel.NothingType -> TODO()
            typeModel.AnyType -> TODO()
            else -> error("Shold not happen")
        }
    }

    private fun createPrimitiveValue(sentence: Sentence, type: PrimitiveType, nodeInfo: SpptDataNodeInfo) {
        val text = when {
            nodeInfo.node.rule.isEmptyTerminal -> null
            else -> sentence.matchedTextNoSkip(nodeInfo.node)
        }
        primitive(type, text)
    }

    private fun createList(nodeData: SpptDataNodeInfo, list: List): List {
        return when {
            nodeData.node.rule.isListSimple -> list
            nodeData.node.rule.isListSeparated -> {
                val rhs = (nodeData.node.rule as RuntimeRule).rhs as RuntimeRuleRhsListSeparated
                when {
                    rhs.separatorRhsItem.isTerminal -> list.toSeparatedList().items
                    else -> list.toSeparatedList().separators
                }
            }

            else -> error("Internal error: List kind not handled")
        }
    }

    private fun createTupleFrom(sentence: Sentence, type: TupleType, path: AsmElementPath, childData: ChildData) {
        for (propDecl in type.property.values) {
            setPropertyOrReferenceFromDeclaration(type, propDecl)
        }
        finishTuple(path)
    }

    private fun createElementFrom(sentence: Sentence, type: DataType, path: AsmElementPath, children: List) {
        if (type.subtypes.isNotEmpty()) {
            if (Debug.CHECK) check(1 == children.size)
            children[0].value
        } else {
            for (propDecl in type.property.values) {
                val propPath = path + propDecl.name
                val propType = propDecl.typeInstance.type
                val childData = children[propDecl.index]
                when (propType) {
                    is PrimitiveType -> {
                        val text = when {
                            childData.nodeInfo.node.rule.isEmptyTerminal -> null
                            else -> sentence.matchedTextNoSkip(childData.nodeInfo.node)
                        }
                        primitive(propType, text)
                    }

                    is CollectionType -> finishList()

                    is TupleType -> createTupleFrom(sentence, propType, path, childData)

                    is UnnamedSuperTypeType -> {
                        val actualType = propType.subtypes[childData.nodeInfo.parentAlt.option].type
                        when (actualType) {
                            is TupleType -> createTupleFrom(sentence, actualType, path, childData)
                            else -> {
                                TODO()
                            }
                        }

                    }

                    else -> children[propDecl.index]
                }
                setPropertyOrReferenceFromDeclaration(type, propDecl)
            }
            finishAsmElement(path, type)
        }
    }

    private fun isReference(elType: StructuredType, name: String): Boolean {
        return scopeModel?.isReference(elType.name, name) ?: false
    }

    private fun setPropertyOrReferenceFromDeclaration(elType: StructuredType, declaration: PropertyDeclaration) {
        val isRef = this.isReference(elType, declaration.name)
        finishProperty(declaration, isRef)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy