Code

frontend parser: Added support for AND and OR matchers.
authorSebastian Harl <sh@tokkee.org>
Sun, 6 Apr 2014 11:28:21 +0000 (13:28 +0200)
committerSebastian Harl <sh@tokkee.org>
Sun, 6 Apr 2014 11:28:21 +0000 (13:28 +0200)
src/frontend/grammar.y
src/frontend/scanner.l
t/frontend/parser_test.c

index 6c52b74907b17163d1c15c7890f9f85d0ed959bf..fd268baf3a9c6ce5126891c9ff6edbcc8af16e4f 100644 (file)
@@ -78,13 +78,19 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
 
 %token SCANNER_ERROR
 
-%token WHERE
+%token AND OR WHERE
 
 %token CMP_EQUAL CMP_REGEX
 
 %token <str> IDENTIFIER STRING
 %token <node> FETCH LIST LOOKUP
 
+/* Precedence (lowest first): */
+%left OR
+%left AND
+%left CMP_EQUAL
+%left CMP_REGEX
+
 %type <list> statements
 %type <node> statement
        fetch_statement
@@ -92,7 +98,8 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg);
        lookup_statement
        expression
 
-%type <m> compare_matcher
+%type <m> matcher
+       compare_matcher
 
 %%
 
@@ -215,7 +222,7 @@ lookup_statement:
        ;
 
 expression:
-       compare_matcher
+       matcher
                {
                        sdb_store_matcher_t *m = $1;
                        if (! m) {
@@ -229,7 +236,9 @@ expression:
                                                conn_node_matcher_t));
                        $$->cmd = CONNECTION_EXPR;
 
-                       if (M(m)->type == MATCHER_HOST)
+                       if ((M(m)->type == MATCHER_HOST)
+                                       || (M(m)->type == MATCHER_AND)
+                                       || (M(m)->type == MATCHER_OR))
                                CONN_MATCHER($$)->matcher = m;
                        else if (M(m)->type == MATCHER_SERVICE)
                                CONN_MATCHER($$)->matcher = sdb_store_host_matcher(NULL,
@@ -239,6 +248,31 @@ expression:
                                CONN_MATCHER($$)->matcher = sdb_store_host_matcher(NULL,
                                                /* name_re = */ NULL, /* service = */ NULL,
                                                /* attr = */ m);
+                       else {
+                               char errbuf[1024];
+                               snprintf(errbuf, sizeof(errbuf),
+                                               YY_("syntax error, unexpected matcher type %d"),
+                                               M(m)->type);
+                               sdb_fe_yyerror(&yylloc, scanner, errbuf);
+                               YYABORT;
+                       }
+               }
+       ;
+
+matcher:
+       matcher AND matcher
+               {
+                       $$ = sdb_store_con_matcher($1, $3);
+               }
+       |
+       matcher OR matcher
+               {
+                       $$ = sdb_store_dis_matcher($1, $3);
+               }
+       |
+       compare_matcher
+               {
+                       $$ = $1;
                }
        ;
 
index 1e371f45668435d509dd4ddf942ec196f547ba76..9eec4de6c455e3dadd99fe586c2d4e68ba324395 100644 (file)
@@ -92,12 +92,16 @@ string              ('[^']*')
 
 {identifier} {
                /* XXX: simplify handling of reserved words */
-               if (! strcasecmp(yytext, "FETCH"))
+               if (! strcasecmp(yytext, "AND"))
+                       return AND;
+               else if (! strcasecmp(yytext, "FETCH"))
                        return FETCH;
                else if (! strcasecmp(yytext, "LIST"))
                        return LIST;
                else if (! strcasecmp(yytext, "LOOKUP"))
                        return LOOKUP;
+               else if (! strcasecmp(yytext, "OR"))
+                       return OR;
                else if (! strcasecmp(yytext, "WHERE"))
                        return WHERE;
 
index 4b177328c084483edc1c74d7e167cf89533a8db3..1a7dc2bb3370de382d49b1b61a66f023bc868c79 100644 (file)
@@ -45,34 +45,41 @@ START_TEST(test_parse)
                sdb_conn_state_t expected_cmd;
        } golden_data[] = {
                /* empty commands */
-               { NULL,                 -1, -1, 0 },
-               { "",                   -1,  0, 0 },
-               { ";",                  -1,  0, 0 },
-               { ";;",                 -1,  0, 0 },
+               { NULL,                  -1, -1, 0 },
+               { "",                    -1,  0, 0 },
+               { ";",                   -1,  0, 0 },
+               { ";;",                  -1,  0, 0 },
 
                /* valid commands */
-               { "FETCH 'host'",       -1,  1, CONNECTION_FETCH  },
-               { "LIST",               -1,  1, CONNECTION_LIST   },
-               { "LIST -- comment",    -1,  1, CONNECTION_LIST   },
-               { "LIST;",              -1,  1, CONNECTION_LIST   },
-               { "LIST; INVALID",       5,  1, CONNECTION_LIST   },
+               { "FETCH 'host'",        -1,  1, CONNECTION_FETCH  },
+               { "LIST",                -1,  1, CONNECTION_LIST   },
+               { "LIST -- comment",     -1,  1, CONNECTION_LIST   },
+               { "LIST;",               -1,  1, CONNECTION_LIST   },
+               { "LIST; INVALID",        5,  1, CONNECTION_LIST   },
 
                { "LOOKUP hosts WHERE "
-                 "host.name = 'host'", -1,  1, CONNECTION_LOOKUP },
+                 "host.name = 'host'",  -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "host.name =~ 'p' AND "
+                 "service.name =~ 'p'", -1,  1, CONNECTION_LOOKUP },
+               { "LOOKUP hosts WHERE "
+                 "host.name =~ 'p' AND "
+                 "service.name =~ 'p' OR "
+                 "service.name =~ 'r'", -1,  1, CONNECTION_LOOKUP },
 
                /* comments */
-               { "/* some comment */", -1,  0, 0 },
-               { "-- another comment", -1,  0, 0 },
+               { "/* some comment */",  -1,  0, 0 },
+               { "-- another comment",  -1,  0, 0 },
 
                /* syntax errors */
-               { "INVALID",            -1, -1, 0 },
-               { "FETCH host",         -1, -1, 0 },
-               { "LIST; INVALID",       8, -1, 0 },
-               { "/* some incomplete", -1, -1, 0 },
+               { "INVALID",             -1, -1, 0 },
+               { "FETCH host",          -1, -1, 0 },
+               { "LIST; INVALID",        8, -1, 0 },
+               { "/* some incomplete",  -1, -1, 0 },
 
-               { "LOOKUP hosts",       -1, -1, 0 },
+               { "LOOKUP hosts",        -1, -1, 0 },
                { "LOOKUP foo WHERE "
-                 "host.name = 'host'", -1, -1, 0 },
+                 "host.name = 'host'",  -1, -1, 0 },
        };
 
        size_t i;
@@ -127,6 +134,10 @@ START_TEST(test_parse_matcher)
                { "host.name = 'localhost'",        -1,  0 },
                { "host.name = 'localhost' -- foo", -1,  0 },
                { "host.name = 'host' <garbage>",   18,  0 },
+               { "host.name =~ 'pattern' AND "
+                 "service.name =~ 'pattern'",      -1,  0 },
+               { "host.name =~ 'pattern' OR "
+                 "service.name =~ 'pattern'",      -1,  0 },
 
                /* syntax errors */
                { "LIST",                           -1, -1 },