50 lines
1.9 KiB
Scheme
50 lines
1.9 KiB
Scheme
|
|
#lang scheme/base
|
|
(require (prefix-in yacc: parser-tools/yacc)
|
|
(for-syntax scheme/base))
|
|
(provide parser
|
|
options
|
|
productions
|
|
definitions)
|
|
|
|
(define-syntax options
|
|
(lambda (stx)
|
|
(raise-syntax-error #f "options keyword used out of context" stx)))
|
|
|
|
(define-syntax productions
|
|
(lambda (stx)
|
|
(raise-syntax-error #f "productions keyword used out of context" stx)))
|
|
|
|
(define-syntax definitions
|
|
(lambda (stx)
|
|
(raise-syntax-error #f "definitions keyword used out of context" stx)))
|
|
|
|
(define-syntax (parser stx)
|
|
(syntax-case stx ()
|
|
[(parser form ...)
|
|
(let ([stop-list (list #'begin #'options #'productions #'definitions)]
|
|
[forms (syntax->list #'(form ...))])
|
|
(define-values (opts prods defs)
|
|
(let loop ([forms forms] [opts null] [prods null] [defs null])
|
|
(if (pair? forms)
|
|
(let ([eform0 (local-expand (car forms) 'expression stop-list)]
|
|
[forms (cdr forms)])
|
|
(syntax-case eform0 (begin options productions definitions)
|
|
[(begin subform ...)
|
|
(loop (append (syntax->list #'(subform ...)) forms) opts prods defs)]
|
|
[(options subform ...)
|
|
(loop forms (append (syntax->list #'(subform ...)) opts) prods defs)]
|
|
[(productions subform ...)
|
|
(loop forms opts (append (syntax->list #'(subform ...)) prods) defs)]
|
|
[(definitions subform ...)
|
|
(loop forms opts prods (append (syntax->list #'(subform ...)) defs))]
|
|
[else
|
|
(raise-syntax-error #f "bad parser subform" eform0)]))
|
|
(values opts prods defs))))
|
|
(with-syntax ([(opt ...) opts]
|
|
[(prod ...) prods]
|
|
[(def ...) defs])
|
|
#'(let ()
|
|
def ...
|
|
(#%expression (yacc:parser opt ... (grammar prod ...))))))]))
|