Javascript 递归布尔和/或到数组jison解析器

Javascript 递归布尔和/或到数组jison解析器,javascript,parsing,jison,Javascript,Parsing,Jison,我对jison非常陌生,并且已经设法拼凑出一个有用的查询解析器。我现在尝试创建一个解析器,它可以将“a==1、b==1和c==1”这样的字符串解析为 {and: [ {a: {eq: 1}}, {b: {eq: 1}}, {c: {eq: 2}} ]} {or: [ {a: {eq: 1}}, {and: [ {b: {eq: 1}}, {c: {eq: 1}} ]} ]} 而像“a==1或b==1和c==1”这样的字符串应该解析为 {and: [

我对jison非常陌生,并且已经设法拼凑出一个有用的查询解析器。我现在尝试创建一个解析器,它可以将“a==1、b==1和c==1”这样的字符串解析为

{and: [
  {a: {eq: 1}},
  {b: {eq: 1}},
  {c: {eq: 2}}
]}
{or: [
  {a: {eq: 1}},
  {and: [
    {b: {eq: 1}},
    {c: {eq: 1}}
  ]}
]}
而像“a==1或b==1和c==1”这样的字符串应该解析为

{and: [
  {a: {eq: 1}},
  {b: {eq: 1}},
  {c: {eq: 2}}
]}
{or: [
  {a: {eq: 1}},
  {and: [
    {b: {eq: 1}},
    {c: {eq: 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; }
  ;
有人能就我做错了什么提出建议吗?非常感谢

e : boolAnd
不可能在以下两者之间作出决定:

boolAnd: e 'and' e
       | boolAnd 'and' e
这正是jison所抱怨的。(值得注意的是,将
boolAnd
减少到
e
似乎并不是您想要的。这实际上是一个类型错误,或者如果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 */ }
  ;

可以制作一个处理可变运算符的语法(即,将
xopyopz
简化为
{OP:[x,y,z]}
),但要正确处理它实际上需要相当多的工作,而且它不容易产生基于优先级声明的解决方案。除非您真的想区分
x OP y OP z
x OP(y OP z)
,这在布尔运算符的情况下是不必要的,否则在第二次遍历解析树时折叠多个类似的二元运算符,或者在创建二元节点时直接折叠多个类似的二元运算符通常更容易、更一般,通过检查子表达式的运算符类型。

这很有帮助。我没有考虑过第二次通过这棵树来折叠同一个操作符。最后,我编写了一个递归,将我的二进制布尔运算符数组展平,效果很好。尽管我很好奇,考虑到你的警告,这种东西的弹性会是什么。非常感谢!