Search code examples
javaparboiled

A way of using multiple parsers in one: is this a safe code?


I have an application that uses xml config file, where I'm describing layouts for components. Currently I have 3 layouts: grid, horizontal and vertical. I want to create a layout which will use those three.

Finally I found a way to do this: for each of the layout class I define a protected package-protected field of that layout class a initialize them in declaration. My general rule uses those fields. The only thing to remember is that they all have their own stacks, which is not a problem, because you can call a code like this: push(gridLayoutParser.pop()).

Here is the example of usage of different parsers in one:

First child parser:

 public static class P1 extends BaseParser<String> {
    public Rule FullContent() {
        return Sequence(Content(), EOI);
    }

    public Rule Content() {
        return Sequence(
                push(""),
                String("STRING1"),
                swap() && push(pop() + " fromParser1 "),
                String(" SOMESTRING1 ")
        );
    }
}

The second is the same:

public static class P2 extends BaseParser<String> {
    public Rule FullContent() {
        return Sequence(Content(), EOI);
    }

    public Rule Content() {
        return Sequence(
                push(""),
                String("STRING2"),
                swap() && push(pop() + " fromParser2 "),
                String(" SOMESTRING2 ")
        );
    }
}

And here the parser that uses both of them:

public class OP extends BaseParser {

protected P1 bool1 = Parboiled.createParser(P1.class);
protected P2 bool2 = Parboiled.createParser(P2.class);

public Rule FullContent() {
    return Sequence(
            push(""),
            OneOrMore(
                    FirstOf(
                            Sequence(
                                    bool1.Content(),
                                    swap() && push(pop() + bool1.pop())
                                    ),
                            Sequence(
                                    bool2.Content(),
                                    swap() && push(pop() + bool2.pop())
                            )
                    )

            )
    );
}

}

For me it works fine. But will it be fine for more complex grammars?


Solution

  • Answer was given by Parboiled author, Mathias.

    http://users.parboiled.org/A-way-of-using-multiple-parsers-in-one-is-this-a-safe-code-td3512129.html#a3518992

    In general, it's even possible to use shared context (and you don't have use push(p1.pop())) if you override method setContext() in this way:

        public void setContext(Context<V> context) { 
           P1.setContext(context); 
           P2.setContext(context);
           super.setContext(context); 
        }