diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 20:34:10 +0000 |
commit | e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch) | |
tree | 68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dfilter/grammar.lemon | |
parent | Initial commit. (diff) | |
download | wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.tar.xz wireshark-e4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc.zip |
Adding upstream version 4.2.2.upstream/4.2.2
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'epan/dfilter/grammar.lemon')
-rw-r--r-- | epan/dfilter/grammar.lemon | 559 |
1 files changed, 559 insertions, 0 deletions
diff --git a/epan/dfilter/grammar.lemon b/epan/dfilter/grammar.lemon new file mode 100644 index 0000000..af997ca --- /dev/null +++ b/epan/dfilter/grammar.lemon @@ -0,0 +1,559 @@ + +%include { +#include "config.h" +#define WS_LOG_DOMAIN LOG_DOMAIN_DFILTER + +#include <assert.h> + +#include "dfilter-int.h" +#include "syntax-tree.h" +#include "sttype-field.h" +#include "sttype-slice.h" +#include "sttype-op.h" +#include "sttype-function.h" +#include "sttype-set.h" +#include "drange.h" + +#include "grammar.h" + +#ifdef _MSC_VER +#pragma warning(disable:4671) +#endif + +static stnode_t * +new_function(dfsyntax_t *dfs, stnode_t *node); + +#define FAIL(dfs, node, ...) \ + do { \ + ws_noisy("Parsing failed here."); \ + dfilter_fail(dfs, DF_ERROR_GENERIC, stnode_location(node), __VA_ARGS__); \ + } while (0) + +DIAG_OFF_LEMON() +} /* end of %include */ + +%code { +DIAG_ON_LEMON() +} + +/* Parser Information */ +%name Dfilter +%token_prefix TOKEN_ +%extra_argument {dfsyntax_t *dfs} + +/* Terminal and Non-Terminal types and destructors */ +%token_type {stnode_t*} +%token_destructor { + (void)dfs; + stnode_free($$); +} + +%default_type {stnode_t*} +%default_destructor {stnode_free($$);} + +%type range_node_list {GSList*} +%destructor range_node_list {drange_node_free_list($$);} + +%type func_params_list {GSList*} +%destructor func_params_list {st_funcparams_free($$);} + +%type set_list {GSList*} +%destructor set_list {set_nodelist_free($$);} + +%type set_element_list {GSList*} +%destructor set_element_list {set_nodelist_free($$);} + +/* This is called as soon as a syntax error happens. After that, +any "error" symbols are shifted, if possible. */ +%syntax_error { + if (!TOKEN) { + dfilter_fail(dfs, DF_ERROR_UNEXPECTED_END, DFILTER_LOC_EMPTY, "Unexpected end of filter expression."); + return; + } + FAIL(dfs, TOKEN, "\"%s\" was unexpected in this context.", stnode_token(TOKEN)); +} + +/* ----------------- The grammar -------------- */ + +/* Associativity */ +%left TEST_OR. +%left TEST_XOR. +%left TEST_AND. +%right TEST_NOT. +%nonassoc TEST_ALL_EQ TEST_ANY_EQ TEST_ALL_NE TEST_ANY_NE TEST_LT TEST_LE TEST_GT TEST_GE + TEST_CONTAINS TEST_MATCHES. +%left BITWISE_AND. +%left PLUS MINUS. +%left STAR RSLASH PERCENT. +%nonassoc UNARY_PLUS UNARY_MINUS. + +/* Top-level targets */ +sentence ::= expr(X). { dfs->st_root = X; } +sentence ::= . { dfs->st_root = NULL; } + +expr(X) ::= relation(R). { X = R; } +expr(X) ::= arithmetic_expr(E). { X = E; } + +/* Logical tests */ +expr(X) ::= expr(Y) TEST_AND(T) expr(Z). +{ + X = T; + sttype_oper_set2(X, STNODE_OP_AND, Y, Z); + stnode_merge_location(X, Y, Z); +} + +expr(X) ::= expr(Y) TEST_OR(T) expr(Z). +{ + X = T; + sttype_oper_set2(X, STNODE_OP_OR, Y, Z); + stnode_merge_location(X, Y, Z); +} + +expr(X) ::= expr(Y) TEST_XOR(T) expr(Z). +{ + stnode_t *A = stnode_new(STTYPE_TEST, NULL, NULL, DFILTER_LOC_EMPTY); + sttype_oper_set2(A, STNODE_OP_OR, stnode_dup(Y), stnode_dup(Z)); + + stnode_t *B = stnode_new(STTYPE_TEST, NULL, NULL, DFILTER_LOC_EMPTY); + sttype_oper_set2(B, STNODE_OP_AND, Y, Z); + + stnode_t *C = stnode_new(STTYPE_TEST, NULL, NULL, DFILTER_LOC_EMPTY); + sttype_oper_set1(C, STNODE_OP_NOT, B); + + X = T; + sttype_oper_set2(X, STNODE_OP_AND, A, C); + stnode_merge_location(X, Y, Z); +} + +expr(X) ::= TEST_NOT(T) expr(Y). +{ + X = T; + sttype_oper_set1(X, STNODE_OP_NOT, Y); + stnode_merge_location(X, T, Y); +} + +/* Any expression inside parens is simply that expression */ +expr(X) ::= LPAREN(L) expr(Y) RPAREN(R). +{ + X = Y; + stnode_merge_location(X, L, R); + stnode_free(L); + stnode_free(R); +} + +/* Entities, or things that can be compared/tested/checked */ +atom(A) ::= STRING(S). { A = S; } +atom(A) ::= CHARCONST(N). { A = N; } +atom(A) ::= LITERAL(S). { A = S; } +atom(A) ::= CONSTANT(C). { A = C; } + +named_field(X) ::= FIELD(F). +{ + X = F; +} + +named_field(X) ::= IDENTIFIER(U). +{ + X = U; + const char *name = stnode_token(U); + header_field_info *hfinfo = dfilter_resolve_unparsed(dfs, name); + if (hfinfo == NULL) { + stnode_replace(X, STTYPE_LITERAL, g_strdup(name)); + } + else { + stnode_replace(X, STTYPE_FIELD, hfinfo); + } +} + +layered_field(X) ::= named_field(F). +{ + X = F; +} + +layered_field(X) ::= named_field(F) HASH LBRACKET range_node_list(L) RBRACKET(R). +{ + X = F; + if (stnode_type_id(X) != STTYPE_FIELD) { + FAIL(dfs, X, "\"%s\" is not a valid protocol or protocol field.", stnode_token(X)); + } + else { + sttype_field_set_range(X, L); + } + g_slist_free(L); + stnode_merge_location(X, F, R); + stnode_free(R); +} + +layered_field(X) ::= named_field(F) HASH INTEGER(N). +{ + X = F; + if (stnode_type_id(X) != STTYPE_FIELD) { + FAIL(dfs, X, "\"%s\" is not a valid protocol or protocol field.", stnode_token(X)); + } + else { + char *err_msg = NULL; + drange_node *range = drange_node_from_str(stnode_token(N), &err_msg); + if (err_msg != NULL) { + FAIL(dfs, N, "%s", err_msg); + g_free(err_msg); + } + sttype_field_set_range1(X, range); + } + stnode_merge_location(X, F, N); + stnode_free(N); +} + +rawable_field(X) ::= layered_field(F). +{ + X = F; +} + +rawable_field(X) ::= ATSIGN(A) layered_field(F). +{ + X = F; + if (stnode_type_id(X) != STTYPE_FIELD) { + FAIL(dfs, X, "\"%s\" is not a valid protocol or protocol field.", stnode_token(X)); + } + else { + sttype_field_set_raw(X, true); + } + stnode_merge_location(X, A, F); + stnode_free(A); +} + +reference(X) ::= DOLLAR(D) LBRACE rawable_field(F) RBRACE(R). +{ + /* convert field to reference */ + if (stnode_type_id(F) != STTYPE_FIELD) { + X = stnode_new(STTYPE_REFERENCE, NULL, NULL, stnode_location(F)); + FAIL(dfs, F, "\"%s\" is not a valid protocol or protocol field.", stnode_token(F)); + } + else { + X = stnode_new(STTYPE_REFERENCE, sttype_field_hfinfo(F), NULL, stnode_location(F)); + sttype_field_set_drange(X, sttype_field_drange_steal(F)); + sttype_field_set_raw(X, sttype_field_raw(F)); + } + stnode_merge_location(X, D, R); + stnode_free(F); + stnode_free(D); + stnode_free(R); +} + +entity(E) ::= atom(A). { E = A; } +entity(E) ::= slice(R). { E = R; } +entity(E) ::= function(F). { E = F; } +entity(E) ::= rawable_field(F). { E = F; } +entity(E) ::= reference(R). { E = R; } + +arithmetic_expr(T) ::= entity(N). +{ + T = N; +} + +arithmetic_expr(T) ::= PLUS(P) arithmetic_expr(N). [UNARY_PLUS] +{ + T = N; + stnode_merge_location(T, P, N); + stnode_free(P); +} + +arithmetic_expr(T) ::= MINUS(M) arithmetic_expr(N). [UNARY_MINUS] +{ + T = M; + sttype_oper_set1(T, STNODE_OP_UNARY_MINUS, N); + stnode_merge_location(T, M, N); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) BITWISE_AND(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_BITWISE_AND, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) PLUS(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_ADD, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) MINUS(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_SUBTRACT, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) STAR(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_MULTIPLY, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) RSLASH(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_DIVIDE, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= arithmetic_expr(F) PERCENT(O) arithmetic_expr(M). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_MODULO, F, M); + stnode_merge_location(T, F, M); +} + +arithmetic_expr(T) ::= LBRACE(L) arithmetic_expr(F) RBRACE(R). +{ + T = F; + stnode_merge_location(T, L, R); + stnode_free(L); + stnode_free(R); +} + +/* Relational tests */ +cmp_op(O) ::= TEST_ALL_EQ(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_ALL_EQ); +} + +cmp_op(O) ::= TEST_ANY_EQ(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_ANY_EQ); +} + +cmp_op(O) ::= TEST_ALL_NE(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_ALL_NE); +} + +cmp_op(O) ::= TEST_ANY_NE(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_ANY_NE); +} + +cmp_op(O) ::= TEST_GT(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_GT); +} + +cmp_op(O) ::= TEST_GE(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_GE); +} + +cmp_op(O) ::= TEST_LT(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_LT); +} + +cmp_op(O) ::= TEST_LE(L). +{ + O = L; + sttype_oper_set_op(O, STNODE_OP_LE); +} + +comparison_test(T) ::= arithmetic_expr(E) cmp_op(O) arithmetic_expr(F). +{ + T = O; + sttype_oper_set2_args(O, E, F); + stnode_merge_location(T, E, F); +} + +/* 'a == b == c' or 'a < b <= c <= d < e' */ +comparison_test(T) ::= arithmetic_expr(E) cmp_op(O) comparison_test(R). +{ + stnode_t *L, *F; + + F = R; + while (stnode_type_id(F) == STTYPE_TEST) { + sttype_oper_get(F, NULL, &F, NULL); + } + + L = O; + sttype_oper_set2_args(L, E, stnode_dup(F)); + + T = stnode_new_empty(STTYPE_TEST); + sttype_oper_set2(T, STNODE_OP_AND, L, R); + stnode_merge_location(T, E, R); +} + +relation_test(T) ::= comparison_test(C). { T = C; } + +relation_test(T) ::= entity(E) TEST_CONTAINS(L) entity(F). +{ + T = L; + sttype_oper_set2(T, STNODE_OP_CONTAINS, E, F); + stnode_merge_location(T, E, F); +} + +relation_test(T) ::= entity(E) TEST_MATCHES(L) entity(F). +{ + T = L; + sttype_oper_set2(T, STNODE_OP_MATCHES, E, F); + stnode_merge_location(T, E, F); +} + +relation_test(T) ::= entity(E) TEST_IN(O) set(S). +{ + T = O; + sttype_oper_set2(T, STNODE_OP_IN, E, S); + stnode_merge_location(T, E, S); +} + +relation_test(T) ::= entity(E) TEST_NOT TEST_IN(O) set(S). +{ + T = O; + sttype_oper_set2(O, STNODE_OP_NOT_IN, E, S); + stnode_merge_location(T, E, S); +} + +relation(R) ::= relation_test(T). { R = T; } + +relation(R) ::= ANY(A) relation_test(T). +{ + R = T; + sttype_test_set_match(R, STNODE_MATCH_ANY); + stnode_merge_location(R, A, T); + stnode_free(A); +} + +relation(R) ::= ALL(A) relation_test(T). +{ + R = T; + sttype_test_set_match(R, STNODE_MATCH_ALL); + stnode_merge_location(R, A, T); + stnode_free(A); +} + +/* Sets */ + +set_element_list(N) ::= arithmetic_expr(X). +{ + N = g_slist_append(NULL, X); + N = g_slist_append(N, NULL); +} + +set_element_list(N) ::= arithmetic_expr(X) DOTDOT arithmetic_expr(Y). +{ + N = g_slist_append(NULL, X); + N = g_slist_append(N, Y); +} + +set_list(L) ::= set_element_list(N). +{ + L = g_slist_concat(NULL, N); +} + +set_list(L) ::= set_list(P) COMMA set_element_list(N). +{ + L = g_slist_concat(P, N); +} + +set(S) ::= LBRACE(LB) set_list(L) RBRACE(RB). +{ + S = stnode_new(STTYPE_SET, L, NULL, DFILTER_LOC_EMPTY); + stnode_merge_location(S, LB, RB); + stnode_free(LB); + stnode_free(RB); +} + +/* Slices */ + +slice(R) ::= entity(E) LBRACKET range_node_list(L) RBRACKET. +{ + R = stnode_new(STTYPE_SLICE, NULL, NULL, DFILTER_LOC_EMPTY); + sttype_slice_set(R, E, L); + + /* Delete the list, but not the drange_nodes that + * the list contains. */ + g_slist_free(L); +} + +range_node_list(L) ::= RANGE_NODE(N). +{ + char *err_msg = NULL; + drange_node *rn = drange_node_from_str(stnode_token(N), &err_msg); + if (err_msg != NULL) { + FAIL(dfs, N, "%s", err_msg); + g_free(err_msg); + } + L = g_slist_append(NULL, rn); + stnode_free(N); +} + +range_node_list(L) ::= range_node_list(P) COMMA RANGE_NODE(N). +{ + char *err_msg = NULL; + drange_node *rn = drange_node_from_str(stnode_token(N), &err_msg); + if (err_msg != NULL) { + FAIL(dfs, N, "%s", err_msg); + g_free(err_msg); + } + L = g_slist_append(P, rn); + stnode_free(N); +} + +/* Functions */ + +%code { + static stnode_t * + new_function(dfsyntax_t *dfs, stnode_t *node) + { + const char *name = stnode_token(node); + + df_func_def_t *def = df_func_lookup(name); + if (!def) { + FAIL(dfs, node, "Function '%s' does not exist", name); + } + stnode_replace(node, STTYPE_FUNCTION, def); + return node; + } +} + +/* A function can have one or more parameters */ +function(F) ::= IDENTIFIER(U) LPAREN func_params_list(P) RPAREN(R). +{ + F = new_function(dfs, U); + sttype_function_set_params(F, P); + stnode_merge_location(F, U, R); + stnode_free(R); +} + +function ::= CONSTANT(U) LPAREN func_params_list RPAREN. +{ + FAIL(dfs, U, "Function '%s' does not exist", stnode_token(U)); +} + +/* A function can have zero parameters. */ +function(F) ::= IDENTIFIER(U) LPAREN RPAREN(R). +{ + F = new_function(dfs, U); + stnode_merge_location(F, U, R); + stnode_free(R); +} + +function ::= CONSTANT(U) LPAREN RPAREN. +{ + FAIL(dfs, U, "Function '%s' does not exist", stnode_token(U)); +} + +func_params_list(P) ::= arithmetic_expr(E). +{ + P = g_slist_append(NULL, E); +} + +func_params_list(P) ::= func_params_list(L) COMMA arithmetic_expr(E). +{ + P = g_slist_append(L, E); +} |