In general, you can look for identifiers that are free-identifier=? to
something from the grammar for "fully expanded programs" (
https://docs.racket-lang.org/reference/syntax-model.html#%28part._fully-expanded%29).
That's a little abstract, though, so I've included an example. There might
be more elegant ways to do this, but hopefully it's at least clear what's
going on.

#lang racket/base

(module lang racket/base
  (provide (except-out (all-from-out racket/base)
                       #%module-begin)
           (rename-out [my-module-begin #%module-begin]))
  (require syntax/parse/define
           (for-syntax racket/base
                       syntax/parse
                       syntax/flatten-begin))
  (define-syntax-parser my-module-begin
    [(_ body:expr ...)
     #`(#%module-begin
        (stratify-module-body
         #:doc #,(syntax-local-introduce (datum->syntax #f 'doc))
         #:collected ()
         #:to-go (body ...)))])
  (begin-for-syntax
    (define-syntax-class definition-form
      #:literals {#%require #%provide define-values define-syntaxes
                            module module* module+}
      (pattern ((~or* #%require #%provide define-values define-syntaxes
                      module module* module+)
                _ ...))))
  (define-syntax-parser stratify-module-body
    [(_ #:doc doc:id
        #:collected (collected:expr ...)
        #:to-go ())
     #`(begin (define doc
                (string-append collected ...))
              doc
              (provide doc))]
    [(_ #:doc doc:id
        #:collected (collected:expr ...)
        #:to-go (this:expr to-go:expr ...))
     (syntax-parse (local-expand #'this
                                 'module
                                 (list #'begin ;; it's implicitly added
anyway
                                       ;; Need to not try to expand these:
                                       #'#%require
                                       #'#%provide
                                       #'define-values
                                       #'define-syntaxes
                                       #'module #'module* #'module+
                                       ))
       #:literals {begin}
       [(begin body:expr ...)
        #:with (flattened ...) (flatten-all-begins
                                #'(begin body ...))
        #`(stratify-module-body
           #:doc doc
           #:collected (collected ...)
           #:to-go (flattened ... to-go ...))]
       [defn:definition-form
        #`(begin defn
                 (stratify-module-body
                  #:doc doc
                  #:collected (collected ...)
                  #:to-go (to-go ...)))]
       [other
        #`(stratify-module-body
           #:doc doc
           #:collected (collected ... other)
           #:to-go (to-go ...))])]))

(module main (submod ".." lang)
  "Hi"
  (require racket/string)
  ","
  " "
  (define (! n)
    (make-string n #\!))
  "world"
  (! 3))

(module+ test
  (require rackunit
           (submod ".." main))
  (check-equal? doc "Hi, world!!!"))


-Philip

On Fri, Aug 17, 2018 at 5:17 AM, Vityou <zlee...@gmail.com> wrote:

> How would I go about doing this?  Is there a certain function that can
> tell if something is a top-level declaration?
>
> On Thursday, August 16, 2018 at 6:44:53 PM UTC-6, Philip McGrath wrote:
>>
>> You probably want to partially expand the expressions, collect the
>> definitions, and lift them to the module level.
>>
>> -Philip
>>
>> On Thu, Aug 16, 2018 at 11:58 PM, Vityou <zle...@gmail.com> wrote:
>>
>>> I'm attempting to make a language similar to scribble.  I'm using the
>>> `make-at-reader` that scribble provides, and have my module-begin as this:
>>>
>>> (define-syntax md-module-begin
>>>   (syntax-parser
>>>     [(_ (expr1 ...)) #'(#%module-begin (define doc (parse-markdown
>>> (string-append (begin expr1) ...)))
>>>                                        (provide doc)
>>>                                        doc)]))
>>>
>>> This works good for normal expressions, but when I try to do something
>>> like `define`, it complains that it is not allowed in expression context.
>>> I tried fixing this by wrapping expressions in `begin`, but I still get the
>>> same error.  Is there any way to fix this?  Thanks for any help.
>>>
>>> --
>>> You received this message because you are subscribed to the Google
>>> Groups "Racket Users" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
>>> an email to racket-users...@googlegroups.com.
>>> For more options, visit https://groups.google.com/d/optout.
>>>
>>
>> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to