Неоднозначная грамматика с Lemon Parser Generator

Итак, в основном я хочу проанализировать структуру CSS-кода в PHP, используя лексер/парсер, сгенерированный пакетами PEAR PHP_LexerGenerator и PHP_ParserGenerator. Моя цель - разобрать файлы следующим образом:

selector, selector2 {
    prop: value;
    prop2 /*comment */ :
       value;

    subselector {
        prop: value;
        subsub { prop: value; }
    }
}

Это все нормально, пока у меня нет псевдоклассов. Псевдоклассы позволяют добавлять : и имя CSS ([a-z][a-z0-9]*) к элементу, как в a.menu:visited. Будучи несколько ленивым, синтаксический анализатор не имеет списка допустимых псевдоклассов и принимает все за имя класса.

Моя грамматика (без учета всех особых случаев и пробелов) выглядит так:

document   ::= (<rule>)*

rule       ::= <selector> '{' (<content>)* '}'

content    ::= <rule>
content    ::= <definition>

definition ::= <name> ':' <name> ';'

//             h1     .class.class2#id    :visited
<selector> ::= <name> (('.'|'#') <name>)* (':' <name>)?

Теперь, когда я пытаюсь проанализировать следующее

h1 {
    test:visited {
        simple: case;
    }
}

Анализатор жалуется, что ожидал, что за двойным двоеточием следует <name>. Поэтому он пытается прочитать simple: как <selector> (просто посмотрите на подсветку синтаксиса SO).

Это моя ошибка, что синтаксический анализатор не может отследить достаточно, чтобы попробовать правило <definition>? Или Лимон просто недостаточно силен, чтобы выразить это? Если да, то что я могу сделать, чтобы синтаксический анализатор работал с этой грамматикой?


person xrstf    schedule 10.10.2011    source источник
comment
Ваша грамматика не поддерживает нотацию select1, select2 { ... }. Нет правила, которое обрабатывает «список селекторов, разделенных запятыми».   -  person Jonathan Leffler    schedule 10.10.2011
comment
В вашем вопросе упоминается «двойное двоеточие», но в примерах нет «::» и нет ничего, что обрабатывает двойное двоеточие в грамматике.   -  person Jonathan Leffler    schedule 10.10.2011


Ответы (1)


Ваш вопрос касается PHP_ParserGenerator и PHP_LexerGenerator. Код генератора синтаксического анализатора помечен как «не поддерживается», что не сулит ничего плохого.

Синтаксис, который вы используете для грамматики, неприемлем для Lemon, поэтому вам нужно уточнить, почему вы считаете, что генератор синтаксического анализатора должен его принять. Вы упомянули проблему с «ожидалось, что <name> будет следовать за двойным двоеточием», но ни в вашей грамматике, ни в вашем образце ввода нет двойного двоеточия, что затрудняет вам помощь.

Я думаю, что эта грамматика Lemon эквивалентна той, которую вы показали:

document        ::= rule_list.
rule_list       ::= .
rule_list       ::= rule_list rule.
rule            ::= selector LBRACE content_list RBRACE.
content_list    ::= .
content_list    ::= content_list content.
content         ::= rule.
content         ::= definition.
definition      ::= NAME COLON NAME SEMICOLON.
selector        ::= NAME opt_dothashlist opt_colonname.
opt_dothashlist ::= .
opt_dothashlist ::= dot_or_hash NAME.
dot_or_hash     ::= DOT.
dot_or_hash     ::= HASH.
opt_colonname   ::= COLON NAME.

Однако, когда он скомпилирован, Lemon жалуется 1 parsing conflicts, и выходной файл показывает:

State 2:
          definition ::= NAME * COLON NAME SEMICOLON
          selector ::= NAME * opt_dothashlist opt_colonname
     (10) opt_dothashlist ::= *
          opt_dothashlist ::= * dot_or_hash NAME
          dot_or_hash ::= * DOT
          dot_or_hash ::= * HASH

                         COLON shift  10
                         COLON reduce 10  ** Parsing conflict **
                           DOT shift  13
                          HASH shift  12
               opt_dothashlist shift  5
                   dot_or_hash shift  7

Это означает, что он не уверен, что делать с двоеточием; это может быть часть «opt_colonname» «селектора» или часть «определения»:

name1:name4 : name2:name3 ;

Вы хотели разрешить такой синтаксис? Номинально, согласно грамматике, это должно быть допустимо, но

name1:name4;

также должно быть действительным. Я думаю, что для их устранения требуется 2 или 3 упреждающих токена (поэтому ваша грамматика не LALR (1), а LALR (3)).

В частности, просмотрите свое определение «селектора».

person Jonathan Leffler    schedule 10.10.2011