#### 6.2.1 Regular S-Expressions ¶

A regular s-expression is either a character or a string, which matches itself, or one of the following forms.

Examples in this section use the following definitions for brevity:

    (define (try-match pattern string)
      (regsexp-match-string (compile-regsexp pattern) string))

    (define (try-search pattern string)
      (regsexp-search-string-forward (compile-regsexp pattern) string))

These forms match one or more characters literally:

regsexp: char-ci char ¶

  Matches char without considering case.

regsexp: string-ci string ¶

  Matches string without considering case.

regsexp: any-char ¶

  Matches one character other than `#\newline`.

      (try-match '(any-char) "") ⇒ #f
      (try-match '(any-char) "a") ⇒ (0 1)
      (try-match '(any-char) "\n") ⇒ #f
      (try-search '(any-char) "") ⇒ #f
      (try-search '(any-char) "ab") ⇒ (0 1)
      (try-search '(any-char) "\na") ⇒ (1 2)

regsexp: char-in datum … ¶
regsexp: char-not-in datum … ¶

  Matches one character in (not in) the character set specified by `(char-set datum …)`.

      (try-match '(seq "a" (char-in "ab") "c") "abc") ⇒ (0 3)
      (try-match '(seq "a" (char-not-in "ab") "c") "abc") ⇒ #f
      (try-match '(seq "a" (char-not-in "ab") "c") "adc") ⇒ (0 3)
      (try-match '(seq "a" (+ (char-in numeric)) "c") "a019c") ⇒ (0 5)

These forms match no characters, but only at specific locations in the input string:

regsexp: line-start ¶
regsexp: line-end ¶

  Matches no characters at the start (end) of a line.

      (try-match '(seq (line-start)
                       (* (any-char))
                       (line-end))
                 "abc") ⇒ (0 3)

      (try-match '(seq (line-start)
                       (* (any-char))
                       (line-end))
                 "ab\nc") ⇒ (0 2)

      (try-search '(seq (line-start)
                        (* (char-in alphabetic))
                        (line-end))
                  "1abc") ⇒ #f

      (try-search '(seq (line-start)
                        (* (char-in alphabetic))
                        (line-end))
                  "1\nabc") ⇒ (2 5)

regsexp: string-start ¶
regsexp: string-end ¶

  Matches no characters at the start (end) of the string.

      (try-match '(seq (string-start)
                       (* (any-char))
                       (string-end))
                 "abc") ⇒ (0 3)

      (try-match '(seq (string-start)
                       (* (any-char))
                       (string-end))
                 "ab\nc") ⇒ #f

      (try-search '(seq (string-start)
                        (* (char-in alphabetic))
                        (string-end))
                  "1abc") ⇒ #f

      (try-search '(seq (string-start)
                        (* (char-in alphabetic))
                        (string-end))
                  "1\nabc") ⇒ #f

These forms match repetitions of a given regsexp. Most of them come in two forms, one of which is greedy and the other shy. The greedy form matches as many repetitions as it can, then uses failure backtracking to reduce the number of repetitions one at a time. The shy form matches the minimum number of repetitions, then uses failure backtracking to increase the number of repetitions one at a time. The shy form is similar to the greedy form except that a `?` is added at the end of the form’s keyword.

regsexp: ? regsexp ¶
regsexp: ?? regsexp ¶

  Matches regsexp zero or one time.

      (try-search '(seq (char-in alphabetic)
                        (? (char-in numeric)))
                  "a") ⇒ (0 1)

      (try-search '(seq (char-in alphabetic)
                        (?? (char-in numeric)))
                  "a") ⇒ (0 1)

      (try-search '(seq (char-in alphabetic)
                        (? (char-in numeric)))
                  "a1") ⇒ (0 2)

      (try-search '(seq (char-in alphabetic)
                        (?? (char-in numeric)))
                  "a1") ⇒ (0 1)

      (try-search '(seq (char-in alphabetic)
                        (? (char-in numeric)))
                  "1a2") ⇒ (1 3)

      (try-search '(seq (char-in alphabetic)
                        (?? (char-in numeric)))
                  "1a2") ⇒ (1 2)

