diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | match.c | 21 | ||||
-rw-r--r-- | txr.1 | 46 |
3 files changed, 46 insertions, 34 deletions
@@ -1,3 +1,16 @@ +2014-08-13 Kaz Kylheku <kaz@kylheku.com> + + Fix regression in previous change: we must match a compound text + element whole, and not break it up. + + * match.c (search_match): Take a spec argument. + (h_var): Turn a text element into a one-element spec and process + with search_match. + + * txr.1: Updated text about matching of variables + followed by a directive or function, and about consecutive + variables via directive. + 2014-08-12 Kaz Kylheku <kaz@kylheku.com> When a variable is delimited by some form other than @@ -450,9 +450,8 @@ static void consume_prefix(match_line_ctx *c) } -static val search_match(match_line_ctx *c, val from_end) +static val search_match(match_line_ctx *c, val from_end, val spec) { - val spec = c->specline; val pos = from_end ? length_str(c->dataline) : c->pos; val step = from_end ? negone : one; @@ -640,11 +639,17 @@ static val h_var(match_line_ctx *c) return repeat_spec_k; } } else if (op == text_s) { - /* Clumped texts: break out the first one. */ - val text_elem = rlcp(second(next), c->specline); - val rest_texts = cons(text_s, rest(rest(next))); - c->specline = cons(elem, cons(text_elem, - cons(rest_texts, rest(c->specline)))); + val text_only_spec = cons(next, nil); + val find = search_match(c, modifier, text_only_spec); + val fpos = car(find); + if (!find) { + LOG_MISMATCH("var delimiting text compound"); + return nil; + } + LOG_MATCH("var delimiting text compound", fpos); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, fpos), c->bindings); + c->pos = fpos; return repeat_spec_k; } else if (consp(op) || stringp(op)) { cons_bind (find, len, search_str_tree(c->dataline, next, c->pos, modifier)); @@ -656,7 +661,7 @@ static val h_var(match_line_ctx *c) c->bindings = acons(sym, sub_str(c->dataline, c->pos, find), c->bindings); c->pos = plus(find, len); } else { - val find = search_match(c, modifier); + val find = search_match(c, modifier, c->specline); val fpos = car(find); if (!find) { LOG_MISMATCH("var delimiting spec"); @@ -722,32 +722,28 @@ text which is bound to FOO. .SS Variable Followed by a Function Call or Directive If the variable is followed by a function call, or a directive, the extent is -determined by scanning the text for the first position where a match occurs for -the regular expression, call or directive. (For a description of functions, +determined by scanning the text for the first position where a match occurs +for the entire remainder of the line. (For a description of functions, see FUNCTIONS.) -Note that the given variable and the function or directive are considered -in isolation. This means, for instance, that @var@(skip)text is a degenerate -form. The @(skip) will be processed alone, without regard for the trailing -text and so consume the input to the end of the line. The right way to -express the most probable intent of this is @{var}text. - -Another degenerate case is @var@(bind ...), or in general, a variable -followed by some directive not used for matching text. Watch out for -the following pitfall: +For example: - @a @b@(bind have_ab "y") + @foo@(bind a "abc")xyz -The intent here is that the variable b captures everything after the space to -the end of the line, and then the variable have_ab is set to "y". But since -@(bind) always succeeds, b captures an empty string, and then the whole line -fails if there is any material after the space. The right way to do this is: +Here, foo will match the text from the current position to where "xyz" +occurs, even though there is a @(bind) directive. Furthermore, if +more material is added after the xyz, it is part of the search. +Note the difference between the following two: - @a @b@(eol)@(bind have_ab "y") + @foo@/abc/@(func) + @foo@(func)@/abc/ -That is to say, match an explicit @(eol) after the variable. This will -search for the end of the line and capture the spanning text into b, as -intended. The bind then happens afterward. +In the first example, the variable foo matches the text from the current +position until the match for the regular expression abc. @(func) is not +considered when processing @foo. In the second example, the variable foo +matches the text from the current position until the position whcih matches +the function call, followed by a match for the regular expression. +The entire sequence @(func)@/abc/ is considered. .SS Consecutive Variables @@ -810,12 +806,10 @@ following example: @var1@(all)@var2@(end) -The @(all) directive does nothing other than assert that all clauses must -match. It has only one clause, @var2. So this is equivalent to just @var1@var2, -except that if both variables are unbound, no semantic error is identified in -this situation. Such a situation is handled as a variable followed by a -directive. Of course @var2 matches everything at the current position, and so -@var1 ends up with nothing. +This is treated just like the variable followed by directive. No semantic +error is identified, even if both variables are unbound. Here, @var2 +@var2 matches everything at the current position, and so @var1 ends up +bound to the empty string. Example 1: b matches at position 0 and a gets nothing: |