h0tk3y/better-parse

Rules dependent on each other

Closed this issue · 2 comments

ksqsf commented

Is it possible to define the following grammar?

val singleton by lbrace cmd rbrace; // singleton -> cmd
val expr by number or funccall or ... or singleton; // expr -> singleton
val cmd by expr semicol; // cmd -> expr
// the dependency is a cycle: cmd -> expr -> singleton -> cmd

so that this grammar accepts

{ 1; }

as an expression. I can't write the grammar in the naive way, because Kotlin rejects this code complaining "Variable cmd must be initialized". I tried lazy but the properties seem to be NULL, not properly initialized.

edit: I added lazy to every parser but it ended up infinite recursion.

ksqsf commented
object NestedGrammar : Grammar<Int>() {
    val ws by regexToken("\\w+", ignore = true)
    val num by regexToken("[0-9]+")
    val lbrace by literalToken("{")
    val rbrace by literalToken("}")
    val semicol by literalToken(";")

    val number: Parser<Int> by num map { it.text.toInt() }
    val singleton: Parser<Int> by -lbrace * cmd * -rbrace
    val expr: Parser<Int> by number or singleton
    val cmd: Parser<Int> by expr * semicol map { it.t1 }
    override val rootParser by cmd
}

fun main() {
    val text = "{ 1; };"
    NestedGrammar.parseToEnd(text)
}

This is a minimal reproducible example.

ksqsf commented

Solved by using parser