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

230 views Asked by At

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?

2

There are 2 answers

0
Askar Kalykov On BEST ANSWER

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); 
    } 
0
ChrisBlom On

Yes, as long as the parsers produce the same type of values there is no problem at all.

Even if the type of produced values differ this approach will work, but you will need to jump trough some hoops to convert or cast the resulting values, but is certainly possible.