From: Sebastian Harl Date: Fri, 17 Oct 2014 07:12:08 +0000 (+0200) Subject: frontend: Added sdb_fe_parse_expr(). X-Git-Tag: sysdb-0.6.0~111 X-Git-Url: https://git.tokkee.org/?p=sysdb.git;a=commitdiff_plain;h=3160b1dc7936a329be2d9cdba8f95fee342bb11c frontend: Added sdb_fe_parse_expr(). This function enables a special new parser mode in which it only accepts simple expressions. --- diff --git a/src/frontend/connection-private.h b/src/frontend/connection-private.h index 85f278c..4ff4e51 100644 --- a/src/frontend/connection-private.h +++ b/src/frontend/connection-private.h @@ -81,6 +81,12 @@ struct sdb_conn { * node types */ +typedef struct { + sdb_conn_node_t super; + sdb_store_expr_t *expr; +} conn_expr_t; +#define CONN_EXPR(obj) ((conn_expr_t *)(obj)) + typedef struct { sdb_conn_node_t super; sdb_store_matcher_t *matcher; @@ -122,6 +128,12 @@ typedef struct { * type helper functions */ +static void __attribute__((unused)) +conn_expr_destroy(sdb_object_t *obj) +{ + sdb_object_deref(SDB_OBJ(CONN_EXPR(obj)->expr)); +} /* conn_expr_destroy */ + static void __attribute__((unused)) conn_matcher_destroy(sdb_object_t *obj) { diff --git a/src/frontend/grammar.y b/src/frontend/grammar.y index ef479ef..40159bf 100644 --- a/src/frontend/grammar.y +++ b/src/frontend/grammar.y @@ -56,6 +56,12 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); /* quick access to the parser mode */ #define parser_mode sdb_fe_yyget_extra(scanner)->mode +#define MODE_TO_STRING(m) \ + (((m) == SDB_PARSE_DEFAULT) ? "statement" \ + : ((m) == SDB_PARSE_COND) ? "condition" \ + : ((m) == SDB_PARSE_EXPR) ? "expression" \ + : "UNKNOWN") + %} %pure-parser @@ -148,11 +154,13 @@ sdb_fe_yyerror(YYLTYPE *lval, sdb_fe_yyscan_t scanner, const char *msg); statements: statements ';' statement { - /* only accept this in default parse mode */ + /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected statement, " - "expecting condition")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($3)); YYABORT; } @@ -165,11 +173,13 @@ statements: | statement { - /* only accept this in default parse mode */ + /* only accepted in default parse mode */ if (parser_mode != SDB_PARSE_DEFAULT) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected statement, " - "expecting condition")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -182,11 +192,13 @@ statements: | condition { - /* only accept this in condition parse mode */ + /* only accepted in condition parse mode */ if (! (parser_mode & SDB_PARSE_COND)) { - sdb_fe_yyerror(&yylloc, scanner, + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), YY_("syntax error, unexpected condition, " - "expecting statement")); + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); sdb_object_deref(SDB_OBJ($1)); YYABORT; } @@ -196,6 +208,31 @@ statements: sdb_object_deref(SDB_OBJ($1)); } } + | + expression + { + /* only accepted in expression parse mode */ + if (! (parser_mode & SDB_PARSE_EXPR)) { + char errmsg[1024]; + snprintf(errmsg, sizeof(errmsg), + YY_("syntax error, unexpected expression, " + "expecting %s"), MODE_TO_STRING(parser_mode)); + sdb_fe_yyerror(&yylloc, scanner, errmsg); + sdb_object_deref(SDB_OBJ($1)); + YYABORT; + } + + if ($1) { + sdb_conn_node_t *n; + n = SDB_CONN_NODE(sdb_object_create_dT(/* name = */ NULL, + conn_expr_t, conn_expr_destroy)); + n->cmd = CONNECTION_EXPR; + CONN_EXPR($$)->expr = $1; + + sdb_llist_append(pt, SDB_OBJ(n)); + sdb_object_deref(SDB_OBJ(n)); + } + } ; statement: diff --git a/src/frontend/parser.c b/src/frontend/parser.c index 3184ffc..b0ae01a 100644 --- a/src/frontend/parser.c +++ b/src/frontend/parser.c @@ -126,5 +126,44 @@ sdb_fe_parse_matcher(const char *cond, int len) return m; } /* sdb_fe_parse_matcher */ +sdb_store_expr_t * +sdb_fe_parse_expr(const char *expr, int len) +{ + sdb_fe_yyscan_t scanner; + sdb_fe_yyextra_t yyextra; + + sdb_conn_node_t *node; + sdb_store_expr_t *e; + + int yyres; + + if (scanner_init(expr, len, &scanner, &yyextra)) + return NULL; + + yyextra.mode = SDB_PARSE_EXPR; + + yyres = sdb_fe_yyparse(scanner); + sdb_fe_scanner_destroy(scanner); + + if (yyres) { + sdb_llist_destroy(yyextra.parsetree); + return NULL; + } + + node = SDB_CONN_NODE(sdb_llist_get(yyextra.parsetree, 0)); + if (! node) + return NULL; + + if (node->cmd == CONNECTION_EXPR) + e = CONN_EXPR(node)->expr; + else + e = NULL; + + CONN_EXPR(node)->expr = NULL; + sdb_llist_destroy(yyextra.parsetree); + sdb_object_deref(SDB_OBJ(node)); + return e; +} /* sdb_fe_parse_expr */ + /* vim: set tw=78 sw=4 ts=4 noexpandtab : */ diff --git a/src/include/frontend/parser.h b/src/include/frontend/parser.h index c5fb4ab..d2dfb01 100644 --- a/src/include/frontend/parser.h +++ b/src/include/frontend/parser.h @@ -39,6 +39,7 @@ extern "C" { enum { SDB_PARSE_DEFAULT = 0, SDB_PARSE_COND, + SDB_PARSE_EXPR, }; /* YY_EXTRA data */ @@ -65,6 +66,9 @@ sdb_fe_yyparse(sdb_fe_yyscan_t scanner); sdb_store_matcher_t * sdb_fe_parse_matcher(const char *cond, int len); +sdb_store_expr_t * +sdb_fe_parse_expr(const char *expr, int len); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/include/frontend/proto.h b/src/include/frontend/proto.h index 0577550..3819e3f 100644 --- a/src/include/frontend/proto.h +++ b/src/include/frontend/proto.h @@ -254,6 +254,12 @@ typedef enum { * A parsed matcher. Only used internally. */ CONNECTION_MATCHER = 100, + + /* + * CONNECTION_EXPR: + * A parsed expression. Only used internally. + */ + CONNECTION_EXPR, } sdb_conn_state_t; #ifdef __cplusplus