import lexer_example
@with_lexer(foo_lexer)
grammar foo_grammar {
    @main_rule main_rule <- list+(pick(decl ";"))
    decl <- or(
        | VarDecl("def" name "=" expr)
        | FuncDecl(
            "def" name "(" list+(name, ",") ")" "=" expr
        )
    )
    expr <- or(Plus(atom "+" expr) | atom)
    atom <- or(Literal(@number) | name)
    name <- Name(@identifier)

}

enum DeclKind {
    case func, var, none
}

@abstract class FooNode : Node {
}

@abstract class Decl : FooNode {

    @export @abstract fun decl_kind (): DeclKind

    @export fun with_kind (): DeclAndKind =
    DeclAndKind(dcl=node, knd=node.decl_kind())
}

class FuncDecl : Decl {
    @parse_field name : Name
    @parse_field args : ASTList[Name]
    @parse_field expr : Expression

    fun decl_kind (): DeclKind = DeclKind.func
}

class VarDecl : Decl {
    @parse_field name : Name
    @parse_field expr : Expression

    fun decl_kind (): DeclKind = DeclKind.var
}

@abstract class Expression : FooNode {
}

class Literal : Expression implements TokenNode {
}

class Name : Expression implements TokenNode {
}

class Plus : Expression {
    @parse_field left : Expression
    @parse_field right : Expression
}

struct DeclAndKind {
    dcl : Decl
    knd : DeclKind
}
