[augeas-devel] augeas: master - Path expressions: add union operator
David Lutterkort
lutter at fedoraproject.org
Wed Oct 21 13:35:08 UTC 2009
Gitweb: http://git.fedorahosted.org/git/augeas.git?p=augeas.git;a=commitdiff;h=68d07dbb3b9354bbad12a047e269e162d8e1f554
Commit: 68d07dbb3b9354bbad12a047e269e162d8e1f554
Parent: f1803bfee5cadaec4cfb58add9bb57fdc631ae62
Author: David Lutterkort <lutter at redhat.com>
AuthorDate: Wed Oct 21 15:27:19 2009 +0200
Committer: David Lutterkort <lutter at redhat.com>
CommitterDate: Wed Oct 21 15:27:19 2009 +0200
Path expressions: add union operator
Nodesets can now be unioned with the '|' operator
Fixes ticket #89
---
doc/xpath.txt | 3 ++-
src/pathx.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++----
tests/xpath.tests | 12 ++++++++++++
3 files changed, 62 insertions(+), 5 deletions(-)
diff --git a/doc/xpath.txt b/doc/xpath.txt
index fa0b643..cd12ebe 100644
--- a/doc/xpath.txt
+++ b/doc/xpath.txt
@@ -128,7 +128,8 @@ RelationalExpr ::= AdditiveExpr (RelationalOp AdditiveExpr)?
RelationalOp ::= ">" | "<" | ">=" | "<="
AdditiveExpr ::= MultiplicativeExpr (AdditiveOp MultiplicativeExpr)*
AdditiveOp ::= '+' | '-'
-MultiplicativeExpr ::= PathExpr ('*' PathExpr)*
+MultiplicativeExpr ::= UnionExpr ('*' UnionExpr)*
+UnionExpr ::= PathExpr ("|" PathExpr)*
Literal ::= '"' /[^"]* / '"' | "'" /[^']* / "'"
Number ::= /[0-9]+/
diff --git a/src/pathx.c b/src/pathx.c
index 89e2663..e5eb8fe 100644
--- a/src/pathx.c
+++ b/src/pathx.c
@@ -84,7 +84,8 @@ enum binary_op {
OP_STAR, /* '*' */
OP_AND, /* 'and' */
OP_OR, /* 'or' */
- OP_RE_MATCH /* '=~' */
+ OP_RE_MATCH, /* '=~' */
+ OP_UNION /* '|' */
};
struct pred {
@@ -823,6 +824,27 @@ static bool eval_re_match_str(struct state *state, struct regexp *rx,
return r == strlen(str);
}
+static void eval_union(struct state *state) {
+ value_ind_t vind = make_value(T_NODESET, state);
+ struct value *r = pop_value(state);
+ struct value *l = pop_value(state);
+ struct nodeset *res = NULL;
+
+ assert(l->tag == T_NODESET);
+ assert(r->tag == T_NODESET);
+
+ CHECK_ERROR;
+
+ res = clone_nodeset(l->nodeset, state);
+ CHECK_ERROR;
+ for (int i=0; i < r->nodeset->used; i++) {
+ ns_add(res, r->nodeset->nodes[i], state);
+ CHECK_ERROR;
+ }
+ state->value_pool[vind].nodeset = res;
+ push_value(vind, state);
+}
+
static void eval_re_match(struct state *state) {
struct value *rx = pop_value(state);
struct value *v = pop_value(state);
@@ -875,6 +897,9 @@ static void eval_binary(struct expr *expr, struct state *state) {
case OP_OR:
eval_and_or(state, expr->op);
break;
+ case OP_UNION:
+ eval_union(state);
+ break;
case OP_RE_MATCH:
eval_re_match(state);
break;
@@ -1163,6 +1188,8 @@ static void check_app(struct expr *expr, struct state *state) {
* '=~' : T_STRING -> T_REGEXP -> T_BOOLEAN
* T_NODESET -> T_REGEXP -> T_BOOLEAN
*
+ * '|' : T_NODESET -> T_NODESET -> T_NODESET
+ *
* Any type can be coerced to T_BOOLEAN (see coerce_to_bool)
*/
static void check_binary(struct expr *expr, struct state *state) {
@@ -1197,6 +1224,10 @@ static void check_binary(struct expr *expr, struct state *state) {
ok = (l == T_NUMBER && r == T_NUMBER);
res = T_NUMBER;
break;
+ case OP_UNION:
+ ok = (l == T_NODESET && r == T_NODESET);
+ res = T_NODESET;
+ break;
case OP_AND:
case OP_OR:
ok = 1;
@@ -1868,14 +1899,27 @@ static void parse_path_expr(struct state *state) {
}
/*
- * MultiplicativeExpr ::= PathExpr ('*' PathExpr)*
+ * UnionExpr ::= PathExpr ('|' PathExpr)*
*/
-static void parse_multiplicative_expr(struct state *state) {
+static void parse_union_expr(struct state *state) {
parse_path_expr(state);
CHECK_ERROR;
- while (match(state, '*')) {
+ while (match(state, '|')) {
parse_path_expr(state);
CHECK_ERROR;
+ push_new_binary_op(OP_UNION, state);
+ }
+}
+
+/*
+ * MultiplicativeExpr ::= UnionExpr ('*' UnionExpr)*
+ */
+static void parse_multiplicative_expr(struct state *state) {
+ parse_union_expr(state);
+ CHECK_ERROR;
+ while (match(state, '*')) {
+ parse_union_expr(state);
+ CHECK_ERROR;
push_new_binary_op(OP_STAR, state);
}
}
diff --git a/tests/xpath.tests b/tests/xpath.tests
index 0f4b0f7..a6eef82 100644
--- a/tests/xpath.tests
+++ b/tests/xpath.tests
@@ -221,3 +221,15 @@ test regexp1 /files/etc/sysconfig/network-scripts/*[label() =~ regexp('.*-eth0')
test regexp2 /files/etc/hosts/*[* =~ regexp('127\..*')]
/files/etc/hosts/1
+
+# Union of nodesets
+test union (/files/etc/yum.conf | /files/etc/yum.repos.d/*)/*/gpgcheck
+ /files/etc/yum.conf/main/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora-updates.repo/updates/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora-updates.repo/updates-debuginfo/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora-updates.repo/updates-source/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora.repo/fedora/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora.repo/fedora-debuginfo/gpgcheck = 1
+ /files/etc/yum.repos.d/fedora.repo/fedora-source/gpgcheck = 1
+ /files/etc/yum.repos.d/remi.repo/remi/gpgcheck = 1
+ /files/etc/yum.repos.d/remi.repo/remi-test/gpgcheck = 1
More information about the augeas-devel
mailing list