|
|
|
@ -1,6 +1,6 @@
|
|
|
|
|
(module stx mzscheme
|
|
|
|
|
(require syntax/boundmap
|
|
|
|
|
"util.rkt")
|
|
|
|
|
(require "util.rkt"
|
|
|
|
|
syntax/id-table)
|
|
|
|
|
|
|
|
|
|
(provide parse)
|
|
|
|
|
|
|
|
|
@ -37,10 +37,18 @@
|
|
|
|
|
;; checks for errors and generates the plain s-exp form for s
|
|
|
|
|
;; Expands lex-abbrevs and applies lex-trans.
|
|
|
|
|
(define (parse stx disappeared-uses)
|
|
|
|
|
(let ((parse
|
|
|
|
|
(lambda (s)
|
|
|
|
|
(parse (syntax-rearm s stx)
|
|
|
|
|
disappeared-uses))))
|
|
|
|
|
(let loop ([stx stx]
|
|
|
|
|
[disappeared-uses disappeared-uses]
|
|
|
|
|
;; seen-lex-abbrevs: id-table
|
|
|
|
|
[seen-lex-abbrevs (make-immutable-free-id-table)])
|
|
|
|
|
(let ([recur (lambda (s)
|
|
|
|
|
(loop (syntax-rearm s stx)
|
|
|
|
|
disappeared-uses
|
|
|
|
|
seen-lex-abbrevs))]
|
|
|
|
|
[recur/abbrev (lambda (s id)
|
|
|
|
|
(loop (syntax-rearm s stx)
|
|
|
|
|
disappeared-uses
|
|
|
|
|
(free-id-table-set seen-lex-abbrevs id id)))])
|
|
|
|
|
(syntax-case (disarm stx) (repetition union intersection complement concatenation
|
|
|
|
|
char-range char-complement)
|
|
|
|
|
(_
|
|
|
|
@ -50,8 +58,15 @@
|
|
|
|
|
(raise-syntax-error 'regular-expression
|
|
|
|
|
"undefined abbreviation"
|
|
|
|
|
stx))
|
|
|
|
|
;; Check for cycles.
|
|
|
|
|
(when (free-id-table-ref seen-lex-abbrevs stx (lambda () #f))
|
|
|
|
|
(raise-syntax-error 'regular-expression
|
|
|
|
|
"illegal lex-abbrev cycle detected"
|
|
|
|
|
stx
|
|
|
|
|
#f
|
|
|
|
|
(list (free-id-table-ref seen-lex-abbrevs stx))))
|
|
|
|
|
(set-box! disappeared-uses (cons stx (unbox disappeared-uses)))
|
|
|
|
|
(parse ((lex-abbrev-get-abbrev expansion)))))
|
|
|
|
|
(recur/abbrev ((lex-abbrev-get-abbrev expansion)) stx)))
|
|
|
|
|
(_
|
|
|
|
|
(or (char? (syntax-e stx)) (string? (syntax-e stx)))
|
|
|
|
|
(syntax-e stx))
|
|
|
|
@ -78,18 +93,18 @@
|
|
|
|
|
#f
|
|
|
|
|
"the first argument is not less than or equal to the second argument"
|
|
|
|
|
stx))
|
|
|
|
|
`(repetition ,low ,high ,(parse re)))))
|
|
|
|
|
`(repetition ,low ,high ,(recur re)))))
|
|
|
|
|
((union re ...)
|
|
|
|
|
`(union ,@(map parse (syntax->list (syntax (re ...))))))
|
|
|
|
|
`(union ,@(map recur (syntax->list (syntax (re ...))))))
|
|
|
|
|
((intersection re ...)
|
|
|
|
|
`(intersection ,@(map parse (syntax->list (syntax (re ...))))))
|
|
|
|
|
`(intersection ,@(map recur (syntax->list (syntax (re ...))))))
|
|
|
|
|
((complement re ...)
|
|
|
|
|
(let ((re-list (syntax->list (syntax (re ...)))))
|
|
|
|
|
(unless (= 1 (length re-list))
|
|
|
|
|
(bad-args stx 1))
|
|
|
|
|
`(complement ,(parse (car re-list)))))
|
|
|
|
|
`(complement ,(recur (car re-list)))))
|
|
|
|
|
((concatenation re ...)
|
|
|
|
|
`(concatenation ,@(map parse (syntax->list (syntax (re ...))))))
|
|
|
|
|
`(concatenation ,@(map recur (syntax->list (syntax (re ...))))))
|
|
|
|
|
((char-range arg ...)
|
|
|
|
|
(let ((arg-list (syntax->list (syntax (arg ...)))))
|
|
|
|
|
(unless (= 2 (length arg-list))
|
|
|
|
@ -106,7 +121,7 @@
|
|
|
|
|
(let ((arg-list (syntax->list (syntax (arg ...)))))
|
|
|
|
|
(unless (= 1 (length arg-list))
|
|
|
|
|
(bad-args stx 1))
|
|
|
|
|
(let ((parsed (parse (car arg-list))))
|
|
|
|
|
(let ((parsed (recur (car arg-list))))
|
|
|
|
|
(unless (char-set? parsed)
|
|
|
|
|
(raise-syntax-error #f
|
|
|
|
|
"not a character set"
|
|
|
|
@ -120,7 +135,7 @@
|
|
|
|
|
(set-box! disappeared-uses (cons o (unbox disappeared-uses)))
|
|
|
|
|
(cond
|
|
|
|
|
((lex-trans? expansion)
|
|
|
|
|
(parse ((lex-trans-f expansion) (disarm stx))))
|
|
|
|
|
(recur ((lex-trans-f expansion) (disarm stx))))
|
|
|
|
|
(expansion
|
|
|
|
|
(raise-syntax-error 'regular-expression
|
|
|
|
|
"not a lex-trans"
|
|
|
|
@ -133,7 +148,7 @@
|
|
|
|
|
(raise-syntax-error
|
|
|
|
|
'regular-expression
|
|
|
|
|
"not a char, string, identifier, or (op args ...)"
|
|
|
|
|
stx)))))
|
|
|
|
|
stx))))))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|