www

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

pre-global-post-order.scrbl (3512B)


      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{Order in which the attributes are bound for post operations and
     12  global operations}
     13 
     14 Within the @racket[_A-pattern]s of post operations, the regular attributes bound
     15 by all the clauses inside @racket[~seq-no-order] or @racket[~no-order] are
     16 bound. The attributes defined as part of all "global" actions are bound too. The
     17 attributes defined as part of "post" actions of other clauses are bound only if
     18 the clause defining them appears before the current clause in the source code.
     19 For example, the following code works because the clause containing
     20 @racket[{~post-fail "2 is incompatible with 1" #:when (not (attribute a))}]
     21 appears after the clause which binds @racket[a] with the "post" action
     22 @racket[{~post-check {~bind ([a #'the-a])}}].
     23 
     24 @racketblock[
     25  {~seq-no-order
     26   {~post-check {~and the-a 1} {~bind ([a #'the-a])}}
     27   {~and 2 {~post-fail "2 is incompatible with 1" #:when (not (attribute a))}}}]
     28 
     29 If the two clauses are swapped, then the following code would raise a syntax
     30 error because @racket[a] is not bound as an attribute in the
     31 @racket[~post-fail]:
     32 
     33 @racketblock[
     34  {~seq-no-order
     35   {~and 2 {~post-fail "2 is incompatible with 1" #:when (not (attribute a))}}
     36   {~post-check {~and the-a 1} {~bind ([a #'the-a])}}}]
     37 
     38 On the other hand, the following code, which does not bind @racket[a] as part
     39 of a post operation, is valid:
     40  
     41 @racketblock[
     42  {~seq-no-order
     43   {~and 2 {~post-fail "2 is incompatible with 1" #:when (not (attribute a))}}
     44   {~and the-a 1 {~bind ([a #'the-a])}}}]
     45 
     46 Furthermore, the following code still works, as attributes are bound by the
     47 "global" operations before the "post" operations are executed:
     48 
     49 @racketblock[
     50  {~seq-no-order
     51   {~and 2 {~post-fail "2 is incompatible with 1" #:when (not (attribute a))}}
     52   {~global-or a 1}}]
     53 
     54 Note that the order in which clauses appear within the @racket[~seq-no-order]
     55 or @racket[~no-order] does not impact the order in which the elements must
     56 appear in the matched syntax (aside from issues related to greediness).
     57 
     58 @defform[(try-attribute #,tribute-name)]{
     59  This macro expands to @racket[(attribute #,tribute-name)] if
     60  @racket[#,tribute-name] is bound as a syntax pattern variable, and to
     61  @racket[#f] otherwise.
     62 
     63  This macro can be used to check for mutual exclusion of an attribute which is
     64  bound by other mixins that might or might not be present in the final
     65  @racket[~no-order] or @racket[~seq-no-order].
     66  
     67  Use this sparingly, as if an syntax pattern variable with that name is bound by
     68  an outer scope, the @racket[try-attribute] macro will still access it, ignorant
     69  of the fact that the current @racket[~seq-no-order] does not contain any mixin
     70  which binds that attribute.
     71 
     72  Instead, it is better practice to use
     73  @racket[{~global-or [_attribute-name #f]}] or
     74  @racket[{~global-and [_attribute-name #t]}] to ensure that the attribute is
     75  declared, while using the operation's neutral element to not alter the final
     76  result.}
     77 
     78 @defform[(if-attribute #,tribute-name if-branch else-branch)]{
     79  This macro expands to @racket[if-branch] if @racket[#,tribute-name] is bound as
     80  a syntax pattern variable, and to @racket[else-branch] otherwise.
     81 
     82  The same caveats as for @racket[try-attribute] apply.}