www

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

rest.scrbl (4370B)


      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{Parsing the tail of improper lists}
     12 
     13 @defform[#:kind "eh-mixin expander"
     14          {~lift-rest pat}]{
     15  Lifts @racket[pat] out of the current mixin, so that it is used as a pattern to
     16  match the tail of the improper list being matched. It is subject to the
     17  following restrictions:
     18  @itemlist[
     19  @item{@racket[~lift-rest] is allowed only within @racket[~no-order], but not
     20    within @racket[~seq-no-order]. @racket[~seq-no-order] always matches against
     21    a proper sequence of elements, while @racket[~no-order] may match a proper or
     22    improper list.}
     23  @item{The tail of the improper list must not be a pair, otherwise the
     24    @racket[car] would have been included in the main part of the list.}
     25  @item{The @racket[pat] is used to match the tail only if its surrounding
     26    pattern successfully matched some elements of the main section of the list.
     27 
     28    If the @racket[{~lift-rest pat}] is the only pattern present within an
     29    alternative, then it is always used.
     30    
     31    @examples[#:eval (make-evaluator)
     32              (syntax-parse #'(x y z . 1)
     33                [(~no-order {~lift-rest r:nat} i:id)
     34                 (syntax->datum #'(r i ...))])]}
     35  @item{
     36    Among the lifted rest patterns which are considered (see the point
     37    above), only one may successfully match. An error is raised if two or more
     38    lifted rest patterns successfully match against the tail of the list.
     39 
     40    @examples[#:eval (make-evaluator)
     41              (eval:no-prompt
     42               (define p
     43                 (syntax-parser
     44                   [(~no-order {~and {~literal x}
     45                                     {~lift-rest rn:nat}
     46                                     {~lift-rest ri:id}}
     47                               {~and {~literal y}
     48                                     {~lift-rest rs:str}
     49                                     {~lift-rest rj:id}})
     50                    'match]
     51                   #;[_
     52                    'fail])))
     53              (code:line (p #'(x . 1))   (code:comment "rn and ri considered, rn matched"))
     54              (code:line (p #'(x . z))   (code:comment "rn and ri considered, ri matched"))
     55              (code:line (p #'(y . "a")) (code:comment "rs and rj considered, rs matched"))
     56              (code:line (p #'(y . z))   (code:comment "rs and rj considered, rj matched"))
     57              (code:line (p #'(x y . 1)) (code:comment "all four considered, rn matched"))
     58              (eval:alts (code:line (p #'(x y . z)) (code:comment "all four considered, both ri and rj matched"))
     59                         (eval:error (p #'(x y . z))))]
     60 
     61    The rationale is that selecting the first lifted rest pattern that matches
     62    would result in unclear behaviour, as the order of the alternative clauses
     63    should not be significant.}
     64  @item{Post and global operations can be used within the @racket[pat]. This
     65    combination of features is not thoroughly tested, however. Please report any
     66    issues you run into.}]}
     67 
     68 @defform[#:kind "eh-mixin expander"
     69          {~as-rest pat ...}]{
     70                              
     71  Like @racket[~seq], but the @racket[pat]s are injected as part of the same
     72  @racket[~or] as @racket[~lift-rest]. This means that syntax/parse will not
     73  throw an error for the following code:
     74 
     75  @examples[#:eval (make-evaluator)
     76            (eval:no-prompt
     77             (define p2
     78               (syntax-parser
     79                 [(~no-order {~once name:id}
     80                             {~once message:str}
     81                             (~once (~or {~as-rest val:nat}
     82                                         {~seq {~lift-rest val:nat}})))
     83                  (syntax->datum
     84                   #'(#:name name #:messsage message #:val val))])))
     85            (code:line (p2 #'(x 123 "msg"))       (code:comment "matched by ~as-rest"))
     86            (code:line (p2 #'(x "msg" 123))       (code:comment "matched by ~as-rest"))
     87            (code:line (p2 #'(x "msg" . 456))     (code:comment "matched by ~lift-rest"))
     88            (eval:alts (code:line (p2 #'(x "msg" 123 . 456)) (code:comment "can't have both"))
     89                       (eval:error (p2 #'(x "msg" 123 . 456))))]}