[augeas-devel] [PATCH 3 of 4] Add subtraction of regular expressions to the language

David Lutterkort dlutter at redhat.com
Fri May 9 19:59:28 UTC 2008


7 files changed, 89 insertions(+), 5 deletions(-)
src/lexer.l                               |    2 -
src/parser.y                              |   13 +++++---
src/regexp.c                              |    1 
src/syntax.c                              |   46 +++++++++++++++++++++++++++++
src/syntax.h                              |    1 
tests/modules/fail_regexp_minus_empty.aug |    9 +++++
tests/modules/pass_regexp_minus.aug       |   22 +++++++++++++


# HG changeset patch
# User David Lutterkort <dlutter at redhat.com>
# Date 1210363161 25200
# Node ID 57b32b999e8beedd1a014553d1b8a49c12f36b55
# Parent  a23b4e8f59df90d2a83e30ac0d9bae32cfc30e93
Add subtraction of regular expressions to the language

It is now possible to say something like

  let re = /[a-z]+/ - "baseurl"

The '-' operator is only defined between regexps.

diff -r a23b4e8f59df -r 57b32b999e8b src/lexer.l
--- a/src/lexer.l	Fri May 09 12:59:20 2008 -0700
+++ b/src/lexer.l	Fri May 09 12:59:21 2008 -0700
@@ -90,7 +90,7 @@ ARROW  ->
                return REGEXP;
   }
 
-  [|*?+()=:;\.\[\]{}]     return yytext[0];
+  [|*?+()=:;\.\[\]{}-]    return yytext[0];
 
   module        return KW_MODULE;
   let           return KW_LET;
diff -r a23b4e8f59df -r 57b32b999e8b src/parser.y
--- a/src/parser.y	Fri May 09 12:59:20 2008 -0700
+++ b/src/parser.y	Fri May 09 12:59:21 2008 -0700
@@ -68,7 +68,7 @@ typedef struct info YYLTYPE;
 }
 
 %type<term>   start decls
-%type<term>   exp composeexp unionexp catexp appexp rexp aexp
+%type<term>   exp composeexp unionexp minusexp catexp appexp rexp aexp
 %type<term>   param param_list
 %type<string> qid id autoload
 %type<type>  type atype
@@ -188,12 +188,17 @@ composeexp: composeexp ';' unionexp
    | unionexp
      { $$ = $1; }
 
-unionexp: unionexp '|' catexp
+unionexp: unionexp '|' minusexp
      { $$ = make_binop(A_UNION, $1, $3, &@$); }
-   | catexp
+   | minusexp
      { $$ = $1; }
    | tree_const
      { $$ = make_tree_value($1, &@1); }
+
+minusexp: minusexp '-' catexp
+     { $$ = make_binop(A_MINUS, $1, $3, &@$); }
+   | catexp
+     { $$ = $1; }
 
 catexp: catexp '.' appexp
 { $$ = make_binop(A_CONCAT, $1, $3, &@$); }
@@ -383,7 +388,7 @@ static struct term *make_binop(enum term
                               struct term *left, struct term *right,
                               struct info *locp) {
   assert(tag == A_COMPOSE || tag == A_CONCAT
-         || tag == A_UNION || tag == A_APP);
+         || tag == A_UNION || tag == A_APP || tag == A_MINUS);
   struct term *term = make_term_locp(tag, locp);
   term->left = left;
   term->right = right;
diff -r a23b4e8f59df -r 57b32b999e8b src/regexp.c
--- a/src/regexp.c	Fri May 09 12:59:20 2008 -0700
+++ b/src/regexp.c	Fri May 09 12:59:21 2008 -0700
@@ -133,6 +133,7 @@ regexp_minus(struct info *info, struct r
     }
 
     result = make_regexp(info, s);
+    s = NULL;
 
  done:
     fa_free(fa);
diff -r a23b4e8f59df -r 57b32b999e8b src/syntax.c
--- a/src/syntax.c	Fri May 09 12:59:20 2008 -0700
+++ b/src/syntax.c	Fri May 09 12:59:21 2008 -0700
@@ -191,6 +191,7 @@ static void free_term(struct term *term)
         break;
     case A_COMPOSE:
     case A_UNION:
+    case A_MINUS:
     case A_CONCAT:
     case A_APP:
     case A_LET:
