github.com/GuanceCloud/cliutils@v1.1.21/filter/gram.y (about)

     1  %{
     2  package filter
     3  
     4  import (
     5  	"time"
     6  )
     7  %}
     8  
     9  %union {
    10  	node       Node
    11  	nodes      []Node
    12  
    13  	item       Item
    14  
    15  	strings    []string
    16  	float      float64
    17  	duration   time.Duration
    18  	timestamp  time.Time
    19  }
    20  
    21  %token <item> EQ COLON SEMICOLON COMMA COMMENT DURATION
    22  	EOF ERROR ID LEFT_BRACE LEFT_BRACKET
    23  	LEFT_PAREN NUMBER RIGHT_BRACE RIGHT_BRACKET
    24  	RIGHT_PAREN SPACE STRING QUOTED_STRING NAMESPACE
    25  	DOT
    26  
    27  // operator
    28  %token operatorsStart
    29  %token <item> ADD
    30  	DIV GTE GT
    31  	LT LTE MOD MUL
    32  	NEQ POW SUB
    33  %token operatorsEnd
    34  
    35  // keywords
    36  %token keywordsStart
    37  %token <item>
    38  AS ASC AUTO BY
    39  MATCH NOT_MATCH
    40  DESC TRUE FALSE FILTER
    41  IDENTIFIER IN NOT_IN AND LINK LIMIT SLIMIT
    42  OR NIL NULL OFFSET SOFFSET
    43  ORDER RE INT FLOAT POINT TIMEZONE WITH
    44  %token keywordsEnd
    45  
    46  // start symbols for parser
    47  %token startSymbolsStart
    48  %token START_STMTS START_BINARY_EXPRESSION START_FUNC_EXPRESSION START_WHERE_CONDITION
    49  %token startSymbolsEnd
    50  
    51  ////////////////////////////////////////////////////
    52  // grammar rules
    53  ////////////////////////////////////////////////////
    54  %type <item>
    55  	unary_op
    56  	function_name
    57  	identifier
    58  
    59  %type<nodes>
    60  	filter_list
    61  	function_args
    62  
    63  %type <node>
    64  	stmts
    65  	where_conditions
    66  	array_elem
    67  	array_list
    68  	attr_expr
    69  	binary_expr
    70  	expr
    71  	function_arg
    72  	function_expr
    73  	naming_arg
    74  	paren_expr
    75  	filter_elem
    76  	regex
    77  	columnref
    78  	bool_literal
    79  	string_literal
    80  	nil_literal
    81  	number_literal
    82  	cascade_functions
    83  	star
    84  
    85  %start start
    86  
    87  // operator listed with increasing precedence
    88  %left OR
    89  %left AND
    90  %left GTE GT NEQ EQ LTE LT
    91  %left ADD SUB
    92  %left MUL DIV MOD
    93  %right POW
    94  
    95  // `offset` do not have associativity
    96  %nonassoc OFFSET
    97  %right LEFT_BRACKET
    98  
    99  %%
   100  
   101  start: START_WHERE_CONDITION stmts
   102  		 {
   103  				yylex.(*parser).parseResult = $2
   104  		 }
   105  		 | start EOF
   106  		 | error
   107  		 {
   108  				yylex.(*parser).unexpected("", "")
   109  		 }
   110  		 ;
   111  
   112  stmts: where_conditions
   113  		 {
   114  		 $$ = WhereConditions{$1}
   115  		 }
   116  		 | stmts SEMICOLON where_conditions
   117  		 {
   118  			 if $3 != nil {
   119  				arr := $1.(WhereConditions)
   120  				arr = append(arr, $3)
   121  				$$ = arr
   122  			 } else {
   123  			 	$$ = $1
   124  			 }
   125  		 }
   126  		 ;
   127  
   128  /* expression */
   129  expr: array_elem | regex | paren_expr | function_expr | binary_expr | cascade_functions
   130  		;
   131  
   132  columnref: identifier
   133  				 {
   134  				   $$ = &Identifier{Name: $1.Val}
   135  				 }
   136  				 | attr_expr
   137  				 {
   138  					 $$ = $1
   139  				 }
   140  				 ;
   141  
   142  attr_expr: identifier DOT identifier
   143  				 {
   144  				 	 $$ = &AttrExpr{
   145  					 	 Obj: &Identifier{Name: $1.Val},
   146  					 	 Attr: &Identifier{Name: $3.Val},
   147  					 }
   148  				 }
   149  				 | attr_expr DOT identifier
   150  				 {
   151  				 	 $$ = &AttrExpr{
   152  						 Obj: $1.(*AttrExpr),
   153  						 Attr: &Identifier{Name: $3.Val},
   154  					 }
   155  				 }
   156  				 ;
   157  
   158  unary_op: ADD
   159  				| SUB
   160  				;
   161  
   162  string_literal: STRING
   163  							{
   164  							  $$ = &StringLiteral{Val: yylex.(*parser).unquoteString($1.Val)}
   165  							}
   166  							;
   167  
   168  nil_literal: NIL
   169  					 {
   170  					 	 $$ = &NilLiteral{}
   171  					 }
   172  					 | NULL
   173  					 {
   174  					 	 $$ = &NilLiteral{}
   175  					 }
   176  					 ;
   177  
   178  bool_literal: TRUE
   179  						{
   180  							$$ = &BoolLiteral{Val: true}
   181  						}
   182  						| FALSE
   183  						{
   184  							$$ = &BoolLiteral{Val: false}
   185  						}
   186  						;
   187  
   188  paren_expr: LEFT_PAREN expr RIGHT_PAREN
   189  					{
   190  						$$ = &ParenExpr{Param: $2}
   191  					}
   192  					;
   193  
   194  function_expr: function_name LEFT_PAREN function_args RIGHT_PAREN
   195  							{
   196  								$$ = yylex.(*parser).newFunc($1.Val, $3)
   197  							}
   198  							;
   199  
   200  cascade_functions: function_expr DOT function_expr
   201  								 {
   202  								 	$$ = &CascadeFunctions{Funcs: []*FuncExpr{$1.(*FuncExpr), $3.(*FuncExpr)}}
   203  								 }
   204  								 | cascade_functions DOT function_expr
   205  								 {
   206  								 	fc := $1.(*CascadeFunctions)
   207  									fc.Funcs = append(fc.Funcs, $3.(*FuncExpr))
   208  									$$ = fc
   209  								 }
   210  								 ;
   211  
   212  function_args: function_args COMMA function_arg
   213  						 {
   214  						   $$ = append($$, $3)
   215  						 }
   216  						 | function_args COMMA
   217  						 | function_arg
   218  						 {
   219  						 	 $$ = []Node{$1}
   220  						 }
   221  						 | /* empty */
   222  						 {
   223  						 	 $$ = nil
   224  						 }
   225  						 ;
   226  
   227  array_list: array_list COMMA array_elem
   228  					{
   229  						nl := $$.(NodeList)
   230  						nl = append(nl, $3)
   231  						$$ = nl
   232  					}
   233  					| array_elem
   234  					{
   235  						$$ = NodeList{$1}
   236  					}
   237  					| /* empty */
   238  					{
   239  						$$ = NodeList{}
   240  					}
   241  					;
   242  
   243  array_elem: number_literal
   244  					| string_literal
   245  					| columnref
   246  					| nil_literal
   247  					| bool_literal
   248  					| star
   249  					;
   250  
   251  star : MUL
   252  		 {
   253  		 		$$ = &Star{}
   254  		 }
   255  		 ;
   256  
   257  function_arg: naming_arg
   258  						| expr
   259  						| LEFT_BRACKET array_list RIGHT_BRACKET
   260  						{
   261  							$$ = getFuncArgList($2.(NodeList))
   262  						}
   263  						;
   264  
   265  naming_arg: identifier EQ expr
   266  						{
   267  							$$ = &FuncArg{ArgName: $1.Val, ArgVal: $3}
   268  						}
   269  						| identifier EQ LEFT_BRACKET array_list RIGHT_BRACKET
   270  						{
   271  							$$ = &FuncArg{
   272  								ArgName: $1.Val,
   273  								ArgVal: getFuncArgList($4.(NodeList)),
   274  							}
   275  						}
   276  						;
   277  
   278  where_conditions: LEFT_BRACE filter_list RIGHT_BRACE
   279  						 {
   280  						   $$ = yylex.(*parser).newWhereConditions($2)
   281  						 }
   282  						 | /* empty */
   283  						 {
   284  						   $$ = nil
   285  						 }
   286  						 ;
   287  
   288  /* filter list */
   289  filter_list: filter_elem
   290  					 {
   291  					  	$$ = []Node{ $1 }
   292  					 }
   293  					 | filter_list COMMA filter_elem
   294  					 {
   295  					  	$$ = append($$, $3)
   296  					 }
   297  					 | filter_list COMMA
   298  					 | /* empty */
   299  					 { $$ = nil }
   300  					 ;
   301  
   302  filter_elem: binary_expr | paren_expr
   303  					;
   304  
   305  binary_expr: expr ADD expr
   306  					 {
   307  					   $$ = yylex.(*parser).newBinExpr($1, $3, $2)
   308  					 }
   309  					 | expr DIV expr
   310  					 {
   311  					   $$ = yylex.(*parser).newBinExpr($1, $3, $2)
   312  					 }
   313  					 | expr GTE expr
   314  					 {
   315  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   316  						 bexpr.ReturnBool = true
   317  						 $$ = bexpr
   318  					 }
   319  					 | expr GT expr
   320  					 {
   321  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   322  						 bexpr.ReturnBool = true
   323  						 $$ = bexpr
   324  					 }
   325  					 | expr AND expr
   326  					 {
   327  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   328  						 bexpr.ReturnBool = true
   329  						 $$ = bexpr
   330  					 }
   331  					 | expr OR expr
   332  					 {
   333  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   334  						 bexpr.ReturnBool = true
   335  						 $$ = bexpr
   336  					 }
   337  					 | expr LT expr
   338  					 {
   339  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   340  						 bexpr.ReturnBool = true
   341  						 $$ = bexpr
   342  					 }
   343  					 | expr LTE expr
   344  					 {
   345  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   346  						 bexpr.ReturnBool = true
   347  						 $$ = bexpr
   348  					 }
   349  					 | expr MOD expr
   350  					 {
   351  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   352  						 $$ = bexpr
   353  					 }
   354  					 | expr MUL expr
   355  					 {
   356  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   357  						 $$ = bexpr
   358  					 }
   359  					 | expr NEQ expr
   360  					 {
   361  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   362  						 bexpr.ReturnBool = true
   363  						 $$ = bexpr
   364  					 }
   365  					 | expr POW expr
   366  					 {
   367  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   368  						 $$ = bexpr
   369  					 }
   370  					 | expr SUB expr
   371  					 {
   372  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   373  						 $$ = bexpr
   374  					 }
   375  					 | expr EQ expr
   376  					 {
   377  						 bexpr := yylex.(*parser).newBinExpr($1, $3, $2)
   378  						 bexpr.ReturnBool = true
   379  						 $$ = bexpr
   380  					 }
   381  					 | columnref IN LEFT_BRACKET array_list RIGHT_BRACKET
   382  					 {
   383  						 bexpr := yylex.(*parser).newBinExpr($1, $4, $2)
   384  						 bexpr.ReturnBool = true
   385  						 $$ = bexpr
   386  					 }
   387  					 | columnref NOT_IN LEFT_BRACKET array_list RIGHT_BRACKET
   388  					 {
   389  						 bexpr := yylex.(*parser).newBinExpr($1, $4, $2)
   390  						 bexpr.ReturnBool = true
   391  						 $$ = bexpr
   392  					 }
   393  					 | columnref MATCH LEFT_BRACKET array_list RIGHT_BRACKET
   394  					 {
   395  						 bexpr := yylex.(*parser).newBinExpr($1, $4, $2)
   396  						 bexpr.ReturnBool = true
   397  						 $$ = bexpr
   398  					 }
   399  					 | columnref NOT_MATCH LEFT_BRACKET array_list RIGHT_BRACKET
   400  					 {
   401  						 bexpr := yylex.(*parser).newBinExpr($1, $4, $2)
   402  						 bexpr.ReturnBool = true
   403  						 $$ = bexpr
   404  					 }
   405  					 ;
   406  
   407  /* function names */
   408  function_name: identifier
   409  						 {
   410  						 	$$ = $1
   411  						 }
   412  						 | attr_expr
   413  						 {
   414  						 	$$ = Item{Val: $1.(*AttrExpr).String()}
   415  						 }
   416  						;
   417  
   418  /* literals */
   419  number_literal: NUMBER
   420  							{
   421  								$$ = yylex.(*parser).number($1.Val)
   422  							}
   423  							| unary_op NUMBER
   424  							{
   425  								num := yylex.(*parser).number($2.Val)
   426  								switch $1.Typ {
   427  								case ADD: // pass
   428  								case SUB:
   429  									if num.IsInt {
   430  										num.Int = -num.Int
   431  									} else {
   432  										num.Float = -num.Float
   433  									}
   434  								}
   435  								$$ = num
   436  							}
   437  							;
   438  
   439  regex: RE LEFT_PAREN string_literal RIGHT_PAREN
   440  		 {
   441  		   $$ = yylex.(*parser).newRegex($3.(*StringLiteral).Val)
   442  		 }
   443  		 | RE LEFT_PAREN QUOTED_STRING RIGHT_PAREN
   444  		 {
   445  		   $$ = yylex.(*parser).newRegex(yylex.(*parser).unquoteString($3.Val))
   446  		 }
   447  		 ;
   448  
   449  identifier: ID
   450            | QUOTED_STRING
   451            {
   452            	$$.Val = yylex.(*parser).unquoteString($1.Val)
   453            }
   454            | IDENTIFIER LEFT_PAREN string_literal RIGHT_PAREN
   455            {
   456            	$$.Val = $3.(*StringLiteral).Val
   457            }
   458  %%