Jison:为 AND 和 OR 生成具有多个子节点的 AST 节点
Jison: produce AST node with multiple children for AND and OR
我正在 JavaScript 中进行简单的 SQL 到 Mongo 查询条件生成。
我正在使用 Jison 来解析 SQL 的 where 子句。
以下语法 return 是一个二叉树形式的 AST,其中嵌套了 OR 和 AND。
我想要的是获得一个 AST,其中 OR 节点具有单个节点(平面树)中的所有术语。
/* lexical grammar */
/* */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
'AND' return 'AND'
'OR' return 'OR'
'NOT' return 'NOT'
'BETWEEN' return 'BETWEEN'
L?\"(\.|[^\"])*\" return 'STRING_LITERAL'
'(' return 'LPAREN'
')' return 'RPAREN'
'!=' return 'NEQ'
'>=' return 'GE'
'<=' return 'LE'
'=' return 'EQ'
'>' return 'GT'
'<' return 'LT'
'IN' return 'IN'
'NIN' return 'NIN'
'+' return 'PLUS'
'-' return 'MINUS'
',' return 'COMMA'
[_a-zA-Z][_\.a-zA-Z0-9]{0,30} return 'IDEN'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
%left OR
%left AND
%right NOT
%left NEQ EQ
%left GT LE LT GE
$left PLUS MINUS
%start start
%% /* language grammar */
start
: search_condition EOF
{return ;}
;
search_condition
: search_condition OR boolean_term
{$$ = {
'or': [ , ]
};
}
| boolean_term
;
boolean_term
: boolean_factor
| boolean_term AND boolean_factor
{$$ = {
'and': [ , ]
};
}
;
boolean_factor
: boolean_test
;
boolean_test
: boolean_primary
;
boolean_primary
: predicate
| LPAREN search_condition RPAREN
{$$ = }
;
predicate
: comparison_predicate
| in_predicate
| nin_predicate
| between_predicate
;
comparison_predicate
: IDEN comp_op value_expression
{$$ = {
var: ,
op: ,
val:
};
}
;
value_expression
: NUMBER
| STRING_LITERAL
;
comp_op
: EQ
| NEQ
| GT
| GE
| LT
| LE
;
in_predicate
: IDEN IN in_predicate_value
{$$ = {
in:
};
}
;
nin_predicate
: IDEN NIN in_predicate_value
{$$ = {
nin:
};
}
;
in_predicate_value
: LPAREN in_value_list RPAREN
{$$ = [];}
;
in_value_list
: in_value_list_element
{$$ = []; $$.push(); }
| in_value_list COMMA in_value_list_element
{.push(); $$ = ; }
;
in_value_list_element
: value_expression
{$$ = ;}
;
between_predicate
: IDEN BETWEEN value_expression AND value_expression
{$$ = {
between: {
from: ,
to:
}
};
}
;
当我解析以下内容时
var ast = parser.parse('a=1 OR b=2 OR c=3 OR d=4 ');
它returns
{
"or": [
{
"or": [
{
"or": [
{
"var": "a",
"op": "=",
"val": "1"
},
{
"var": "b",
"op": "=",
"val": "2"
}
]
},
{
"var": "c",
"op": "=",
"val": "3"
}
]
},
{
"var": "d",
"op": "=",
"val": "4"
}
]
}
但我想要它 return
{
"or": [
{
"var": "a",
"op": "=",
"val": "1"
},
{
"var": "b",
"op": "=",
"val": "2"
},
{
"var": "c",
"op": "=",
"val": "3"
},
{
"var": "d",
"op": "=",
"val": "4"
}
]
}
使用 Jison 可以吗?如果是这样,需要进行哪些更改?
你只需要修复这些动作。
首先,将search_condition
规则中的动作修改如下:
search_condition
: search_condition OR boolean_term
{ ['or'].push(); $$ = ; }
| boolean_term
{ $$ = { 'or': [ ] }; }
;
这可确保 search_condition
始终生成 or
节点,即使该节点仅包含一个元素。由于基础产生式创建了一个(单个)or
节点,因此递归产生式可以自由地附加到它。
如果你想摆脱退化的 or
节点(在 search_condition
不包含 OR
运算符的情况下),你可以在包装器中这样做(或者直接在start production):
start
: simplified_search_condition EOF
{ return ; }
;
simplified_search_condition
: search_condition EOF
{ $$ = ['or'].length == 1 ? ['or'] : ; }
;
我正在 JavaScript 中进行简单的 SQL 到 Mongo 查询条件生成。 我正在使用 Jison 来解析 SQL 的 where 子句。
以下语法 return 是一个二叉树形式的 AST,其中嵌套了 OR 和 AND。 我想要的是获得一个 AST,其中 OR 节点具有单个节点(平面树)中的所有术语。
/* lexical grammar */
/* */
%lex
%%
\s+ /* skip whitespace */
[0-9]+("."[0-9]+)?\b return 'NUMBER'
'AND' return 'AND'
'OR' return 'OR'
'NOT' return 'NOT'
'BETWEEN' return 'BETWEEN'
L?\"(\.|[^\"])*\" return 'STRING_LITERAL'
'(' return 'LPAREN'
')' return 'RPAREN'
'!=' return 'NEQ'
'>=' return 'GE'
'<=' return 'LE'
'=' return 'EQ'
'>' return 'GT'
'<' return 'LT'
'IN' return 'IN'
'NIN' return 'NIN'
'+' return 'PLUS'
'-' return 'MINUS'
',' return 'COMMA'
[_a-zA-Z][_\.a-zA-Z0-9]{0,30} return 'IDEN'
<<EOF>> return 'EOF'
. return 'INVALID'
/lex
%left OR
%left AND
%right NOT
%left NEQ EQ
%left GT LE LT GE
$left PLUS MINUS
%start start
%% /* language grammar */
start
: search_condition EOF
{return ;}
;
search_condition
: search_condition OR boolean_term
{$$ = {
'or': [ , ]
};
}
| boolean_term
;
boolean_term
: boolean_factor
| boolean_term AND boolean_factor
{$$ = {
'and': [ , ]
};
}
;
boolean_factor
: boolean_test
;
boolean_test
: boolean_primary
;
boolean_primary
: predicate
| LPAREN search_condition RPAREN
{$$ = }
;
predicate
: comparison_predicate
| in_predicate
| nin_predicate
| between_predicate
;
comparison_predicate
: IDEN comp_op value_expression
{$$ = {
var: ,
op: ,
val:
};
}
;
value_expression
: NUMBER
| STRING_LITERAL
;
comp_op
: EQ
| NEQ
| GT
| GE
| LT
| LE
;
in_predicate
: IDEN IN in_predicate_value
{$$ = {
in:
};
}
;
nin_predicate
: IDEN NIN in_predicate_value
{$$ = {
nin:
};
}
;
in_predicate_value
: LPAREN in_value_list RPAREN
{$$ = [];}
;
in_value_list
: in_value_list_element
{$$ = []; $$.push(); }
| in_value_list COMMA in_value_list_element
{.push(); $$ = ; }
;
in_value_list_element
: value_expression
{$$ = ;}
;
between_predicate
: IDEN BETWEEN value_expression AND value_expression
{$$ = {
between: {
from: ,
to:
}
};
}
;
当我解析以下内容时
var ast = parser.parse('a=1 OR b=2 OR c=3 OR d=4 ');
它returns
{
"or": [
{
"or": [
{
"or": [
{
"var": "a",
"op": "=",
"val": "1"
},
{
"var": "b",
"op": "=",
"val": "2"
}
]
},
{
"var": "c",
"op": "=",
"val": "3"
}
]
},
{
"var": "d",
"op": "=",
"val": "4"
}
]
}
但我想要它 return
{
"or": [
{
"var": "a",
"op": "=",
"val": "1"
},
{
"var": "b",
"op": "=",
"val": "2"
},
{
"var": "c",
"op": "=",
"val": "3"
},
{
"var": "d",
"op": "=",
"val": "4"
}
]
}
使用 Jison 可以吗?如果是这样,需要进行哪些更改?
你只需要修复这些动作。
首先,将search_condition
规则中的动作修改如下:
search_condition
: search_condition OR boolean_term
{ ['or'].push(); $$ = ; }
| boolean_term
{ $$ = { 'or': [ ] }; }
;
这可确保 search_condition
始终生成 or
节点,即使该节点仅包含一个元素。由于基础产生式创建了一个(单个)or
节点,因此递归产生式可以自由地附加到它。
如果你想摆脱退化的 or
节点(在 search_condition
不包含 OR
运算符的情况下),你可以在包装器中这样做(或者直接在start production):
start
: simplified_search_condition EOF
{ return ; }
;
simplified_search_condition
: search_condition EOF
{ $$ = ['or'].length == 1 ? ['or'] : ; }
;