www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

no-order.scrbl (8339B)


      1 #lang scribble/manual
      2 @require[scribble/example
      3          "utils.rkt"
      4          @for-label[phc-toolkit/untyped
      5                     extensible-parser-specifications
      6                     generic-syntax-expanders
      7                     racket/base
      8                     syntax/parse
      9                     (only-in racket/base [... …])]]
     10 
     11 @title{Matching alternatives in any order}
     12 
     13 @defform[#:kind "pattern expander"
     14          #:literals (~mixin ~or)
     15          (~seq-no-order clause-or-mixin ...)
     16          #:grammar
     17          [(clause-or-mixin #,ntax-pattern
     18                            (~mixin #,-alternative-mixin)
     19                            (~or clause-or-mixin ...)
     20                            derived-or)]]{
     21  Splicing pattern which matches the given @racket[clause-or-mixin]s in any
     22  order, enforcing the global constraints expressed within each.
     23 
     24  Nested @racket[~or] directly below @racket[~seq-no-order] are recursively
     25  inlined. In other words, the @racket[~or] present directly below the
     26  @racket[~seq-no-order] or below such an @racket[~or] clause do not behave as
     27  "exclusive or", but instead contain clauses which can appear in any order.
     28  These clauses are not grouped in any way by the @racket[~or], i.e.
     29  @racket[(~no-order (~or (~or a b) (~or c d)))] is equivalent to
     30  @racket[(~no-order a b c d)].
     31                                          
     32  The @racket[derived-or] term covers any
     33  @tech[#:doc '(lib "syntax/scribblings/syntax.scrbl")]{pattern expander} or
     34  @tech{eh-mixin expander} application which expands to a
     35  @racket[clause-or-mixin]. The expansion of pattern and eh-mixin expanders
     36  happens before inlining the top @racket[~or] clauses.}
     37 
     38 @defform[#:kind "pattern expander"
     39          #:literals (~mixin ~or)
     40          (~no-order clause-or-mixin ...)
     41          #:grammar
     42          [(clause-or-mixin #,ntax-pattern
     43                            (~mixin #,-alternative-mixin)
     44                            (~or clause-or-mixin ...)
     45                            derived-or)]]{
     46                                          
     47  Like @racket[~seq-no-order], except that it matches a syntax list, instead of
     48  being spliced into the surrounding sequence of patterns. In other words,
     49 
     50  @racketblock[({~seq-no-order clause-or-mixin ...})]
     51  
     52  is equivalent to (notice the extra pair of braces above):
     53 
     54  @racketblock[(~no-order clause-or-mixin ...)]
     55 
     56  Additionally, @racket[~no-order] can include clauses which use
     57  @racket[~lift-rest], which lifts a pattern which matches the tail of an
     58  improper list.}
     59 
     60 @section{Enforcing a partial order on the alternatives}
     61 
     62 @defform[#:kind "eh-mixin expander"
     63          (~order-point point-name #,ntax-pattern ...)]{
     64  When parsing a sequence of elements, @racket[~seq-no-order] and
     65  @racket[~no-order] associate an increasing number to each element starting from
     66  zero.
     67  
     68  The number associated with the first element matched by
     69  @racket[#,ntax-pattern ...] is memorised into the attribute
     70  @racket[point-name].
     71 
     72  This allows the position of elements matched by otherwise independent mixins to
     73  be compared using @racket[order-point<] and @racket[order-point>]}
     74 
     75 @defform[(order-point< a b)
     76          #:grammar
     77          [(a #,tribute-name)
     78           (b #,tribute-name)]]{
     79  Returns @racket[#t] when the first element matched by
     80  @racket[(~order-point a #,ntax-pattern ...)] occurs before the first element
     81  matched by @racket[(~order-point b #,ntax-pattern ...)]. Otherwise, returns
     82  @racket[#f].
     83 
     84  This operation does not fail if @racket[a] or @racket[b] are bound to
     85  @racket[#f] (i.e. their corresponding @racket[_syntax-pattern ...] did not
     86  match). Instead, in both cases, it returns @racket[#f].}
     87 
     88 @defform[(order-point> a b)
     89          #:grammar
     90          [(a #,tribute-name)
     91           (b #,tribute-name)]]{
     92  Returns @racket[#t] when the first element matched by
     93  @racket[(~order-point a #,ntax-pattern ...)] occurs after the first element
     94  matched by @racket[(~order-point b #,ntax-pattern ...)]. Otherwise, returns
     95  @racket[#f].
     96 
     97  This operation does not fail if @racket[a] or @racket[b] are bound to
     98  @racket[#f] (i.e. their corresponding @racket[_syntax-pattern ...] did not
     99  match). Instead, in both cases, it returns @racket[#f].}
    100 
    101 @defform[(try-order-point< a b)
    102          #:grammar
    103          [(a #,tribute-name)
    104           (b #,tribute-name)]]{
    105 
    106  Like @racket[order-point<], except that it does not fail if @racket[a] or
    107  @racket[b] are not attributes, or if they are bound to @racket[#f]. Instead, in
    108  all those cases, it returns @racket[#f].
    109 
    110  It can be used as follows:
    111 
    112  @racketblock[
    113  (~post-fail "a must appear after b"
    114              #:when (try-order-point< a b))]
    115 
    116  The same caveats as for @racket[try-attribute] apply.}
    117 
    118 @defform[(try-order-point> a b)
    119          #:grammar
    120          [(a #,tribute-name)
    121           (b #,tribute-name)]]{
    122 
    123  Like @racket[order-point>], except that it does not fail if @racket[a] or
    124  @racket[b] are not attributes, or if they are bound to @racket[#f]. Instead, in
    125  all those cases, it returns @racket[#f].
    126 
    127  It can be used as follows:
    128 
    129  @racketblock[
    130  (~post-fail "a must appear before b"
    131              #:when (try-order-point> a b))]
    132 
    133  The same caveats as for @racket[try-attribute] apply.}
    134 
    135 @defform[#:kind "eh-mixin-expander"
    136          (~before other message pat ...)]{
    137                                               
    138  Post-checks that the first element matched by @racket[pat ...] appears before
    139  the @racket[other] order-point. This is a shorthand for:
    140  
    141  @racketblock[{~order-point pt
    142                 {~seq pat ...}
    143                 {~post-fail message #:when (order-point> pt other)}}]
    144 
    145  Note: Hopefully @racket[~before] will be modified in the future so that it
    146  auto-detects if the @racket[other] order-point is not defined as part of the
    147  current @racket[~no-order]. Do not rely on comparisons with order points
    148  somehow defined outside the current @racket[~no-order], as that behaviour may
    149  change in the future.
    150 
    151  This is implemented as a @seclink["Pre__global_and_post_operations"]{pre
    152   operation}.}
    153 
    154 @defform[#:kind "eh-mixin-expander"
    155          (~after other message pat ...)]{
    156  Post-checks that the first element matched by @racket[pat ...] appears after
    157  the @racket[other] order-point. This is a shorthand for:
    158  
    159  @racketblock[{~order-point pt
    160                 {~seq pat ...}
    161                 {~post-fail message #:when (order-point< pt other)}}]
    162 
    163  Note: Hopefully @racket[~after] will be modified in the future so that it
    164  auto-detects if the @racket[other] order-point is not defined as part of the
    165  current @racket[~no-order]. Do not rely on comparisons with order points
    166  somehow defined outside the current @racket[~no-order], as that behaviour may
    167  change in the future.
    168 
    169  This is implemented as a @seclink["Pre__global_and_post_operations"]{pre
    170   operation}.}
    171 
    172 @defform[#:kind "eh-mixin-expander"
    173          (~try-before other message pat ...)]{
    174                                               
    175  Post-checks that the first element matched by @racket[pat ...] appears before
    176  the @racket[other] order-point. The @racket[try-] version does not cause an
    177  error if the order-point @racket[other] is not define (e.g. it was part of
    178  another mixin which was not included). This is a shorthand for:
    179  
    180  @racketblock[{~order-point pt
    181                 {~seq pat ...}
    182                 {~post-fail message #:when (try-order-point> pt other)}}]
    183 
    184  Note: Hopefully @racket[~before] will be modified in the future so that it
    185  auto-detects if the @racket[other] order-point is missing. This form will then
    186  be removed.
    187 
    188  This is implemented as a @seclink["Pre__global_and_post_operations"]{pre
    189   operation}.}
    190 
    191 @defform[#:kind "eh-mixin-expander"
    192          (~try-after other message pat ...)]{
    193  Post-checks that the first element matched by @racket[pat ...] appears after
    194  the @racket[other] order-point. The @racket[try-] version does not cause an
    195  error if the order-point @racket[other] is not define (e.g. it was part of
    196  another mixin which was not included). This is a shorthand for:
    197  
    198  @racketblock[{~order-point pt
    199                 {~seq pat ...}
    200                 {~post-fail message #:when (try-order-point< pt other)}}]
    201 
    202  Note: Hopefully @racket[~after] will be modified in the future so that it
    203  auto-detects if the @racket[other] order-point is missing. This form will then
    204  be removed.
    205 
    206  This is implemented as a @seclink["Pre__global_and_post_operations"]{pre
    207   operation}.}
    208