2016-05-06 11 views
3

私は例外的にjisonの新機能であり、有用なクエリーパーサーをまとめて管理しています。私は今==」のような文字列ながら再帰的ブール値および/またはjisonパーザーを配列する

{and: [ 
    {a: {eq: 1}}, 
    {b: {eq: 1}}, 
    {c: {eq: 2}} 
]} 

のようにオブジェクトに「== 1とB == 1とC == 1」のような文字列を解析できるパーサを作成しようとしています

%lex 

%% 
\s+  /*skip whitespace*/ 
\"(\\.|[^"])*\"   yytext = yytext.substr(1, yyleng-2); return 'STRING'; 
"=="      return '=='; 
and[^\w]     return 'and'; 
or[^\w]     return 'or'; 
[0-9]+(?:\.[0-9]+)?\b return 'NUMBER'; 
[a-zA-Z][\.a-zA-Z0-9_]* return 'SYMBOL'; 
<<EOF>>     return 'EOF'; 

/lex 

%left 'or' 
%left 'and' 
%left '==' 

%start expressions 

%% 

expressions 
    : e EOF 
    {$$ = $1;} 
    ; 

e 
    : property '==' value 
    { $$ = {}; $[$1] = {eq: $3}; } 
    | boolAnd 
    { $$ = {and: $1}} 
    | boolOr 
    { $$ = {or: $1}} 
    ; 

boolAnd 
    : boolAnd 'and' e 
    {$$ = $1; $1.push($3);} 
    | e 'and' e 
    {$$ = [$1, $3];} 
    ; 

boolOr 
    : boolOr 'or' e 
    {$$ = $1; $1.push($3);} 
    | e 'or' e 
    {$$ = [$1, $3];} 
    ; 

property 
    : SYMBOL 
    {$$ = $1;} 
    ; 

value 
    : NUMBER 
    {$$ = Number(yytext);} 
    | STRING 
    {$$ = yytext; } 
    ; 

をし、それは以下の競合エラーを私に与えます:1またはb == 1とC == 1" は

{or: [ 
    {a: {eq: 1}}, 
    {and: [ 
    {b: {eq: 1}}, 
    {c: {eq: 1}} 
    ]} 
]} 

私の文法はこれまでのところ、このようになりますようにオブジェクトに解析する必要があります

Conflict in grammar: multiple actions possible when lookahead token is and in state 4 
- reduce by rule: e -> boolAnd 
- shift token (then go to state 11) 
Conflict in grammar: multiple actions possible when lookahead token is or in state 5 
- reduce by rule: e -> boolOr 
- shift token (then go to state 12) 

States with conflicts: 
State 4 
    e -> boolAnd . #lookaheads= EOF and or 
    boolAnd -> boolAnd .and e #lookaheads= EOF and or 
State 5 
    e -> boolOr . #lookaheads= EOF and or 
    boolOr -> boolOr .or e #lookaheads= EOF or and 

私が間違っていることについて誰でも提案できますか? jisonが文句を言っているものである

boolAnd: e 'and' e 
     | boolAnd 'and' e 

:間で決定することは不可能である

e : boolAnd 

ので感謝

答えて

1

。 (ITとはeからboolAndの減少は、あなたが望むものではないようであることは注目に値しますそれは本当に型エラーだ、またはJSは種類があった場合になります。)個人的に

、私はちょうど二分木を使うだろう。私の経験では、彼らは仕事がより簡単になることが分かりました。単一の非終端宣言と優先順位宣言で簡単に行うことができます。

%left 'or' 
%left 'and' 
%% 
e 
    : property '==' value 
    { $$ = {eq: [$1, $3]}; /* This seems better to me. YMMV. } 
    | e 'and' e 
    { $$ = {and: [$1, $3]}} 
    | e 'or' e 
    { $$ = {or: [$1, $3]}} 
    | '(' e ')' 
    { $$ = $2 /* You didn't have this one, but it seems useful */ } 
    ; 

それは可変引数演算子を処理する文法を作ることが可能である(すなわち。{OP: [x, y, z]}からx OP y OP zを減らす)が、それは右のそれを得るために、実際の仕事のかなりのだし、それはベースのソリューションに簡単に得られません優先順位の宣言を行います。ブール演算子では不要なx OP y OP zx OP (y OP z)の区別が本当に必要な場合を除き、2番目のパスのパースツリーで複数の同様の2項演算子を折りたたむことは、通常は簡単であり、より一般的です。子式の演算子の型を調べることにより、

+0

これは役に立ちました。私は同じオペレータを崩壊させるために木を二度目に渡ることを考えなかった。私はバイナリブール演算子配列を平坦化した再帰を書き終えました。うまく動作します。私はあなたの警告を与えられたようなもののためにどのようなフレックスがあるのだろうかと不思議に思います。本当にありがとう! – jonotron

関連する問題