3.2.2 mischief/parse: Tools for syntax-parse
(require mischief/parse) | package: mischief |
3.2.2.1 Shorthand Macros
syntax
(@ attribute-id)
syntax
(syntax-matches? expr pat ...)
syntax
(syntax-matcher pat ...)
syntax
(syntax-class/c class-id)
syntax
(syntax-parse/c pat ...)
3.2.2.2 Syntax Classes
3.2.2.2.1 Formal Arguments
syntax
The attribute arg-id has a depth of 1 and contains all the positional, non-rest formal argument identifiers.
The attribute rest has a depth of 0 and contains the tail of the (possibly improper) list of arguments: either a rest argument or ().
The attribute rest-id? has a depth of 0 and contains the rest argument identifier if one is present, or #false otherwise.
The attribute rest-id has a depth of 1. If there is a rest argument, the attribute contains just that identifier. Otherwise the attribute is empty.
The attribute formal-id has a depth of 1 and contains the result of appending arg-id with rest-id.
The attribute call has a depth of 0. It is bound to #%app if rest-id is empty and apply otherwise.
> (define (recursive stx) (syntax-parse stx [({~literal define} (name:id . args:formals) . _) #'(args.call name args.formal-id ...)])) > (recursive #'(define (print x port) ---etc---)) #<syntax:1:0 (#%app print x port)>
> (recursive #'(define (printf fmt . args) ---etc---)) #<syntax:1:0 (apply printf fmt args)>
syntax
> (syntax-parse '{a b [c "one"] [d "two"] #:w e #:x f #:y [g "three"] #:z [h "four"] . i} [args:kw-formals (stylish-println (list (@ args.req-id) (@ args.opt-id) (@ args.opt-expr) (@ args.req-kw) (@ args.req-kw-id) (@ args.opt-kw) (@ args.opt-kw-id) (@ args.opt-kw-expr) (@ args.rest) (@ args.rest-id?) (@ args.rest-id) (@ args.formal-id) (@ args.call)))])
(list
(list #'a #'b)
(list #'c #'d)
(list #'"one" #'"two")
(list #'#:w #'#:x)
(list #'e #'f)
(list #'#:y #'#:z)
(list #'g #'h)
(list #'"three" #'"four")
#'i
#'i
(list #'i)
(list #'a #'b #'e #'f #'c #'d #'g #'h #'i)
#'keyword-apply #| parse.rkt:161.14 |#)
3.2.2.2.2 For Loops
syntax
> (define (f x) (syntax-parse x [c:for-clauses #'c])) > (f #'{[(k v) (in-dict (hash))] #:when (eq? k v)}) #<syntax:6:0 (((k v) (in-dict (hash))) #:w...>
> (f #'{[(k v) (in-dict (hash))] [k (in-naturals)]}) eval:7.0: ?: duplicate identifier
at: k
in: (((k v) (in-dict (hash))) (k (in-naturals)))
parsing context:
while parsing for-clauses
term: (((k v) (in-dict (hash))) (k (in-naturals)))
location: eval:7.0
> (f #'{[(k v) (in-dict (hash))] #:else "something"}) eval:8.0: ?: expected for-clause
at: #:else
in: (((k v) (in-dict (hash))) #:else "something")
parsing context:
while parsing for-clauses
term: (((k v) (in-dict (hash))) #:else "something")
location: eval:8.0
See for-body for a more practical example.
syntax
> (define-syntax (for/string-set! stx) (syntax-parse stx [(_ target:expr clauses:for-clauses . body:for-body) #'(let {[s target]} (for clauses body.head ... (define-values {i c} body.tail) (string-set! s i c)))])) > (define s (string-copy "fox"))
> (for/string-set! s {[i (in-naturals)] [c (in-string "abcdefghijklmnopqrstuvwxyz")]} #:break (>= i (string-length s)) (values i c)) > s "abc"
3.2.2.2.3 Definition and Expression Bodies
syntax
3.2.2.2.4 Literal Data
syntax
syntax
procedure
(datum-literal pred desc) → syntax-class
pred : predicate/c desc : string?
3.2.2.2.5 Identifier Bindings
syntax
syntax
syntax
procedure
(static-binding pred desc) → syntax-class
pred : predicate/c desc : string?
The attribute value contains the value that the matched identifier is bound to.
The attribute delta contains a delta syntax introducer based on the parsed identifier. This value is a function that operates on syntax, applying any marks that are present on the parsed identifier that were not present on the original identifier that defined it.
> (define-syntax (write-static-string stx) (syntax-parse stx [(_ (~var s (static-binding string? "a static string variable"))) (displayln (@ s.value)) #'(begin)])) > (define-syntax x "x") > (write-static-string x) x
> (define-syntax y 'y) > (write-static-string y) eval:17.0: write-static-string: expected a static string
variable, but found an identifier bound as syntax to 'y
at: y
in: (write-static-string y)
parsing context:
while parsing a static string variable
term: y
location: eval:17.0
syntax
The attribute value contains the struct-info? value that the parsed identifier is bound to.
The attributes descriptor-id, constructor-id, predicate-id, accessor-id, mutator-id, and super-id correspond to the fields of the list produced by extract-struct-info. The attributes accessor-id and mutator-id have depth 1, and unlike in extract-struct-info they are proper lists and are not reversed.
The attribute known-fields? contains a boolean that is #true if the attributes accessor-id and mutator-id represent every field of the structure, and #false if there may be missing fields.
syntax
procedure
(struct-binding/check [ #:all all #:descriptor known-descriptor? #:constructor known-constructor? #:predicate known-predicate? #:fields known-fields? #:super known-super? #:mutable known-mutators?]) → syntax-class all : boolean? = #false known-descriptor? : boolean? = all known-constructor? : boolean? = all known-predicate? : boolean? = all known-fields? : boolean? = all known-super? : boolean? = all known-mutators? : boolean? = all
3.2.2.3 Literal Sets
syntax
(define-literals/ids base-id opt ... [literal-id ...])
syntax
(require/define-literals/ids base-id require-spec)