[augeas-devel] [PATCH 2/3] Use precise ctype of a square lens if it is indeed regular
lutter at redhat.com
lutter at redhat.com
Tue Oct 23 23:25:28 UTC 2012
From: David Lutterkort <lutter at redhat.com>
---
src/get.c | 48 +++++++++++++++++++++++++++++----------------
src/lens.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 94 insertions(+), 17 deletions(-)
diff --git a/src/get.c b/src/get.c
index 535c6fe..a7ee565 100644
--- a/src/get.c
+++ b/src/get.c
@@ -862,31 +862,31 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
struct lens *concat = lens->child;
struct tree *tree = NULL;
- struct lens *curr;
+ struct re_registers *old_regs = state->regs;
uint old_nreg = state->nreg;
- uint nreg = state->nreg;
- uint nsub, i;
+ uint end = REG_END(state);
+ uint start = REG_START(state);
char *rsqr = NULL, *lsqr = NULL;
- uint start, end;
+ int r;
+
+ r = match(state, lens->child, lens->child->ctype, end, start);
+ ERR_NOMEM(r < 0, state->info);
tree = get_lens(lens->child, state);
/* retrieve left component */
- nreg = old_nreg + 1;
- start = state->regs->start[nreg];
- end = state->regs->end[nreg];
+ state->nreg = 1;
+ start = REG_START(state);
+ end = REG_END(state);
lsqr = token_range(state->text, start, end);
/* retrieve right component */
/* compute nreg for the last children */
- nreg = old_nreg + 1;
- for (i = 0; i < concat->nchildren - 1; i++) {
- curr = concat->children[i];
- nsub = regexp_nsub(curr->ctype);
- nreg += 1 + nsub;
- }
- start = state->regs->start[nreg];
- end = state->regs->end[nreg];
+ for (int i = 0; i < concat->nchildren - 1; i++)
+ state->nreg += 1 + regexp_nsub(concat->children[i]->ctype);
+
+ start = REG_START(state);
+ end = REG_END(state);
rsqr = token_range(state->text, start, end);
if (!square_match(lens, lsqr, rsqr)) {
@@ -897,7 +897,9 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
}
done:
+ free_regs(state);
state->nreg = old_nreg;
+ state->regs = old_regs;
FREE(lsqr);
FREE(rsqr);
return tree;
@@ -911,14 +913,26 @@ static struct tree *get_square(struct lens *lens, struct state *state) {
static struct skel *parse_square(struct lens *lens, struct state *state,
struct dict **dict) {
ensure0(lens->tag == L_SQUARE, state->info);
- struct skel *skel, *sk;
+ struct re_registers *old_regs = state->regs;
+ uint old_nreg = state->nreg;
+ uint end = REG_END(state);
+ uint start = REG_START(state);
+ struct skel *skel = NULL, *sk = NULL;
+ int r;
+
+ r = match(state, lens->child, lens->child->ctype, end, start);
+ ERR_NOMEM(r < 0, state->info);
- skel = parse_concat(lens->child, state, dict);
+ skel = parse_lens(lens->child, state, dict);
if (skel == NULL)
return NULL;
sk = make_skel(lens);
sk->skels = skel;
+ error:
+ free_regs(state);
+ state->regs = old_regs;
+ state->nreg = old_nreg;
return sk;
}
diff --git a/src/lens.c b/src/lens.c
index 3e99159..58256ed 100644
--- a/src/lens.c
+++ b/src/lens.c
@@ -400,6 +400,66 @@ struct value *lns_make_maybe(struct info *info, struct lens *l, int check) {
return make_lens_value(lens);
}
+/* The ctype of SQR is a regular approximation of the true ctype of SQR
+ * at this point. In some situations, for example in processing quoted
+ * strings this leads to false typecheck errors; to lower the chances
+ * of these, we try to construct the precise ctype of SQR if the
+ * language of L1 is finite (and has a small number of words)
+ */
+static void square_precise_type(struct info *info,
+ struct regexp **sqr,
+ struct regexp *left,
+ struct regexp *body) {
+
+ char **words = NULL;
+ int nwords = 0, r;
+ struct fa *fa = NULL;
+ struct value *exn = NULL;
+ struct regexp **u = NULL, *c[3], *w = NULL;
+
+ exn = str_to_fa(info, left->pattern->str, &fa, left->nocase);
+ if (exn != NULL)
+ goto error;
+
+ nwords = fa_enumerate(fa, 10, &words); /* The limit of 10 is arbitrary */
+ if (nwords < 0)
+ goto error;
+
+ r = ALLOC_N(u, nwords);
+ ERR_NOMEM(r < 0, info);
+
+ c[1] = body;
+ for (int i=0; i < nwords; i++) {
+ w = make_regexp_literal(left->info, words[i]);
+ ERR_NOMEM(w == NULL, info);
+ w->nocase = left->nocase;
+
+ c[0] = c[2] = w;
+ u[i] = regexp_concat_n(info, 3, c);
+
+ unref(w, regexp);
+ ERR_NOMEM(u[i] == NULL, info);
+ }
+ w = regexp_union_n(info, nwords, u);
+ if (w != NULL) {
+ unref(*sqr, regexp);
+ *sqr = w;
+ w = NULL;
+ }
+
+ error:
+ unref(w, regexp);
+ for (int i=0; i < nwords; i++) {
+ free(words[i]);
+ if (u != NULL)
+ unref(u[i], regexp);
+ }
+ free(words);
+ free(u);
+ fa_free(fa);
+ unref(exn, value);
+}
+
/* Build a square lens as
* left . body . right
* where left and right accepts the same language and
@@ -433,6 +493,9 @@ struct value * lns_make_square(struct info *info, struct lens *l1,
for (int t=0; t < ntypes; t++)
ltype(sqr, t) = ref(ltype(cnt2->lens, t));
+
+ square_precise_type(info, &(sqr->ctype), l1->ctype, l2->ctype);
+
sqr->recursive = cnt2->lens->recursive;
sqr->rec_internal = cnt2->lens->rec_internal;
sqr->consumes_value = cnt2->lens->consumes_value;
--
1.7.7.6
More information about the augeas-devel
mailing list