import lexer_example
@with_lexer(foo_lexer)
grammar foo_grammar {
    deps <- list*(pick(Dep(pick("+" name)) ";"))
    defs <- list*(pick(or(scope | var) ";"))
    @main_rule scope <- Scope(name "{" deps defs "}")
    var <- Var(id "=" name)
    id <- Id(@identifier)
    name <- or(Prefix(name "." id) | id)

}

@abstract class FooNode : Node {
}

class Dep : FooNode {
    @parse_field name : Name
}

@abstract class Name : FooNode {

    @export @abstract fun resolve (): FooNode

    @export @abstract fun suffix_symbol (): Symbol

    @abstract fun referenced_unit_or_error (or_error : Bool): AnalysisUnit

    @export fun referenced_unit (): AnalysisUnit =
    node.referenced_unit_or_error(false)
}

class Id : Name implements TokenNode {

    fun resolve (): FooNode = node.node_env().get_first(node)

    fun suffix_symbol (): Symbol = node.symbol
}

class Prefix : Name {
    @parse_field prefix : Name
    @parse_field suffix : Id

    fun resolve (): FooNode =
    node.prefix.resolve().children_env().get_first(node.suffix.symbol)

    fun suffix_symbol (): Symbol = node.suffix.symbol
}

class Scope : FooNode {
    @parse_field name : Name
    @parse_field deps : ASTList[Dep]
    @parse_field defs : ASTList[FooNode]

    fun initial_env (): LexicalEnv = match node.name {
        case p : Prefix => p.prefix.referenced_unit().root.children_env()
        case _ => node.children_env()
    }
}

class Var : FooNode {
    @parse_field name : Id
    @parse_field value : Name
}
