2

したがって、基本的には、PEAR パッケージ PHP_LexerGenerator および PHP_ParserGenerator によって生成されたレクサー/パーサーを使用して、PHP で構造 CSS コードを解析したいと考えています。私の目標は、次のようなファイルを解析することです。

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>パーサーは、二重コロンの後に a が続くことを期待していると不平を言います。そのため、 を として読み取ろうとしますsimple:( <selector>SO の構文強調表示を見てください)。

<definition>パーサーがルールを試すのに十分なバックトレースができないのは私のエラーですか? それとも、レモンはこれを表現するのに十分なほど強力ではありませんか? もしそうなら、パーサーがこの文法で動作するようにするにはどうすればよいですか?

4

1 に答える 1

3

あなたの質問はPHP_ParserGeneratorPHP_LexerGeneratorについて尋ねます。パーサジェネレータコードは「維持されていません」とマークされており、これは悪い兆候です。

文法に使用している構文はLemonには受け入れられないため、パーサジェネレータがそれを受け入れる必要があると考える理由を明確にする必要があります。'が二重コロンの後に続くと予想される問題について言及しました<name>が、文法もサンプル入力にも二重コロンがないため、役に立ちません。

このレモンの文法は、あなたが示したものと同等だと思います。

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)です)。

特に「セレクター」の定義を確認してください。

于 2011-10-10T04:25:44.597 に答える