2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
%include {
|
|
|
|
#include "config.h"
|
|
|
|
|
2013-11-10 15:59:37 +00:00
|
|
|
#include <assert.h>
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
#include "dfilter-int.h"
|
|
|
|
#include "syntax-tree.h"
|
|
|
|
#include "sttype-range.h"
|
|
|
|
#include "sttype-test.h"
|
2006-05-02 14:26:17 +00:00
|
|
|
#include "sttype-function.h"
|
2015-08-19 03:03:41 +00:00
|
|
|
#include "sttype-set.h"
|
2001-02-27 19:23:30 +00:00
|
|
|
#include "drange.h"
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2005-08-20 16:19:22 +00:00
|
|
|
#include "grammar.h"
|
|
|
|
|
2007-04-03 19:08:00 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#pragma warning(disable:4671)
|
|
|
|
#endif
|
2015-08-26 08:32:52 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
/* End of C code */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Parser Information */
|
|
|
|
%name Dfilter
|
|
|
|
%token_prefix TOKEN_
|
|
|
|
%extra_argument {dfwork_t *dfw}
|
|
|
|
|
|
|
|
/* Terminal and Non-Terminal types and destructors */
|
2021-10-26 09:09:36 +00:00
|
|
|
%token_type {df_lval_t*}
|
2013-12-14 23:44:25 +00:00
|
|
|
%token_destructor {
|
2021-10-26 09:09:36 +00:00
|
|
|
(void)dfw;
|
|
|
|
df_lval_free($$);
|
2013-12-14 23:44:25 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
%type sentence {stnode_t*}
|
2007-01-17 16:41:22 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
%type expr {stnode_t*}
|
|
|
|
%destructor expr {stnode_free($$);}
|
|
|
|
|
|
|
|
%type entity {stnode_t*}
|
|
|
|
%destructor entity {stnode_free($$);}
|
|
|
|
|
2021-10-26 09:09:36 +00:00
|
|
|
%type function {stnode_t*}
|
|
|
|
%destructor function {stnode_free($$);}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
%type relation_test {stnode_t*}
|
|
|
|
%destructor relation_test {stnode_free($$);}
|
|
|
|
|
2021-11-05 06:30:40 +00:00
|
|
|
%type comparison_test {stnode_t*}
|
|
|
|
%destructor comparison_test {stnode_free($$);}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
%type logical_test {stnode_t*}
|
|
|
|
%destructor logical_test {stnode_free($$);}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
%type rel_binop {test_op_t}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2021-11-05 06:30:40 +00:00
|
|
|
%type cmp_op {test_op_t}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
%type range {stnode_t*}
|
|
|
|
%destructor range {stnode_free($$);}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
%type range_node {drange_node*}
|
|
|
|
%destructor range_node {drange_node_free($$);}
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
%type range_node_list {GSList*}
|
|
|
|
%destructor range_node_list {drange_node_free_list($$);}
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
%type function_params {GSList*}
|
|
|
|
%destructor function_params {st_funcparams_free($$);}
|
2006-05-02 14:26:17 +00:00
|
|
|
|
2021-10-26 09:35:12 +00:00
|
|
|
%type set {stnode_t*}
|
|
|
|
%destructor set {stnode_free($$);}
|
|
|
|
|
|
|
|
%type set_list {GSList*}
|
|
|
|
%destructor set_list {set_nodelist_free($$);}
|
|
|
|
|
|
|
|
%type set_element {GSList*}
|
|
|
|
%destructor set_element {set_nodelist_free($$);}
|
2015-08-19 03:03:41 +00:00
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
/* This is called as soon as a syntax error happens. After that,
|
|
|
|
any "error" symbols are shifted, if possible. */
|
|
|
|
%syntax_error {
|
|
|
|
|
|
|
|
if (!TOKEN) {
|
2015-01-18 10:22:19 +00:00
|
|
|
dfilter_fail(dfw, "Unexpected end of filter string.");
|
2015-10-27 07:53:44 +00:00
|
|
|
dfw->syntax_error = TRUE;
|
2001-02-01 20:21:25 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-10-26 09:09:36 +00:00
|
|
|
dfilter_fail(dfw, "\"%s\" was unexpected in this context.",
|
|
|
|
df_lval_value(TOKEN));
|
2015-10-27 07:53:44 +00:00
|
|
|
dfw->syntax_error = TRUE;
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* When a parse fails, mark an error. This occurs after
|
|
|
|
the above syntax_error code and after the parser fails to
|
|
|
|
use error recovery, shifting an "error" symbol and successfully
|
|
|
|
shifting 3 more symbols. */
|
|
|
|
%parse_failure {
|
|
|
|
dfw->syntax_error = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ----------------- The grammar -------------- */
|
|
|
|
|
|
|
|
/* Associativity */
|
|
|
|
%left TEST_AND.
|
|
|
|
%left TEST_OR.
|
2004-02-27 12:00:32 +00:00
|
|
|
%nonassoc TEST_EQ TEST_NE TEST_LT TEST_LE TEST_GT TEST_GE TEST_CONTAINS TEST_MATCHES TEST_BITWISE_AND.
|
2001-02-01 20:21:25 +00:00
|
|
|
%right TEST_NOT.
|
|
|
|
|
|
|
|
/* Top-level targets */
|
2015-08-26 08:32:52 +00:00
|
|
|
sentence ::= expr(X). { dfw->st_root = X; }
|
|
|
|
sentence ::= . { dfw->st_root = NULL; }
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
expr(X) ::= relation_test(R). { X = R; }
|
|
|
|
expr(X) ::= logical_test(L). { X = L; }
|
|
|
|
|
|
|
|
|
|
|
|
/* Logical tests */
|
|
|
|
logical_test(T) ::= expr(E) TEST_AND expr(F).
|
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_AND, E, F);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
logical_test(T) ::= expr(E) TEST_OR expr(F).
|
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_OR, E, F);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
logical_test(T) ::= TEST_NOT expr(E).
|
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_NOT, E, NULL);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2004-02-11 21:20:52 +00:00
|
|
|
logical_test(T) ::= entity(E).
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_EXISTS, E, NULL);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Entities, or things that can be compared/tested/checked */
|
2021-10-26 09:09:36 +00:00
|
|
|
entity(E) ::= STRING(S).
|
|
|
|
{
|
2021-10-26 11:32:08 +00:00
|
|
|
E = stnode_new(STTYPE_STRING, df_lval_value(S));
|
2021-10-26 09:09:36 +00:00
|
|
|
df_lval_free(S);
|
|
|
|
}
|
|
|
|
entity(E) ::= CHARCONST(C).
|
|
|
|
{
|
2021-10-31 18:18:28 +00:00
|
|
|
/* A charconst uses "unparsed" semantic rules. */
|
|
|
|
E = stnode_new(STTYPE_UNPARSED, df_lval_value(C));
|
2021-10-26 09:09:36 +00:00
|
|
|
df_lval_free(C);
|
|
|
|
}
|
|
|
|
entity(E) ::= UNPARSED(U).
|
|
|
|
{
|
2021-10-26 11:32:08 +00:00
|
|
|
E = stnode_new(STTYPE_UNPARSED, df_lval_value(U));
|
2021-10-26 09:09:36 +00:00
|
|
|
dfilter_resolve_unparsed(dfw, E);
|
|
|
|
df_lval_free(U);
|
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
entity(E) ::= range(R). { E = R; }
|
2021-10-05 15:48:42 +00:00
|
|
|
entity(E) ::= function(F). { E = F; }
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2001-02-27 19:23:30 +00:00
|
|
|
|
|
|
|
/* Ranges */
|
2021-10-05 05:18:28 +00:00
|
|
|
range(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET.
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2021-10-26 11:32:08 +00:00
|
|
|
R = stnode_new(STTYPE_RANGE, NULL);
|
2021-10-05 05:18:28 +00:00
|
|
|
sttype_range_set(R, E, L);
|
2001-02-27 19:23:30 +00:00
|
|
|
|
|
|
|
/* Delete the list, but not the drange_nodes that
|
|
|
|
* the list contains. */
|
|
|
|
g_slist_free(L);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
range_node_list(L) ::= range_node(D).
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2001-02-27 19:23:30 +00:00
|
|
|
L = g_slist_append(NULL, D);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
range_node_list(L) ::= range_node_list(P) COMMA range_node(D).
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2001-02-27 19:23:30 +00:00
|
|
|
L = g_slist_append(P, D);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2021-10-25 20:27:40 +00:00
|
|
|
range_node(D) ::= RANGE(R).
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2021-10-25 20:27:40 +00:00
|
|
|
char *err = NULL;
|
2021-10-08 12:26:53 +00:00
|
|
|
|
2021-10-26 09:09:36 +00:00
|
|
|
D = drange_node_from_str(df_lval_value(R), &err);
|
2021-10-25 20:27:40 +00:00
|
|
|
if (err != NULL) {
|
|
|
|
dfilter_parse_fail(dfw, "%s", err);
|
|
|
|
g_free(err);
|
|
|
|
}
|
2001-02-27 19:23:30 +00:00
|
|
|
|
2021-10-26 09:09:36 +00:00
|
|
|
df_lval_free(R);
|
2001-02-27 19:23:30 +00:00
|
|
|
}
|
|
|
|
|
2001-02-01 20:21:25 +00:00
|
|
|
|
|
|
|
/* Relational tests */
|
2021-11-05 06:30:40 +00:00
|
|
|
cmp_op(O) ::= TEST_ANY_EQ. { O = TEST_OP_ANY_EQ; }
|
|
|
|
cmp_op(O) ::= TEST_ALL_NE. { O = TEST_OP_ALL_NE; }
|
|
|
|
cmp_op(O) ::= TEST_ANY_NE. { O = TEST_OP_ANY_NE; }
|
|
|
|
cmp_op(O) ::= TEST_GT. { O = TEST_OP_GT; }
|
|
|
|
cmp_op(O) ::= TEST_GE. { O = TEST_OP_GE; }
|
|
|
|
cmp_op(O) ::= TEST_LT. { O = TEST_OP_LT; }
|
|
|
|
cmp_op(O) ::= TEST_LE. { O = TEST_OP_LE; }
|
|
|
|
cmp_op(O) ::= TEST_BITWISE_AND. { O = TEST_OP_BITWISE_AND; }
|
|
|
|
|
|
|
|
comparison_test(T) ::= entity(E) cmp_op(O) entity(F).
|
2001-02-01 20:21:25 +00:00
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(O, E, F);
|
2001-02-01 20:21:25 +00:00
|
|
|
}
|
|
|
|
|
2012-06-19 12:12:41 +00:00
|
|
|
/* 'a == b == c' or 'a < b <= c <= d < e' */
|
2021-11-05 06:30:40 +00:00
|
|
|
comparison_test(T) ::= entity(E) cmp_op(O) comparison_test(R).
|
2012-06-19 12:12:41 +00:00
|
|
|
{
|
|
|
|
stnode_t *L, *F;
|
|
|
|
/* for now generate it like E O F TEST_OP_AND F P G, later it could be optimized
|
|
|
|
or semantically checked (to make a <= b >= c or a == b != c invalid)?
|
|
|
|
*/
|
|
|
|
|
|
|
|
F = R;
|
|
|
|
do {
|
2021-06-18 18:21:42 +00:00
|
|
|
ws_assert(F != NULL && stnode_type_id(F) == STTYPE_TEST);
|
2012-06-19 12:12:41 +00:00
|
|
|
sttype_test_get(F, NULL, &F, NULL);
|
|
|
|
} while (stnode_type_id(F) == STTYPE_TEST);
|
|
|
|
|
2021-10-27 05:38:36 +00:00
|
|
|
L = stnode_new_test(O, E, stnode_dup(F));
|
2012-06-19 12:12:41 +00:00
|
|
|
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_AND, L, R);
|
2012-06-19 12:12:41 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 06:30:40 +00:00
|
|
|
relation_test(T) ::= comparison_test(C). { T = C; }
|
|
|
|
|
|
|
|
/* Does not chain like math comparisons. */
|
|
|
|
rel_binop(O) ::= TEST_CONTAINS. { O = TEST_OP_CONTAINS; }
|
|
|
|
rel_binop(O) ::= TEST_MATCHES. { O = TEST_OP_MATCHES; }
|
|
|
|
|
|
|
|
relation_test(T) ::= entity(E) rel_binop(O) entity(F).
|
2021-10-14 16:21:10 +00:00
|
|
|
{
|
2021-11-05 06:30:40 +00:00
|
|
|
T = stnode_new_test(O, E, F);
|
2021-10-14 16:21:10 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 09:35:12 +00:00
|
|
|
relation_test(T) ::= entity(E) TEST_IN set(S).
|
2015-08-19 03:03:41 +00:00
|
|
|
{
|
2021-10-27 05:38:36 +00:00
|
|
|
T = stnode_new_test(TEST_OP_IN, E, S);
|
2015-08-19 03:03:41 +00:00
|
|
|
}
|
|
|
|
|
2021-10-18 17:31:59 +00:00
|
|
|
relation_test(T) ::= entity(E) TEST_NOT TEST_IN set(S).
|
|
|
|
{
|
|
|
|
stnode_t *R = stnode_new_test(TEST_OP_IN, E, S);
|
|
|
|
|
|
|
|
T = stnode_new_test(TEST_OP_NOT, R, NULL);
|
|
|
|
}
|
|
|
|
|
2021-10-26 09:35:12 +00:00
|
|
|
set(S) ::= LBRACE set_list(L) RBRACE.
|
|
|
|
{
|
|
|
|
S = stnode_new(STTYPE_SET, L);
|
|
|
|
}
|
|
|
|
|
|
|
|
set_list(L) ::= set_element(N).
|
2015-08-19 03:03:41 +00:00
|
|
|
{
|
2021-10-26 09:35:12 +00:00
|
|
|
L = g_slist_concat(NULL, N);
|
2015-08-19 03:03:41 +00:00
|
|
|
}
|
|
|
|
|
2021-10-27 17:20:38 +00:00
|
|
|
set_list(L) ::= set_list(P) COMMA set_element(N).
|
2015-08-19 03:03:41 +00:00
|
|
|
{
|
2021-10-26 09:35:12 +00:00
|
|
|
L = g_slist_concat(P, N);
|
2018-04-14 16:07:22 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 09:35:12 +00:00
|
|
|
set_element(N) ::= entity(X).
|
2018-04-14 16:07:22 +00:00
|
|
|
{
|
2021-10-26 09:35:12 +00:00
|
|
|
N = g_slist_append(NULL, X);
|
|
|
|
N = g_slist_append(N, NULL);
|
2018-04-14 16:07:22 +00:00
|
|
|
}
|
|
|
|
|
2021-10-26 09:35:12 +00:00
|
|
|
set_element(N) ::= entity(X) DOTDOT entity(Y).
|
2018-04-14 16:07:22 +00:00
|
|
|
{
|
2021-10-26 09:35:12 +00:00
|
|
|
N = g_slist_append(NULL, X);
|
|
|
|
N = g_slist_append(N, Y);
|
2015-08-19 03:03:41 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|
2006-05-02 14:26:17 +00:00
|
|
|
/* Functions */
|
|
|
|
|
|
|
|
/* A function can have one or more parameters */
|
2021-09-27 09:33:42 +00:00
|
|
|
function(F) ::= UNPARSED(U) LPAREN function_params(P) RPAREN.
|
2006-05-02 14:26:17 +00:00
|
|
|
{
|
2021-10-26 09:09:36 +00:00
|
|
|
F = dfilter_new_function(dfw, df_lval_value(U));
|
2021-09-27 09:33:42 +00:00
|
|
|
sttype_function_set_params(F, P);
|
2021-10-26 09:09:36 +00:00
|
|
|
df_lval_free(U);
|
2006-05-02 14:26:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* A function can have zero parameters. */
|
2021-09-27 09:33:42 +00:00
|
|
|
function(F) ::= UNPARSED(U) LPAREN RPAREN.
|
2006-05-02 14:26:17 +00:00
|
|
|
{
|
2021-10-26 09:09:36 +00:00
|
|
|
F = dfilter_new_function(dfw, df_lval_value(U));
|
|
|
|
df_lval_free(U);
|
2006-05-02 14:26:17 +00:00
|
|
|
}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
function_params(P) ::= entity(E).
|
2006-05-02 14:26:17 +00:00
|
|
|
{
|
|
|
|
P = g_slist_append(NULL, E);
|
|
|
|
}
|
|
|
|
|
2021-10-01 11:14:56 +00:00
|
|
|
function_params(P) ::= function_params(L) COMMA entity(E).
|
2006-05-02 14:26:17 +00:00
|
|
|
{
|
|
|
|
P = g_slist_append(L, E);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Any expression inside parens is simply that expression */
|
|
|
|
expr(X) ::= LPAREN expr(Y) RPAREN.
|
|
|
|
{
|
|
|
|
X = Y;
|
2021-09-27 00:54:41 +00:00
|
|
|
stnode_set_inside_parens(X, TRUE);
|
2006-05-02 14:26:17 +00:00
|
|
|
}
|
2001-02-01 20:21:25 +00:00
|
|
|
|