diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-12-27 07:36:01 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-12-27 07:36:01 -0800 |
commit | f9bcbd884bb1cd60144f13df3de00516b731827c (patch) | |
tree | 0d8f9badb6203c43652853bf8c127f8b1cc53114 /match.c | |
parent | 8ccf4c0a9076c957a5ed58f6ccc6ede7f71644a3 (diff) | |
download | txr-f9bcbd884bb1cd60144f13df3de00516b731827c.tar.gz txr-f9bcbd884bb1cd60144f13df3de00516b731827c.tar.bz2 txr-f9bcbd884bb1cd60144f13df3de00516b731827c.zip |
txr: do not ignore regex in positive match.
* match.c (h_var): Refactor the logic here a bit. Without
regard for whether the variable has a value, we dispatch the
regex, fixed field and function cases. These handle the
binding against the existing value. Then before all other
cases, we check for the existing value and convert that to a
literal text match. The effect of this is that now the regular
expression is processed even if the variable has a value.
* tests/010/span-var.txr: Last two test cases hardened a bit
so they cannot fall through to a successful exit, if
they invoke the wrong case. This is not related to this
change. New test cases for regex span.
* txr.1: Updated documentation and compatibility notes.
Diffstat (limited to 'match.c')
-rw-r--r-- | match.c | 56 |
1 files changed, 17 insertions, 39 deletions
@@ -843,41 +843,8 @@ static val h_var(match_line_ctx *c) modifier = cdr(mpair); } - if (pair && !consp(modifier)) { - /* Except in two cass, if the variable already has a binding, we replace - it with its value, and treat it as a string match. And if the spec looks - like ((var <sym>) <next> ...) and it must be transformed into - (<sym-substituted> <next> ...). - The special cases are: - - if the variable is a fix sized field match, then it has to match - that much text; - - if the variable is a function-spanning match, the function has - to be called every time; hence he !consp(modifier) check above, - and the use of dest_bind in the function spanning case. */ - if (integerp(modifier)) { - val past = plus(c->pos, modifier); - - if (length_str_lt(c->dataline, past) || lt(past, c->pos)) - { - LOG_MISMATCH("fixed field size"); - return nil; - } - - if (!tree_find(trim_str(sub_str(c->dataline, c->pos, past)), - cdr(pair), equal_f)) - { - LOG_MISMATCH("fixed field contents"); - return nil; - } - - LOG_MATCH("fixed field", past); - c->pos = past; - c->specline = rest(c->specline); - } else { - c->specline = rlcp(cons(cdr(pair), c->specline), c->specline); - } - return repeat_spec_k; - } else if (consp(modifier) || regexp(modifier)) { /* var bound over text matched by form */ + if (consp(modifier) || regexp(modifier)) { + /* var bound over text matched by regex or function */ cons_bind (new_bindings, new_pos, match_line(ml_specline(*c, cons(modifier, nil)))); @@ -888,13 +855,12 @@ static val h_var(match_line_ctx *c) new_pos = minus(new_pos, c->base); - LOG_MATCH("var spanning form", new_pos); c->bindings = dest_bind(c->specline, new_bindings, sym, sub_str(c->dataline, c->pos, new_pos), equal_f); if (c->bindings == t) { - LOG_MISMATCH("function span mismatch"); + LOG_MISMATCH("span mismatch"); return nil; } @@ -912,8 +878,15 @@ static val h_var(match_line_ctx *c) return nil; } LOG_MATCH("count based var", past); - if (sym) - c->bindings = acons(sym, trim_str(sub_str(c->dataline, c->pos, past)), c->bindings); + + c->bindings = dest_bind(c->specline, c->bindings, sym, + trim_str(sub_str(c->dataline, c->pos, past)), + equal_f); + if (c->bindings == t) { + LOG_MISMATCH("count based mismatch"); + return nil; + } + c->pos = past; /* This may have another variable attached */ if (next) { @@ -923,6 +896,11 @@ static val h_var(match_line_ctx *c) } else if (modifier && modifier != t) { sem_error(elem, lit("invalid modifier ~s on variable ~s"), modifier, sym, nao); + } else if ((pair = if2(sym, tx_lookup_var(sym, c->bindings)))) { + /* Variable is not of the above types and has an existing binding, + * Just substitute its value into the spec stream and match. */ + c->specline = rlcp(cons(cdr(pair), c->specline), c->specline); + return repeat_spec_k; } else if (next == nil) { /* no modifier, no elem -> to end of line */ if (sym) c->bindings = acons(sym, sub_str(c->dataline, c->pos, nil), c->bindings); |