Способ использования нескольких парсеров в одном: это безопасный код? - PullRequest
2 голосов
/ 16 ноября 2011

У меня есть приложение, которое использует XML-файл конфигурации, где я описываю макеты для компонентов. На данный момент у меня есть 3 макета: сетка, горизонтальная и вертикальная. Я хочу создать макет, который будет использовать эти три.

Наконец, я нашел способ сделать это: для каждого класса макета я определяю защищенное поле, защищенное пакетом этого класса макета, и инициализирую их в объявлении. Мое общее правило использует эти поля. Единственное, что нужно помнить, это то, что все они имеют свои собственные стеки, что не является проблемой, потому что вы можете вызвать такой код: push(gridLayoutParser.pop()).

Вот пример использования разных парсеров в одном:

Первый дочерний парсер:

 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 ")
        );
    }
}

Второй тоже самое:

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 ")
        );
    }
}

А вот парсер, который использует их оба:

открытый класс OP расширяет 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())
                            )
                    )

            )
    );
}

}

У меня все работает нормально. Но хорошо ли это для более сложных грамматик?

Ответы [ 2 ]

1 голос
/ 18 ноября 2011

Ответ дал пропаренный автор Матиас.

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

В общем, даже возможно использовать общий контекст (и вы не используете push (p1.pop ())), если переопределите метод setContext () следующим образом:

    public void setContext(Context<V> context) { 
       P1.setContext(context); 
       P2.setContext(context);
       super.setContext(context); 
    } 
0 голосов
/ 04 октября 2013

Да, если синтаксические анализаторы выдают значения одинакового типа, проблем вообще не возникает.

Даже если тип производимых значений различается, этот подход будет работать, но вам нужно будет пройти через несколько циклов для преобразования или приведения результирующих значений, но это, безусловно, возможно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...