summaryrefslogtreecommitdiffstats
path: root/epan/dfilter/grammar.lemon
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-10 20:34:10 +0000
commite4ba6dbc3f1e76890b22773807ea37fe8fa2b1bc (patch)
tree68cb5ef9081156392f1dd62a00c6ccc1451b93df /epan/dfilter/grammar.lemon
parentInitial commit. (diff)
downloadwireshark-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.lemon559
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);
+}