@@ -1096,6 +1097,9 @@ static int check_exp(struct term *term, 
     case A_UNION:
         result = check_binop("union", term, ctx, 2, t_regexp, t_lens);
         break;
+    case A_MINUS:
+        result = check_binop("minus", term, ctx, 1, t_regexp);
+        break;
     case A_COMPOSE:
         result = check_compose(term, ctx);
         break;
@@ -1312,6 +1316,45 @@ static struct value *compile_union(struc
     return v;
 }
 
+static struct value *compile_minus(struct term *exp, struct ctx *ctx) {
+    struct value *v1 = compile_exp(exp->info, exp->left, ctx);
+    if (EXN(v1))
+        return v1;
+    struct value *v2 = compile_exp(exp->info, exp->right, ctx);
+    if (EXN(v2)) {
+        unref(v1, value);
+        return v2;
+    }
+
+    struct type *t = exp->type;
+    struct info *info = exp->info;
+    struct value *v;
+
+    v1 = coerce(v1, t);
+    v2 = coerce(v2, t);
+    if (t->tag == T_REGEXP) {
+        struct regexp *re1 = v1->regexp;
+        struct regexp *re2 = v2->regexp;
+        struct regexp *re = regexp_minus(info, re1, re2);
+        if (re == NULL) {
+            v = make_exn_value(info,
+                   "Regular expression subtraction 'r1 - r2' failed");
+            exn_printf_line(v, "r1: /%s/", re1->pattern->str);
+            exn_printf_line(v, "r2: /%s/", re2->pattern->str);
+        } else {
+            v = make_value(V_REGEXP, ref(info));
+            v->regexp = re;
+        }
+    } else {
+        fatal_error(info, "Tried to subtract a %s and a %s to yield a %s",
+                    type_name(exp->left->type), type_name(exp->right->type),
+                    type_name(t));
+    }
+    unref(v1, value);
+    unref(v2, value);
+    return v;
+}
+
 static struct value *compile_compose(struct term *exp, struct ctx *ctx) {
     struct type *t = exp->type;
     struct info *info = exp->info;
@@ -1508,6 +1551,9 @@ static struct value *compile_exp(struct 
         break;
     case A_UNION:
         v = compile_union(exp, ctx);
+        break;
+    case A_MINUS:
+        v = compile_minus(exp, ctx);
         break;
     case A_CONCAT:
         v = compile_concat(exp, ctx);
diff -r a23b4e8f59df -r 57b32b999e8b src/syntax.h
--- a/src/syntax.h	Fri May 09 12:59:20 2008 -0700
+++ b/src/syntax.h	Fri May 09 12:59:21 2008 -0700
@@ -59,6 +59,7 @@ enum term_tag {
     A_LET,               /* local LET .. IN binding */
     A_COMPOSE,
     A_UNION,
+    A_MINUS,
     A_CONCAT,
     A_APP,
     A_VALUE,
diff -r a23b4e8f59df -r 57b32b999e8b tests/modules/fail_regexp_minus_empty.aug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/modules/fail_regexp_minus_empty.aug	Fri May 09 12:59:21 2008 -0700
@@ -0,0 +1,9 @@
+module Fail_regexp_minus_empty =
+
+  (* This fails since the result of the subtraction is the empty set *)
+  (* which we can not represent as a regular expression.             *)
+  let re = "a" - /[a-z]/
+
+(* Local Variables: *)
+(* mode: caml       *)
+(* End:             *)
diff -r a23b4e8f59df -r 57b32b999e8b tests/modules/pass_regexp_minus.aug
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/modules/pass_regexp_minus.aug	Fri May 09 12:59:21 2008 -0700
@@ -0,0 +1,22 @@
+module Pass_regexp_minus =
+
+  let word = /[a-z]+/
+  let no_baseurl = word - "baseurl"
+
+  let eq = del "=" "="
+
+  let l1 = [ key no_baseurl . eq . store /[a-z]+/ ]
+  let l2 = [ key "baseurl" . eq . store /[0-9]+/ ]
+
+  let lns = ((l1 | l2) . del "\n" "\n")*
+
+  test lns get "foo=abc\nbaseurl=123\n" = 
+    { "foo" = "abc" }
+    { "baseurl" = "123" }
+
+  test lns get "baseurl=abc\n" = *      
+  
+
+(* Local Variables: *)
+(* mode: caml       *)
+(* End:             *)




More information about the augeas-devel mailing list