regsexp: * regsexp ¶
regsexp: *? regsexp ¶

  Matches regsexp zero or more times.

      (try-match '(seq (char-in alphabetic)
                       (* (char-in numeric))
                       (any-char))
                 "aa") ⇒ (0 2)

      (try-match '(seq (char-in alphabetic)
                       (*? (char-in numeric))
                       (any-char))
                 "aa") ⇒ (0 2)

      (try-match '(seq (char-in alphabetic)
                       (* (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 5)

      (try-match '(seq (char-in alphabetic)
                       (*? (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 2)

regsexp: + regsexp ¶
regsexp: +? regsexp ¶

  Matches regsexp one or more times.

      (try-match '(seq (char-in alphabetic)
                       (+ (char-in numeric))
                       (any-char))
                 "aa") ⇒ #f

      (try-match '(seq (char-in alphabetic)
                       (+? (char-in numeric))
                       (any-char))
                 "aa") ⇒ #f

      (try-match '(seq (char-in alphabetic)
                       (+ (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 5)

      (try-match '(seq (char-in alphabetic)
                       (+? (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 3)

regsexp: ** n m regsexp ¶
regsexp: **? n m regsexp ¶

  The n argument must be an exact nonnegative integer. The m argument must be either an exact integer greater than or equal to n, or else `#f`.

  Matches regsexp at least n times and at most m times; if m is `#f` then there is no upper limit.

      (try-match '(seq (char-in alphabetic)
                       (** 0 2 (char-in numeric))
                       (any-char))
                 "aa") ⇒ (0 2)

      (try-match '(seq (char-in alphabetic)
                       (**? 0 2 (char-in numeric))
                       (any-char))
                 "aa") ⇒ (0 2)

      (try-match '(seq (char-in alphabetic)
                       (** 0 2 (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 4)

      (try-match '(seq (char-in alphabetic)
                       (**? 0 2 (char-in numeric))
                       (any-char))
                 "a123a") ⇒ (0 2)

regsexp: ** n regsexp ¶

  This is an abbreviation for `(** n n regsexp)`. This matcher is neither greedy nor shy since it matches a fixed number of repetitions.

These forms implement alternatives and sequencing:

regsexp: alt regsexp … ¶

  Matches one of the regsexp arguments, trying each in order from left to right.

      (try-match '(alt #\a (char-in numeric)) "a") ⇒ (0 1)
      (try-match '(alt #\a (char-in numeric)) "b") ⇒ #f
      (try-match '(alt #\a (char-in numeric)) "1") ⇒ (0 1)

regsexp: seq regsexp … ¶

  Matches the first regsexp, then continues the match with the next regsexp, and so on until all of the arguments are matched.

      (try-match '(seq #\a #\b) "a") ⇒ #f
      (try-match '(seq #\a #\b) "aa") ⇒ #f
      (try-match '(seq #\a #\b) "ab") ⇒ (0 2)

These forms implement named registers, which store matched segments of the input string:

regsexp: group key regsexp ¶

  The key argument must be a fixnum, a character, or a symbol.

  Matches regsexp. If the match succeeds, the matched segment is stored in the register named key.

      (try-match '(seq (group a (any-char))
                       (group b (any-char))
                       (any-char))
                 "radar") ⇒ (0 3 (a . "r") (b . "a"))

regsexp: group-ref key ¶

  The key argument must be a fixnum, a character, or a symbol.

  Matches the characters stored in the register named key. It is an error if that register has not been initialized with a corresponding `group` expression.

      (try-match '(seq (group a (any-char))
                       (group b (any-char))
                       (any-char)
                       (group-ref b)
                       (group-ref a))
                 "radar") ⇒ (0 5 (a . "r") (b . "a"))