From a2c999f4a7c1368c8cdaf554219fb4123068a3f7 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 6 Apr 2014 13:28:21 +0200 Subject: [PATCH] frontend parser: Added support for AND and OR matchers. --- src/frontend/grammar.y | 42 +++++++++++++++++++++++++++++++---- src/frontend/scanner.l | 6 ++++- t/frontend/parser_test.c | 47 +++++++++++++++++++++++++--------------- 3 files changed, 72 insertions(+), 23 deletions(-) diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index 6c52b74..fd268ba 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -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 IDENTIFIER STRING %token FETCH LIST LOOKUP +/* Precedence (lowest first): */ +%left OR +%left AND +%left CMP_EQUAL +%left CMP_REGEX + %type statements %type statement fetch_statement @@ -92,7 +98,8 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); lookup_statement expression -%type compare_matcher +%type 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; } ; diff --git a/src/frontend/scanner.l b/src/frontend/scanner.l index 1e371f4..9eec4de 100644 --- a/src/frontend/scanner.l +++ b/src/frontend/scanner.l @@ -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; diff --git a/t/frontend/parser_test.c b/t/frontend/parser_test.c index 4b17732..1a7dc2b 100644 --- a/t/frontend/parser_test.c +++ b/t/frontend/parser_test.c @@ -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' ", 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 }, -- 2.30.2