Hi Frank,
I have a slightly shorter program from this:
$ txr -B -c '@(gather)
@{A /a/}
@{B /b/}
@(and)
@(line l1)
@X
@(line l2)
@Y
@(line l3)
@(end)'
a
b
[Ctrl-D][Enter]
false
If we supply the input
a
x
b
where x is any content whatsoever, then it works. The reason is this
[Doc quote]:
How gather works is that the text is searched for matches for
the sin‐
gle line and multi-line queries. The clauses are applied in the
order
in which they appear. Whenever one of the clauses matches, any
bind‐
ings it produces are retained and it is removed from further
considera‐
tion. Multiple clauses can match at the same text position. The
posi‐
tion advances by the longest match from among the clauses
which
matched. If no clauses match, the position advances by one
line. The
search stops when all clauses are eliminated, and then the
cumulative
bindings are produced. If the data runs out, but unmatched
clauses
remain, the directive fails.
The key requirement above is "The position advances by the longest match
from
among the clauses which matched".
When the lines ("a" "b") match the multi-line block, both lines are
consumed.
At that time, there is no match for the b variable. In the subsequent
iteration,
the @{b /b/} doesn't have an opportunity to match the "b" line because
it has
been consumed by the block match. So @(gather) is still missing the "b"
match
and looking for it in any subsequent material.
This is where the @(trailer) directive comes in handy:
$ txr -B -c '@(gather)
@{A /a/}
@{B /b/}
@(and)
@(line l1)
@X
@X
@(line l2)
@Y
@(line l3)
@(end)'
a
b
[Ctrl-D][Enter]
A="a"
l1="1"
X="a"
l2="2"
Y="b"
l3="3"
B="b"
Now we have a two-line match, which advances only by one line.
@(trailer) and its name were inspired by trailing contexts in Lex.
(And they are used in TXR's parse.l source file).
Cheers ...