Hi, Here is a small patch that add the new primitive square lens with test.
The get and put directions are working. The square lens is limited to a static string body. This has to be changed for a lens body. Also, the typecheck is not done properly yet. There is some cleanup to do, since there is a lot of debug output. Valgrind reports no leaks for the test. Since this is the first lens primitive to take a lens as an argument, I don't know how to handle the case in lns_square. Should I add a third argument to functions that build primitive lenses? Francis
From 8c8d31fd51ce24fd7b8fdb8d47f08a2d0a83f701 Mon Sep 17 00:00:00 2001 From: Francis Giraldeau <[email protected]> Date: Sat, 29 May 2010 16:00:03 -0400 Subject: [PATCH] ADD basic square lens with static string inner body --- src/builtin.c | 11 ++++ src/get.c | 122 ++++++++++++++++++++++++++++++++++++++++- src/lens.c | 23 ++++++- src/lens.h | 10 ++- src/put.c | 6 ++ tests/modules/pass_square.aug | 7 ++ 6 files changed, 170 insertions(+), 9 deletions(-) create mode 100644 tests/modules/pass_square.aug diff --git a/src/builtin.c b/src/builtin.c index ef7b7d3..2de92f8 100644 --- a/src/builtin.c +++ b/src/builtin.c @@ -85,6 +85,16 @@ static struct value *lns_counter(struct info *info, struct value *str) { assert(str->tag == V_STRING); return lns_make_prim(L_COUNTER, ref(info), NULL, ref(str->string)); } +/* FIXME: actual square lens takes only a static string as the inner body, + * should be a lens + */ +/* V_REGEXP -> V_STRING -> V_LENS */ +static struct value *lns_square(struct info *info, struct value *rxp, struct value *str) { + assert(rxp->tag == V_REGEXP); + assert(str->tag == V_STRING); + return lns_make_prim(L_SQUARE, ref(info), + ref(rxp->regexp), ref(str->string)); +} static struct value *make_exn_lns_error(struct info *info, struct lns_error *err, @@ -536,6 +546,7 @@ struct module *builtin_init(struct error *error) { DEFINE_NATIVE(modl, "label", 1, lns_label, T_STRING, T_LENS); DEFINE_NATIVE(modl, "seq", 1, lns_seq, T_STRING, T_LENS); DEFINE_NATIVE(modl, "counter", 1, lns_counter, T_STRING, T_LENS); + DEFINE_NATIVE(modl, "square", 2, lns_square, T_REGEXP, T_STRING, T_LENS); /* Applying lenses (mostly for tests) */ DEFINE_NATIVE(modl, "get", 2, lens_get, T_LENS, T_STRING, T_TREE); DEFINE_NATIVE(modl, "put", 3, lens_put, T_LENS, T_TREE, T_STRING, diff --git a/src/get.c b/src/get.c index a8f05e4..f947f52 100644 --- a/src/get.c +++ b/src/get.c @@ -556,6 +556,18 @@ static struct skel *parse_concat(struct lens *lens, struct state *state, return skel; } +void dump_regs(struct state *state); +void dump_regs(struct state *state){ + printf("state->nreg=%d\tstate->nregs->num_regs=%d\n", state->nreg, state->regs->num_regs); + for (int i=0; i<state->regs->num_regs;i++){ + const char *start = state->text + state->regs->start[i]; + uint size = state->regs->end[i] - state->regs->start[i]; + char *s = strndup(start, size); + printf("state->nregs->start=%d\tstate->nregs->end=%d %s\n", state->regs->start[i], state->regs->end[i], s); + free(s); + } +} + static struct tree *get_quant_star(struct lens *lens, struct state *state) { ensure0(lens->tag == L_STAR, state->info); struct lens *child = lens->child; @@ -568,6 +580,7 @@ static struct tree *get_quant_star(struct lens *lens, struct state *state) { state->regs = NULL; while (size > 0 && match(state, child, child->ctype, end, start) > 0) { + dump_regs(state); struct tree *t = NULL; t = get_lens(lens->child, state); @@ -682,6 +695,58 @@ static struct skel *parse_subtree(struct lens *lens, struct state *state, return make_skel(lens); } +static struct tree *get_square(struct lens *lens, struct state *state){ + ensure0(lens->tag == L_SQUARE, state->info); + dump_regs(state); + + char *key1 = NULL, *inner = NULL, *key2 = NULL; + + printf("nsub-total=%d %s\n", regexp_nsub(lens->ctype), lens->ctype->pattern->str); + printf("nsub-basic=%d %s\n", regexp_nsub(lens->regexp), lens->regexp->pattern->str); + // nreg for the key + size_t key_nreg = regexp_nsub(lens->regexp); + uint old_nreg = state->nreg; + state->nreg++; + // match the key + if (! REG_MATCHED(state)) + no_match_error(state, lens); + else + key1 = token(state); + + // match inner lens + state->nreg += 1 + key_nreg; + if (! REG_MATCHED(state)) + no_match_error(state, lens); + else + inner = token(state); + + // match again the key + state->nreg++; + if (! REG_MATCHED(state)) + no_match_error(state, lens); + else + key2 = token(state); + + state->nreg = old_nreg; + + printf("key1=%s inner=%s key2=%s\n", key1, inner, key2); + if (strcmp(key1,key2)==0){ + printf("key1 == key2\n"); + } else { + printf("key1 != key2\n"); + } + + state->key = key1; + free(inner); + free(key2); + return NULL; +} + +static struct skel *parse_square(struct lens *lens, struct state *state){ + ensure0(lens->tag == L_SQUARE, state->info); + return make_skel(lens); +} + /* * Helpers for recursive lenses */ @@ -1060,10 +1125,59 @@ static struct skel *parse_rec(struct lens *lens, struct state *state, } return skel; } +void print_lens(struct lens *lens); +void print_lens(struct lens *lens){ + const char *tag; + switch(lens->tag){ + case L_DEL: + tag = "L_DEL"; + break; + case L_STORE: + tag = "L_STORE"; + break; + case L_VALUE: + tag = "L_VALUE"; + break; + case L_KEY: + tag = "L_KEY"; + break; + case L_LABEL: + tag = "L_LABEL"; + break; + case L_SEQ: + tag = "L_SEQ"; + break; + case L_COUNTER: + tag = "L_COUNTER"; + break; + case L_CONCAT: + tag = "L_CONCAT"; + break; + case L_UNION: + tag = "L_UNION"; + break; + case L_SUBTREE: + tag = "L_SUBTREE"; + break; + case L_STAR: + tag = "L_STAR"; + break; + case L_MAYBE: + tag = "L_MAYBE"; + break; + case L_SQUARE: + tag = "L_SQUARE"; + break; + case L_REC: + tag = "L_REC"; + break; + } + printf("%s\n", tag); +} static struct tree *get_lens(struct lens *lens, struct state *state) { struct tree *tree = NULL; - + print_lens(lens); switch(lens->tag) { case L_DEL: tree = get_del(lens, state); @@ -1101,6 +1215,9 @@ static struct tree *get_lens(struct lens *lens, struct state *state) { case L_MAYBE: tree = get_quant_maybe(lens, state); break; + case L_SQUARE: + tree = get_square(lens, state); + break; default: BUG_ON(true, state->info, "illegal lens tag %d", lens->tag); break; @@ -1237,6 +1354,9 @@ static struct skel *parse_lens(struct lens *lens, struct state *state, case L_MAYBE: skel = parse_quant_maybe(lens, state, dict); break; + case L_SQUARE: + skel = parse_square(lens, state); + break; default: BUG_ON(true, state->info, "illegal lens tag %d", lens->tag); break; diff --git a/src/lens.c b/src/lens.c index 41fcd50..3d7cae0 100644 --- a/src/lens.c +++ b/src/lens.c @@ -54,7 +54,7 @@ static struct value *typecheck_maybe(struct info *info, struct lens *l); /* Lens names for pretty printing */ static const char *const tags[] = { - "del", "store", "value", "key", "label", "seq", "counter", + "del", "store", "value", "key", "label", "seq", "counter", "square", "concat", "union", "subtree", "star", "maybe", "rec" }; @@ -447,7 +447,7 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info, struct fa *fa_isect = NULL; /* Typecheck */ - if (tag == L_KEY) { + if (tag == L_KEY || tag == L_SQUARE) { exn = str_to_fa(info, "(.|\n)*/(.|\n)*", &fa_slash, regexp->nocase); if (exn != NULL) goto error; @@ -494,7 +494,7 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info, lens = make_lens(tag, info); lens->regexp = regexp; lens->string = string; - lens->key = (tag == L_KEY || tag == L_LABEL || tag == L_SEQ); + lens->key = (tag == L_KEY || tag == L_LABEL || tag == L_SEQ || tag == L_SQUARE); lens->value = (tag == L_STORE || tag == L_VALUE); lens->consumes_value = (tag == L_STORE || tag == L_VALUE); lens->atype = regexp_make_empty(info); @@ -502,6 +502,17 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info, if (tag == L_DEL || tag == L_STORE || tag == L_KEY) { lens->ctype = ref(regexp); lens->ctype_nullable = regexp_matches_empty(lens->ctype); + } else if (tag == L_SQUARE) { + struct regexp *rx[3]; + struct regexp *inner = make_regexp_literal(info, string->str); + rx[0] = regexp; + rx[1] = inner; + rx[2] = regexp; + struct regexp *r = regexp_concat_n(info, 3, rx); + printf("L_SQUARE->ctype=%s\n",r->pattern->str); + lens->ctype = r; + lens->ctype_nullable = regexp_matches_empty(lens->ctype); + unref(inner, regexp); } else if (tag == L_LABEL || tag == L_VALUE || tag == L_SEQ || tag == L_COUNTER) { lens->ctype = regexp_make_empty(info); @@ -518,7 +529,7 @@ struct value *lns_make_prim(enum lens_tag tag, struct info *info, make_regexp_from_string(info, (struct string *) digits_pat); if (lens->ktype == NULL) goto error; - } else if (tag == L_KEY) { + } else if (tag == L_KEY || tag == L_SQUARE) { lens->ktype = restrict_regexp(lens->regexp); } else if (tag == L_LABEL) { lens->ktype = make_regexp_literal(info, lens->string->str); @@ -826,6 +837,10 @@ void free_lens(struct lens *lens) { jmt_free(lens->jmt); } break; + case L_SQUARE: + unref(lens->regexp, regexp); + unref(lens->string, string); + break; default: BUG_LENS_TAG(lens); break; diff --git a/src/lens.h b/src/lens.h index 7c2b6ce..bb848ea 100644 --- a/src/lens.h +++ b/src/lens.h @@ -40,7 +40,8 @@ enum lens_tag { L_SUBTREE, L_STAR, L_MAYBE, - L_REC + L_REC, + L_SQUARE }; /* A lens. The way the type information is computed is a little @@ -87,9 +88,10 @@ struct lens { unsigned int ctype_nullable : 1; union { /* Primitive lenses */ - struct { /* L_DEL uses both */ - struct regexp *regexp; /* L_STORE, L_KEY */ - struct string *string; /* L_VALUE, L_LABEL, L_SEQ, L_COUNTER */ + struct { /* L_DEL uses both */ + struct regexp *regexp; /* L_STORE, L_KEY */ + struct string *string; /* L_VALUE, L_LABEL, L_SEQ, L_COUNTER */ + struct lens *content; /* L_SQUARE */ }; /* Combinators */ struct lens *child; /* L_SUBTREE, L_STAR, L_MAYBE */ diff --git a/src/put.c b/src/put.c index 7c72dd1..263eb11 100644 --- a/src/put.c +++ b/src/put.c @@ -627,6 +627,9 @@ static void put_lens(struct lens *lens, struct state *state) { case L_REC: put_rec(lens, state); break; + case L_SQUARE: + fprintf(state->out, "%s%s%s", state->key, lens->string->str, state->key); + break; default: assert(0); break; @@ -749,6 +752,9 @@ static void create_lens(struct lens *lens, struct state *state) { case L_REC: create_rec(lens, state); break; + case L_SQUARE: + fprintf(state->out, "%s%s%s", state->key, lens->string->str, state->key); + break; default: assert(0); break; diff --git a/tests/modules/pass_square.aug b/tests/modules/pass_square.aug new file mode 100644 index 0000000..141b44c --- /dev/null +++ b/tests/modules/pass_square.aug @@ -0,0 +1,7 @@ +module Pass_square = + +let y = [ square /[a-b]*/ "zz" . del "x" "x" ] * +test y get "aazzaaaxbbzzbbx" = { "aa" }{ "bb" } + +test y get "azzax" = { "a" } +test y put "azzax" after clear "/b" = "azzaxbzzbx" -- 1.7.0.4
_______________________________________________ augeas-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/augeas-devel
