@c =================================================================== @c
@c    serrano/prgm/project/bigloo/manuals/pregexp.texi                 @c
@c    ------------------------------------------------------------     @c
@c    Author      :  Dorai Sitaram                                     @c
@c    Creation    :  Mon Nov 12 10:21:58 2001                          @c
@c    Last change :  Wed Dec  5 14:52:29 2001 (serrano)                @c
@c    Copyright   :  2001 Dorai Sitaram                                @c
@c    ------------------------------------------------------------     @c
@c    The documentation for pregexp                                    @c
@c =================================================================== @c

@c ------------------------------------------------------------------- @c
@c    Rgc                                                              @c
@c ------------------------------------------------------------------- @c
@node Posix Regular Expressions, ,Date, Standard Library
@comment  node-name,  next,  previous,  up
@section Posix Regular Expressions
@cindex Regular expressions

This whole section has been written by @b{Dorai Sitaram}. 
It consists in the documentation of the @code{pregexp} package that may be 
found at @url{http://www.ccs.neu.edu/~dorai/pregexp/pregexp.html}.

@sp 1

The regexp notation supported is modeled on Perl's, and includes such
powerful directives as numeric and nongreedy quantifiers, capturing and
non-capturing clustering, POSIX character classes, selective case- and
space-insensitivity, backreferences, alternation, backtrack pruning,
positive and negative lookahead and lookbehind, in addition to the more
basic directives familiar to all regexp users.  A @emph{regexp} is a
string that describes a pattern.  A regexp matcher tries to @emph{match}
this pattern against (a portion of) another string, which we will call
the @emph{text string}.  The text string is treated as raw text and not
as a pattern.

Most of the characters in a regexp pattern are meant to match
occurrences of themselves in the text string.  Thus, the pattern
@code{"abc"} matches a string that contains the characters @code{a}, @code{b},
@code{c} in succession.

In the regexp pattern, some characters  act as 
@emph{metacharacters}, and some character sequences act as
@emph{metasequences}.  That is, they specify something
other than their literal selves.  For example, in the
pattern @code{"a.c"}, the characters @code{a} and @code{c} do
stand for themselves but the @emph{metacharacter} @code{.}
can match @emph{any} character (other than
newline).  Therefore, the pattern @code{"a.c"}
matches an @code{a}, followed by @emph{any} character,
followed by a @code{c}. 

If we needed to match the character @code{.} itself,
we @emph{escape} it, ie, precede it with a backslash
(@code{\}).  The character sequence @code{\.} is thus a 
@emph{metasequence}, since it doesn't match itself but rather
just @code{.}.  So, to match @code{a} followed by a literal
@code{.} followed by @code{c}, we use the regexp pattern
@code{"a\\.c"}.@footnote{The double backslash is an artifact of
Scheme strings, not the regexp pattern itself.  When we
want a literal backslash inside a Scheme string, we
must escape it so that it shows up in the string at
all. Scheme strings use backslash as the escape
character, so we end up with two backslashes --- one
Scheme-string backslash to escape the regexp backslash,
which then escapes the dot.  Another character that
would need escaping inside a Scheme string is @code{"}.}
Another example of a metasequence is @code{\t}, which is a
readable way to represent the tab character.

We will call the string representation of a regexp the
@emph{U-regexp}, where @emph{U} can be taken to mean @emph{Unix-style} or 
@emph{universal}, because this
notation for regexps is universally familiar.  Our
implementation uses an intermediate tree-like
representation called the @emph{S-regexp}, where @emph{S}
can stand for @emph{Scheme}, @emph{symbolic}, or 
@emph{s-expression}.  S-regexps are more verbose
and less readable than U-regexps, but they are much
easier for Scheme's recursive procedures to navigate. 

@menu
* Regular Expressions Procedures::
* The Regular Expressions Pattern Language::
* An Extended Example::
@end menu

@c ------------------------------------------------------------------- @c
@c    Posix regular expressions procedures                             @c
@c ------------------------------------------------------------------- @c
@node Regular Expressions Procedures, The Regular Expressions Pattern Language, , Posix Regular Expressions
@subsection Regular Expressions Procedures

Four procedures @code{pregexp}, @code{pregexp-match-positions},
@code{pregexp-match}, @code{pregexp-replace}, and
@code{pregexp-replace*} enable compilation and matching of regular
expressions.

@deffn {bigloo procedure} pregexp U-regexp
The procedure @code{pregexp} takes a U-regexp, which is a
string, and returns an S-regexp, which is a tree.  

@smalllisp
(pregexp "c.r") @result{} (:sub (:or (:seq #\c :any #\r)))
@end smalllisp

@noindent There is rarely any need to look at the S-regexps 
returned by @code{pregexp}.
@end deffn


@deffn {bigloo procedure} pregexp-match-positions regexp string

The procedure @code{pregexp-match-positions} takes a
regexp pattern and a text string, and returns a @emph{match} 
if the pattern @emph{matches} the text string.
The pattern may be either a U- or an S-regexp.
(@code{pregexp-match-positions} will internally compile a
U-regexp to an S-regexp before proceeding with the
matching.  If you find yourself calling
@code{pregexp-match-positions} repeatedly with the same
U-regexp, it may be advisable to explicitly convert the
latter into an S-regexp once beforehand, using
@code{pregexp}, to save needless recompilation.)

@code{pregexp-match-positions} returns @code{#f} if the pattern did not
match the string; and a list of @emph{index pairs} if it
did match. Eg,

@smalllisp
(pregexp-match-positions "brain" "bird")
 @result{} #f
(pregexp-match-positions "needle" "hay needle stack")
 @result{} ((4 . 10))
@end smalllisp

@noindent In the second example, the integers 4 and 10 identify
the substring that was matched. 1 is the starting
(inclusive) index and 2 the ending (exclusive) index of
the matching substring.

@smalllisp
(substring "hay needle stack" 4 10)
 @result{} "needle"
@end smalllisp

Here, @code{pregexp-match-positions}'s return list contains only 
one index pair, and that pair represents the entire
substring matched by the regexp.  When we discuss
@emph{subpatterns} later, we will see how a single match
operation can yield a list of @emph{submatches}.

@code{pregexp-match-positions} takes optional third
and fourth arguments that specify the indices of
the text string within which the matching should
take place.   

@smalllisp
(pregexp-match-positions "needle" 
  "his hay needle stack -- my hay needle stack -- her hay needle stack"
  24 43)
 @result{} ((31 . 37))
@end smalllisp

Note that the returned indices are still reckoned
relative to the full text string.  
@end deffn

@deffn {bigloo procedure} pregexp-match regexp string
The procedure @code{pregexp-match} is called like 
@code{pregexp-match-positions}
but instead of returning index pairs it returns the
matching substrings:

@smalllisp
(pregexp-match "brain" "bird")
 @result{} #f
(pregexp-match "needle" "hay needle stack")
 @result{} ("needle")
@end smalllisp

@code{pregexp-match} also takes optional third and
fourth arguments, with the same meaning as does
@code{pregexp-match-positions}.
@end deffn

@deffn {bigloo procedure} pregexp-replace regexp string1 string2
The procedure @code{pregexp-replace} replaces the
matched portion of the text string by another
string.  The first argument is the regexp,
the second the text string, and the third
is the @emph{insert string} (string to be inserted).

@smalllisp
(pregexp-replace "te" "liberte" "ty") 
 @result{} "liberty"
@end smalllisp

If the pattern doesn't occur in the text string, the returned string is 
identical (@code{eq?}) to the text string.
@end deffn

@deffn {bigloo procedure} pregexp-replace* regexp string1 string2
The procedure @code{pregexp-replace*} replaces @emph{all} matches in the
text string by the insert string:

@smalllisp
(pregexp-replace* "te" "liberte egalite fraternite" "ty")
 @result{} "liberty egality fratyrnity"
@end smalllisp

As with @code{pregexp-replace}, if the pattern doesn't occur in the text
string, the returned string is identical (@code{eq?}) to the text string.
@end deffn

@deffn {bigloo procedure} pregexp-split regexp string
The procedure @code{pregexp-split} takes two arguments, a
regexp pattern and a text string, and returns a list of
substrings of the text string, where the pattern identifies the 
delimiter separating the substrings.

@smalllisp
(pregexp-split ":" "/bin:/usr/bin:/usr/bin/X11:/usr/local/bin")
 @result{} ("/bin" "/usr/bin" "/usr/bin/X11" "/usr/local/bin")

(pregexp-split " " "pea soup")
 @result{} ("pea" "soup")
@end smalllisp

If the first argument can match an empty string, then
the list of all the single-character substrings is returned.

@smalllisp
(pregexp-split "" "smithereens")
 @result{} ("s" "m" "i" "t" "h" "e" "r" "e" "e" "n" "s")
@end smalllisp

To identify one-or-more spaces as the delimiter,
take care to use the regexp @code{" +"}, not @code{" *"}.

@smalllisp
(pregexp-split " +" "split pea     soup")
 @result{} ("split" "pea" "soup")

(pregexp-split " *" "split pea     soup")
 @result{} ("s" "p" "l" "i" "t" "p" "e" "a" "s" "o" "u" "p")
@end smalllisp
@end deffn

@deffn {bigloo procedure} regexp-quote string

The procedure @code{pregexp-quote} takes an arbitrary @var{string} and 
returns a U-regexp (string) that precisely represents it. In particular, 
characters in the input string that could serve as regexp metacharacters are 
escaped with a backslash, so that they safely match only themselves.

@smalllisp
(pregexp-quote "cons")
 @result{} "cons"

(pregexp-quote "list?")
 @result{} "list\\?"
@end smalllisp

@code{pregexp-quote} is useful when building a composite regexp 
from a mix of regexp strings and verbatim strings. 
@end deffn

@c ------------------------------------------------------------------- @c
@c    Posix regular expressions language                               @c
@c ------------------------------------------------------------------- @c
@node The Regular Expressions Pattern Language, An Extended Example, Regular Expressions Procedures, Posix Regular Expressions
@subsection Regular Expressions Pattern Language

@menu
* Basic assertions::
* Characters and character classes::
* Quantifiers::
* Clusters::
* Alternation::
* Backtracking::
* Looking ahead and behind::
@end menu

Here is a complete description of the regexp pattern
language recognized by the @code{pregexp} procedures.

@node Basic assertions, Characters and character classes, ,The Regular Expressions Pattern Language
@subsubsection Basic assertions

The @emph{assertions} @code{^} and @code{$} identify the beginning and
the end of the text string respectively.  They ensure that their
adjoining regexps match at one or other end of the text string.
Examples:

@smalllisp
(pregexp-match-positions "^contact" "first contact") @result{} #f 
@end smalllisp

@noindent The regexp fails to match because @code{contact} does not
occur at the beginning of the text string.

@smalllisp
(pregexp-match-positions "laugh$" "laugh laugh laugh laugh") @result{} ((18 . 23))
@end smalllisp

@noindent The regexp matches the @emph{last} @code{laugh}.

The metasequence @code{\b} asserts that
a @emph{word boundary} exists. 

@smalllisp
(pregexp-match-positions "yack\\b" "yackety yack") @result{} ((8 . 12))
@end smalllisp

@noindent The @code{yack} in @code{yackety} doesn't end at a word
boundary so it isn't matched.  The second @code{yack} does and is.

The metasequence @code{\B} has the opposite effect to @code{\b}.  It
asserts that a word boundary does not exist.

@smalllisp
(pregexp-match-positions "an\\B" "an analysis") @result{} ((3 . 5))
@end smalllisp

@noindent The @code{an} that doesn't end in a word boundary
is matched.

@node Characters and character classes, Quantifiers, Basic assertions, The Regular Expressions Pattern Language
@subsubsection Characters and character classes

Typically a character in the regexp matches the same character in the
text string.  Sometimes it is necessary or convenient to use a regexp
metasequence to refer to a single character.  Thus, metasequences
@code{\n}, @code{\r}, @code{\t}, and @code{\.}  match the newline,
return, tab and period characters respectively.

The @emph{metacharacter} period (@code{.}) matches
@emph{any} character other than newline.

@smalllisp
(pregexp-match "p.t" "pet") @result{} ("pet")
@end smalllisp

@noindent It also matches @code{pat}, @code{pit}, @code{pot}, @code{put},
and @code{p8t} but not @code{peat} or @code{pfffft}.

A @emph{character class} matches any one character from a set of
characters.  A typical format for this is the @emph{bracketed character
class} @code{[}...@code{]}, which matches any one character from the
non-empty sequence of characters enclosed within the
brackets.@footnote{Requiring a bracketed character class to be non-empty is not
a limitation, since an empty character class can be more easily
represented by an empty string.}  Thus @code{"p[aeiou]t"} matches
@code{pat}, @code{pet}, @code{pit}, @code{pot}, @code{put} and nothing
else.

Inside the brackets, a hyphen (@code{-}) between two characters
specifies the ascii range between the characters.  Eg,
@code{"ta[b-dgn-p]"} matches @code{tab}, @code{tac}, @code{tad},
@emph{and} @code{tag}, @emph{and} @code{tan}, @code{tao}, @code{tap}.

An initial caret (@code{^}) after the left bracket inverts the set
specified by the rest of the contents, ie, it specifies the set of
characters @emph{other than} those identified in the brackets.  Eg,
@code{"do[^g]"} matches all three-character sequences starting with
@code{do} except @code{dog}.

Note that the metacharacter @code{^} inside brackets means something
quite different from what it means outside.  Most other metacharacters
(@code{.}, @code{*}, @code{+}, @code{?}, etc) cease to be metacharacters
when inside brackets, although you may still escape them for peace of
mind.  @code{-} is a metacharacter only when it's inside brackets, and
neither the first nor the last character.

Bracketed character classes cannot contain other bracketed character
classes (although they contain certain other types of character classes
--- see below).  Thus a left bracket (@code{[}) inside a bracketed
character class doesn't have to be a metacharacter; it can stand for
itself.  Eg, @code{"[a[b]"} matches @code{a}, @code{[}, and @code{b}.

Furthermore, since empty bracketed character classes are disallowed, a
right bracket (@code{]}) immediately occurring after the opening left
bracket also doesn't need to be a metacharacter.  Eg, @code{"[]ab]"}
matches @code{]}, @code{a}, and @code{b}.

@subsubsection Some frequently used character classes

Some standard character classes can be conveniently represented as
metasequences instead of as explicit bracketed expressions.  @code{\d}
matches a digit (@code{[0-9]}); @code{\s} matches a whitespace
character; and @code{\w} matches a character that could be part of a
``word''.@footnote{Following regexp custom, we identify ``word'' characters as
@code{[A-Za-z0-9_]}, although these are too restrictive for what a
Schemer might consider a ``word''.}

The upper-case versions of these metasequences stand for the inversions
of the corresponding character classes.  Thus @code{\D} matches a
non-digit, @code{\S} a non-whitespace character, and @code{\W} a
non-``word'' character.

Remember to include a double backslash when putting these metasequences
in a Scheme string:

@smalllisp
(pregexp-match "\\d\\d" "0 dear, 1 have 2 read catch 22 before 9") @result{} ("22")
@end smalllisp

These character classes can be used inside 
a bracketed expression.  Eg,
@code{"[a-z\\d]"} matches a lower-case letter
or a digit.

@subsubsection POSIX character classes

A @emph{POSIX character class} is a special metasequence
of the form @code{[:}...@code{:]} that can be used only
inside a bracketed expression.  The POSIX classes
supported are  

@smallexample
@code{[:alnum:]}  letters and digits 
@code{[:alpha:]}  letters  
@code{[:algor:]}  the letters @code{c}, @code{h}, @code{a} and @code{d} 
@code{[:ascii:]}  7-bit ascii characters 
@code{[:blank:]}  widthful whitespace, ie, space and tab 
@code{[:cntrl:]}  ``control'' characters, viz, those with code @code{<} 32 
@code{[:digit:]}  digits, same as @code{\d} 
@code{[:graph:]}  characters that use ink 
@code{[:lower:]}  lower-case letters 
@code{[:print:]}  ink-users plus widthful whitespace  
@code{[:space:]}  whitespace, same as @code{\s} 
@code{[:upper:]}  upper-case letters 
@code{[:word:]}   letters, digits, and underscore, same as @code{\w} 
@code{[:xdigit:]} hex digits 
@end smallexample

@noindent For example, the regexp  @code{"[[:alpha:]_]"}
matches a letter or underscore.  

@smalllisp
(pregexp-match "[[:alpha:]_]" "--x--") @result{} ("x")
(pregexp-match "[[:alpha:]_]" "--_--") @result{} ("_")
(pregexp-match "[[:alpha:]_]" "--:--") @result{} #f
@end smalllisp

The POSIX class notation is valid @emph{only} inside a
bracketed expression.  For instance, @code{[:alpha:]},
when not inside a bracketed expression, will @emph{not}
be read as the letter class.
Rather it is (from previous principles) the character
class containing the characters @code{:}, @code{a}, @code{l},
@code{p}, @code{h}.

@smalllisp
(pregexp-match "[:alpha:]" "--a--") @result{} ("a")
(pregexp-match "[:alpha:]" "--_--") @result{} #f
@end smalllisp

By placing a caret (@code{^}) immediately after
@code{[:}, you get the inversion of that POSIX
character class.  Thus, @code{[:^alpha]} 
is the class containing all characters 
except the letters.

@node Quantifiers, Clusters, Characters and character classes, The Regular Expressions Pattern Language
@subsubsection Quantifiers

The @emph{quantifiers} @code{*}, @code{+}, and @code{?} match
respectively: zero or more, one or more, and zero or one instances of
the preceding subpattern.

@smalllisp
(pregexp-match-positions "c[ad]*r" "cadaddadddr") @result{} ((0 . 11))
(pregexp-match-positions "c[ad]*r" "cr")          @result{} ((0 . 2))

(pregexp-match-positions "c[ad]+r" "cadaddadddr") @result{} ((0 . 11))
(pregexp-match-positions "c[ad]+r" "cr")          @result{} #f

(pregexp-match-positions "c[ad]?r" "cadaddadddr") @result{} #f
(pregexp-match-positions "c[ad]?r" "cr")          @result{} ((0 . 2))
(pregexp-match-positions "c[ad]?r" "car")         @result{} ((0 . 3))
@end smalllisp

@subsubsection Numeric quantifiers

You can use braces to specify much finer-tuned quantification than is
possible with @code{*}, @code{+}, @code{?}.

The quantifier @code{@{m@}} matches @emph{exactly} @code{m}
instances of the preceding @emph{subpattern}.  @code{m}
must be a nonnegative integer.

The quantifier @code{@{m,n@}} matches at least @code{m} and at most
@code{n} instances.  @code{m} and @code{n} are nonnegative integers with
@code{m <= n}.  You may omit either or both numbers, in which case
@code{m} defaults to 0 and @code{n} to infinity.

It is evident that @code{+} and @code{?} are abbreviations for
@code{@{1,@}} and @code{@{0,1@}} respectively.  @code{*} abbreviates
@code{@{,@}}, which is the same as @code{@{0,@}}.

@smalllisp
(pregexp-match "[aeiou]@{3@}" "vacuous")  @result{} ("uou")
(pregexp-match "[aeiou]@{3@}" "evolve")   @result{} #f
(pregexp-match "[aeiou]@{2,3@}" "evolve") @result{} #f
(pregexp-match "[aeiou]@{2,3@}" "zeugma") @result{} ("eu")
@end smalllisp

@subsubsection Non-greedy quantifiers

The quantifiers described above are @emph{greedy}, ie, they match the
maximal number of instances that would still lead to an overall match
for the full pattern.

@smalllisp
(pregexp-match "<.*>" "<tag1> <tag2> <tag3>")
 @result{} ("<tag1> <tag2> <tag3>")
@end smalllisp

To make these quantifiers @emph{non-greedy}, append a @code{?} to them.
Non-greedy quantifiers match the minimal number of instances needed to
ensure an overall match.

@smalllisp
(pregexp-match "<.*?>" "<tag1> <tag2> <tag3>") @result{} ("<tag1>")
@end smalllisp

The non-greedy quantifiers are respectively:
@code{*?}, @code{+?}, @code{??}, @code{@{m@}?}, @code{@{m,n@}?}.
Note the two uses of the metacharacter @code{?}.

@node Clusters, Alternation, Quantifiers, The Regular Expressions Pattern Language
@subsubsection Clusters

@emph{Clustering}, ie, enclosure within parens @code{(}...@code{)},
identifies the enclosed @emph{subpattern} as a single entity.  It causes
the matcher to @emph{capture} the @emph{submatch}, or the portion of the
string matching the subpattern, in addition to the overall match.

@smalllisp
(pregexp-match "([a-z]+) ([0-9]+), ([0-9]+)" "jan 1, 1970")
 @result{} ("jan 1, 1970" "jan" "1" "1970")
@end smalllisp

Clustering also causes a following quantifier to treat
the entire enclosed subpattern as an entity.

@smalllisp
(pregexp-match "(poo )*" "poo poo platter") @result{} ("poo poo " "poo ")
@end smalllisp

The number of submatches returned is always equal to the number of
subpatterns specified in the regexp, even if a particular subpattern
happens to match more than one substring or no substring at all.

@smalllisp
(pregexp-match "([a-z ]+;)*" "lather; rinse; repeat;")
 @result{} ("lather; rinse; repeat;" " repeat;")
@end smalllisp

@noindent Here the @code{*}-quantified subpattern matches three
times, but it is the last submatch that is returned.

It is also possible for a quantified subpattern to
fail to match, even if the overall pattern matches. 
In such cases, the failing submatch is represented
by @code{#f}.

@smalllisp
(define date-re
  ;match `month year' or `month day, year'.
  ;subpattern matches day, if present 
  (pregexp "([a-z]+) +([0-9]+,)? *([0-9]+)"))

(pregexp-match date-re "jan 1, 1970")
 @result{} ("jan 1, 1970" "jan" "1," "1970")

(pregexp-match date-re "jan 1970")
 @result{} ("jan 1970" "jan" #f "1970")
@end smalllisp

@subsubsection Backreferences

Submatches can be used in the insert string argument of the procedures
@code{pregexp-replace} and @code{pregexp-replace*}.  The insert string
can use @code{\n} as a @emph{backreference} to refer back to the
@emph{n}th submatch, ie, the substring that matched the @emph{n}th
subpattern.  @code{\0} refers to the entire match, and it can also be
specified as @code{\&}.

@smalllisp
(pregexp-replace "_(.+?)_" 
  "the _nina_, the _pinta_, and the _santa maria_"
  "*\\1*")
 @result{} "the *nina*, the _pinta_, and the _santa maria_"

(pregexp-replace* "_(.+?)_" 
  "the _nina_, the _pinta_, and the _santa maria_"
  "*\\1*")
 @result{} "the *nina*, the *pinta*, and the *santa maria*"

;recall: \S stands for non-whitespace character

(pregexp-replace "(\\S+) (\\S+) (\\S+)"
  "eat to live"
  "\\3 \\2 \\1")
 @result{} "live to eat"
@end smalllisp

Use @code{\\} in the insert string to specify a literal
backslash.  Also, @code{\$} stands for an empty string,
and is useful for separating a backreference @code{\n}
from an immediately following number.

Backreferences can also be used within the regexp
pattern to refer back to an already matched subpattern
in the pattern.  @code{\n} stands for an exact repeat
of the @emph{n}th submatch.@footnote{@code{\0}, which is useful in
an insert string, makes no  sense within the regexp
pattern, because the entire regexp has not matched yet
that you could refer back to it.} 

@smalllisp
(pregexp-match "([a-z]+) and \\1"
  "billions and billions")
 @result{} ("billions and billions" "billions")
@end smalllisp

@noindent Note that the backreference is not simply a repeat
of the previous subpattern.  Rather it is a repeat of
@emph{the particular  substring already matched by the
subpattern}. 

In the above example, the backreference can only match
@code{billions}.  It will not match @code{millions}, even
though the subpattern it harks back to --- @code{([a-z]+)}
---  would have had no problem doing so: 

@smalllisp
(pregexp-match "([a-z]+) and \\1"
  "billions and millions")
 @result{} #f 
@end smalllisp

The following corrects doubled words:

@smalllisp
(pregexp-replace* "(\\S+) \\1"
  "now is the the time for all good men to to come to the aid of of the party"
  "\\1")
 @result{} "now is the time for all good men to come to the aid of the party"
@end smalllisp

The following marks all immediately repeating patterns
in a number string:

@smalllisp
(pregexp-replace* "(\\d+)\\1"
  "123340983242432420980980234"
  "@{\\1,\\1@}")
 @result{} "12@{3,3@}40983@{24,24@}3242@{098,098@}0234"
@end smalllisp


@subsubsection Non-capturing clusters

It is often required to specify a cluster
(typically for quantification) but without triggering
the capture of submatch information.  Such
clusters are called @emph{non-capturing}.  In such cases,
use @code{(?:} instead of @code{(} as the cluster opener.  In
the following example, the  non-capturing cluster 
eliminates the ``directory'' portion of a given
pathname, and the capturing cluster  identifies the
basename.

@smalllisp
(pregexp-match "^(?:[a-z]*/)*([a-z]+)$" 
  "/usr/local/bin/mzscheme")
 @result{} ("/usr/local/bin/mzscheme" "mzscheme")
@end smalllisp

@subsubsection Cloisters

The location between the @code{?} and the @code{:} of a non-capturing
cluster is called a @emph{cloister}.@footnote{A useful, if terminally cute,
coinage from the abbots of Perl.}  You can put @emph{modifiers} there
that will cause the enclustered subpattern to be treated specially.  The
modifier @code{i} causes the subpattern to match
@emph{case-insensitively}:

@smalllisp
(pregexp-match "(?i:hearth)" "HeartH") @result{} ("HeartH")
@end smalllisp

The modifier @code{x} causes the subpattern to match
@emph{space-insensitively}, ie, spaces and
comments within the
subpattern are ignored.  Comments are introduced
as usual with a semicolon (@code{;}) and extend till
the end of the line.  If you need
to include a literal space or semicolon in
a space-insensitized subpattern, escape it
with a backslash.

@smalllisp
(pregexp-match "(?x: a   lot)" "alot")
 @result{} ("alot")

(pregexp-match "(?x: a  \\  lot)" "a lot")
 @result{} ("a lot")

(pregexp-match "(?x:
   a \\ man  \\; \\   ; ignore
   a \\ plan \\; \\   ; me
   a \\ canal         ; completely
   )" 
 "a man; a plan; a canal")
 @result{} ("a man; a plan; a canal")
@end smalllisp

@noindent The global variable @code{*pregexp-comment-char*}
contains the comment character (@code{#\;}).  
For Perl-like comments,  

@smalllisp
(set! *pregexp-comment-char* #\#)
@end smalllisp

You can put more than one modifier in the cloister.

@smalllisp
(pregexp-match "(?ix:
   a \\ man  \\; \\   ; ignore
   a \\ plan \\; \\   ; me
   a \\ canal         ; completely
   )" 
 "A Man; a Plan; a Canal")
 @result{} ("A Man; a Plan; a Canal")
@end smalllisp

A minus sign before a modifier inverts its meaning.
Thus, you can use @code{-i} and @code{-x} in a 
@emph{subcluster} to overturn the insensitivities caused by an
enclosing cluster.

@smalllisp
(pregexp-match "(?i:the (?-i:TeX)book)"
  "The TeXbook")
 @result{} ("The TeXbook")
@end smalllisp

@noindent This regexp will allow any casing for @code{the}
and @code{book} but insists that @code{TeX} not be 
differently cased.

@node Alternation, Backtracking, Clusters, The Regular Expressions Pattern Language
@subsubsection Alternation

You can specify a list of @emph{alternate}
subpatterns by separating them by @code{|}.   The @code{|}
separates subpatterns in the nearest enclosing cluster 
(or in the entire pattern string if there are no
enclosing parens).  

@smalllisp
(pregexp-match "f(ee|i|o|um)" "a small, final fee")
 @result{} ("fi" "i")

(pregexp-replace* "([yi])s(e[sdr]?|ing|ation)"
   "it is energising to analyse an organisation 
   pulsing with noisy organisms"
   "\\1z\\2")
 @result{} "it is energizing to analyze an organization 
   pulsing with noisy organisms"
@end smalllisp
 
Note again that if you wish
to use clustering merely to specify a list of alternate
subpatterns but do not want the submatch, use @code{(?:}
instead of @code{(}. 

@smalllisp
(pregexp-match "f(?:ee|i|o|um)" "fun for all")
 @result{} ("fo")
@end smalllisp

An important thing to note about alternation is that
the leftmost matching alternate is picked regardless of
its length.  Thus, if one of the alternates is a prefix
of a later alternate, the latter may not have 
a chance to match.

@smalllisp
(pregexp-match "call|call-with-current-continuation" 
  "call-with-current-continuation")
 @result{} ("call")
@end smalllisp

To allow the longer alternate to have a shot at 
matching, place it before the shorter one:

@smalllisp
(pregexp-match "call-with-current-continuation|call"
  "call-with-current-continuation")
 @result{} ("call-with-current-continuation")
@end smalllisp

In any case, an overall match for the entire regexp is
always preferred to an overall nonmatch.  In the
following, the longer alternate still wins, because its
preferred shorter prefix fails to yield an overall
match.

@smalllisp
(pregexp-match "(?:call|call-with-current-continuation) constrained"
  "call-with-current-continuation constrained")
 @result{} ("call-with-current-continuation constrained")
@end smalllisp

@node Backtracking, Looking ahead and behind, Alternation, The Regular Expressions Pattern Language
@subsubsection Backtracking

We've already seen that greedy quantifiers match
the maximal number of times, but the overriding priority
is that the overall match succeed.  Consider

@smalllisp
(pregexp-match "a*a" "aaaa")
@end smalllisp

@noindent The regexp consists of two subregexps,
@code{a*} followed by @code{a}.
The subregexp @code{a*} cannot be allowed to match
all four @code{a}'s in the text string @code{"aaaa"}, even though
@code{*} is a greedy quantifier.  It may match only the first
three, leaving the last one for the second subregexp.
This ensures that the full regexp matches successfully.

The regexp matcher accomplishes this via a process
called @emph{backtracking}.  The matcher
tentatively allows the greedy quantifier 
to match all four @code{a}'s, but then when it becomes
clear that the overall match is in jeopardy, it 
@emph{backtracks} to a less greedy match of 
@emph{three} @code{a}'s.  If even this fails, as in the
call

@smalllisp
(pregexp-match "a*aa" "aaaa")
@end smalllisp

@noindent the matcher backtracks even further.  Overall
failure is conceded only when all possible backtracking
has been tried with no success. 

Backtracking is not restricted to greedy quantifiers.
Nongreedy quantifiers match as few instances as
possible, and progressively backtrack to more and more
instances in order to attain an overall match.  There
is backtracking in alternation too, as the more
rightward alternates are tried when locally successful
leftward ones fail to yield an overall match.

@subsubsection Disabling backtracking

Sometimes it is efficient to disable backtracking.  For
example, we may wish  to  @emph{commit} to a choice, or
we know that trying alternatives is fruitless.  A
nonbacktracking regexp is enclosed in @code{(?>}...@code{)}.

@smalllisp
(pregexp-match "(?>a+)." "aaaa")
 @result{} #f
@end smalllisp

In this call, the subregexp @code{?>a*} greedily matches
all four @code{a}'s, and is denied the opportunity to
backpedal.  So the overall match is denied.  The effect
of the regexp is therefore to match one or more @code{a}'s
followed by something that is definitely non-@code{a}.

@node Looking ahead and behind, , Backtracking, The Regular Expressions Pattern Language
@subsubsection Looking ahead and behind

You can have assertions in your pattern that look 
@emph{ahead} or @emph{behind} to ensure that a subpattern does
or does not occur.   These ``look around'' assertions are
specified by putting the subpattern checked for in a
cluster whose leading characters are: @code{?=} (for positive
lookahead), @code{?!} (negative lookahead), @code{?<=}
(positive lookbehind), @code{?<!} (negative lookbehind).
Note that the subpattern in the assertion  does not
generate a match in the final result.  It merely allows
or disallows the rest of the match.

@subsubsection Lookahead

Positive lookahead (@code{?=}) peeks ahead to ensure that
its subpattern @emph{could} match.  

@smalllisp
(pregexp-match-positions "grey(?=hound)" 
  "i left my grey socks at the greyhound") 
 @result{} ((28 . 32))
@end smalllisp

@noindent The regexp @code{"grey(?=hound)"} matches @code{grey}, but
@emph{only} if it is followed by @code{hound}.  Thus, the first
@code{grey} in the text string is not matched. 

Negative lookahead (@code{?!}) peeks ahead
to ensure that its subpattern could not possibly match.  

@smalllisp
(pregexp-match-positions "grey(?!hound)"
  "the gray greyhound ate the grey socks") 
 @result{} ((27 . 31))
@end smalllisp

@noindent The regexp @code{"grey(?!hound)"} matches @code{grey}, but
only if it is @emph{not} followed by @code{hound}.  Thus 
the @code{grey} just before @code{socks} is matched.

@subsubsection Lookbehind

Positive lookbehind (@code{?<=}) checks that its subpattern @emph{could} match
immediately to the left of the current position in
the text string.  

@smalllisp
(pregexp-match-positions "(?<=grey)hound"
  "the hound in the picture is not a greyhound") 
 @result{} ((38 . 43))
@end smalllisp

@noindent The regexp @code{(?<=grey)hound} matches @code{hound}, 
but only if it is preceded by @code{grey}.  

Negative lookbehind
(@code{?<!}) checks that its subpattern
could not possibly match immediately to the left.  

@smalllisp
(pregexp-match-positions "(?<!grey)hound"
  "the greyhound in the picture is not a hound")
 @result{} ((38 . 43))
@end smalllisp

The regexp @code{(?<!grey)hound} matches @code{hound}, but only if
it is @emph{not} preceded by @code{grey}.

Lookaheads and lookbehinds can be convenient when they
are not confusing.  

@c ------------------------------------------------------------------- @c
@c    An extended example                                              @c
@c ------------------------------------------------------------------- @c
@node An Extended Example, , The Regular Expressions Pattern Language , Posix Regular Expressions
@subsection An Extended Example

Here's an extended example from Friedl that covers many of the features
described above.  The problem is to fashion a regexp that will match any
and only IP addresses or @emph{dotted quads}, ie, four numbers separated
by three dots, with each number between 0 and 255.  We will use the
commenting mechanism to build the final regexp with clarity.  First, a
subregexp @code{n0-255} that matches 0 through 255.

@smalllisp
(define n0-255
  "(?x:
  \\d          ;  0 through   9
  | \\d\\d     ; 00 through  99
  | [01]\\d\\d ;000 through 199
  | 2[0-4]\\d  ;200 through 249
  | 25[0-5]    ;250 through 255
  )")
@end smalllisp

The first two alternates simply get all single- and
double-digit numbers.  Since 0-padding is allowed, we
need to match both 1 and 01.  We need to be careful
when getting 3-digit numbers, since numbers above 255
must be excluded.  So we fashion alternates to get 000
through 199, then 200 through 249, and finally 250
through 255.@footnote{Note that @code{n0-255} lists prefixes as
preferred alternates, something we cautioned against in
section @ref{Alternation}. However, since we intend
to anchor this subregexp explicitly to force an overall
match, the order of the alternates does not matter.}

An IP-address is a string that consists of
four @code{n0-255}s with three dots separating
them.

@smalllisp
(define ip-re1
  (string-append
    "^"        ;nothing before
    n0-255     ;the first n0-255,
    "(?x:"     ;then the subpattern of
    "\\."      ;a dot followed by
    n0-255     ;an n0-255,
    ")"        ;which is
    "@{3@}"      ;repeated exactly 3 times
    "$"        ;with nothing following
    ))
@end smalllisp

Let's try it out.

@smalllisp
(pregexp-match ip-re1 "1.2.3.4")        @result{} ("1.2.3.4")
(pregexp-match ip-re1 "55.155.255.265") @result{} #f
@end smalllisp

which is fine, except that we also have

@smalllisp
(pregexp-match ip-re1 "0.00.000.00") @result{} ("0.00.000.00")
@end smalllisp

All-zero sequences are not valid IP addresses!  Lookahead to the rescue.
Before starting to match @code{ip-re1}, we look ahead to ensure we don't
have all zeros.  We could use positive lookahead to ensure there
@emph{is} a digit other than zero.

@smalllisp
(define ip-re
  (string-append
    "(?=.*[1-9])" ;ensure there's a non-0 digit
    ip-re1))
@end smalllisp

Or we could use negative lookahead to ensure that what's ahead isn't
composed of @emph{only} zeros and dots.

@smalllisp
(define ip-re
  (string-append
    "(?![0.]*$)" ;not just zeros and dots
                 ;(note: dot is not metachar inside [])
    ip-re1))
@end smalllisp

The regexp @code{ip-re} will match all and only valid IP addresses.

@smalllisp
(pregexp-match ip-re "1.2.3.4") @result{} ("1.2.3.4")
(pregexp-match ip-re "0.0.0.0") @result{} #f
@end smalllisp




