refactor into racket/base
parent
fc1e00bc2a
commit
fd446e6013
@ -1,24 +1,23 @@
|
|||||||
(module lex-plt-v200 mzscheme
|
#lang racket/base
|
||||||
(require br-parser-tools/lex
|
(require (for-syntax racket/base)
|
||||||
(prefix : br-parser-tools/lex-sre))
|
br-parser-tools/lex
|
||||||
|
(prefix-in : br-parser-tools/lex-sre))
|
||||||
|
|
||||||
(provide epsilon
|
(provide epsilon ~
|
||||||
~
|
(rename-out [:* *]
|
||||||
(rename :* *)
|
[:+ +]
|
||||||
(rename :+ +)
|
[:? ?]
|
||||||
(rename :? ?)
|
[:or :]
|
||||||
(rename :or :)
|
[:& &]
|
||||||
(rename :& &)
|
[:: @]
|
||||||
(rename :: @)
|
[:~ ^]
|
||||||
(rename :~ ^)
|
[:/ -]))
|
||||||
(rename :/ -))
|
|
||||||
|
|
||||||
(define-lex-trans epsilon
|
(define-lex-trans (epsilon stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_) "")))
|
[(_) #'""]))
|
||||||
|
|
||||||
(define-lex-trans ~
|
|
||||||
(syntax-rules ()
|
|
||||||
((_ re) (complement re)))))
|
|
||||||
|
|
||||||
|
(define-lex-trans (~ stx)
|
||||||
|
(syntax-case stx ()
|
||||||
|
[(_ RE) #'(complement RE)]))
|
||||||
|
|
||||||
|
@ -1,119 +1,103 @@
|
|||||||
(module lex-sre mzscheme
|
#lang racket/base
|
||||||
(require br-parser-tools/lex)
|
(require (for-syntax racket/base)
|
||||||
|
br-parser-tools/lex)
|
||||||
(provide (rename sre-* *)
|
|
||||||
(rename sre-+ +)
|
(provide (rename-out [sre-* *]
|
||||||
?
|
[sre-+ +]
|
||||||
(rename sre-= =)
|
[sre-= =]
|
||||||
(rename sre->= >=)
|
[sre->= >=]
|
||||||
**
|
[sre-or or]
|
||||||
(rename sre-or or)
|
[sre-- -]
|
||||||
:
|
[sre-/ /])
|
||||||
seq
|
? ** : seq & ~ /-only-chars)
|
||||||
&
|
|
||||||
~
|
(define-lex-trans (sre-* stx)
|
||||||
(rename sre-- -)
|
(syntax-case stx ()
|
||||||
(rename sre-/ /)
|
[(_ RE ...)
|
||||||
/-only-chars)
|
#'(repetition 0 +inf.0 (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans sre-*
|
(define-lex-trans (sre-+ stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(repetition 0 +inf.0 (union re ...)))))
|
#'(repetition 1 +inf.0 (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans sre-+
|
(define-lex-trans (? stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(repetition 1 +inf.0 (union re ...)))))
|
#'(repetition 0 1 (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans ?
|
(define-lex-trans (sre-= stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ N RE ...)
|
||||||
(repetition 0 1 (union re ...)))))
|
#'(repetition N N (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans sre-=
|
(define-lex-trans (sre->= stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ n re ...)
|
[(_ N RE ...)
|
||||||
(repetition n n (union re ...)))))
|
#'(repetition N +inf.0 (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans sre->=
|
(define-lex-trans (** stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ n re ...)
|
[(_ LOW #f RE ...)
|
||||||
(repetition n +inf.0 (union re ...)))))
|
#'(** LOW +inf.0 RE ...)]
|
||||||
|
[(_ LOW HIGH RE ...)
|
||||||
(define-lex-trans **
|
#'(repetition LOW HIGH (union RE ...))]))
|
||||||
(syntax-rules ()
|
|
||||||
((_ low #f re ...)
|
(define-lex-trans (sre-or stx)
|
||||||
(** low +inf.0 re ...))
|
(syntax-case stx ()
|
||||||
((_ low high re ...)
|
[(_ RE ...)
|
||||||
(repetition low high (union re ...)))))
|
#'(union RE ...)]))
|
||||||
|
|
||||||
(define-lex-trans sre-or
|
(define-lex-trans (: stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(union re ...))))
|
#'(concatenation RE ...)]))
|
||||||
|
|
||||||
(define-lex-trans :
|
(define-lex-trans (seq stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(concatenation re ...))))
|
#'(concatenation RE ...)]))
|
||||||
|
|
||||||
(define-lex-trans seq
|
(define-lex-trans (& stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(concatenation re ...))))
|
#'(intersection RE ...)]))
|
||||||
|
|
||||||
(define-lex-trans &
|
(define-lex-trans (~ stx)
|
||||||
(syntax-rules ()
|
(syntax-case stx ()
|
||||||
((_ re ...)
|
[(_ RE ...)
|
||||||
(intersection re ...))))
|
#'(char-complement (union RE ...))]))
|
||||||
|
|
||||||
(define-lex-trans ~
|
|
||||||
(syntax-rules ()
|
|
||||||
((_ re ...)
|
|
||||||
(char-complement (union re ...)))))
|
|
||||||
|
|
||||||
;; set difference
|
;; set difference
|
||||||
(define-lex-trans (sre-- stx)
|
(define-lex-trans (sre-- stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
((_)
|
[(_)
|
||||||
(raise-syntax-error #f
|
(raise-syntax-error #f
|
||||||
"must have at least one argument"
|
"must have at least one argument"
|
||||||
stx))
|
stx)]
|
||||||
((_ big-re re ...)
|
[(_ BIG-RE RE ...)
|
||||||
(syntax (& big-re (complement (union re ...)))))))
|
#'(& BIG-RE (complement (union RE ...)))]))
|
||||||
|
|
||||||
(define-lex-trans (sre-/ stx)
|
(define-lex-trans (sre-/ stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
((_ range ...)
|
[(_ RANGE ...)
|
||||||
(let ((chars
|
(let ([chars
|
||||||
(apply append (map (lambda (r)
|
(apply append (for/list ([r (in-list (syntax->list #'(RANGE ...)))])
|
||||||
(let ((x (syntax-e r)))
|
(let ([x (syntax-e r)])
|
||||||
(cond
|
(cond
|
||||||
((char? x) (list x))
|
[(char? x) (list x)]
|
||||||
((string? x) (string->list x))
|
[(string? x) (string->list x)]
|
||||||
(else
|
[else
|
||||||
(raise-syntax-error
|
(raise-syntax-error #f "not a char or string" stx r)]))))])
|
||||||
#f
|
|
||||||
"not a char or string"
|
|
||||||
stx
|
|
||||||
r)))))
|
|
||||||
(syntax->list (syntax (range ...)))))))
|
|
||||||
(unless (even? (length chars))
|
(unless (even? (length chars))
|
||||||
(raise-syntax-error
|
(raise-syntax-error #f "not given an even number of characters" stx))
|
||||||
#f
|
#`(/-only-chars #,@chars))]))
|
||||||
"not given an even number of characters"
|
|
||||||
stx))
|
(define-lex-trans (/-only-chars stx)
|
||||||
#`(/-only-chars #,@chars)))))
|
(syntax-case stx ()
|
||||||
|
[(_ C1 C2)
|
||||||
(define-lex-trans /-only-chars
|
#'(char-range C1 C2)]
|
||||||
(syntax-rules ()
|
[(_ C1 C2 C ...)
|
||||||
((_ c1 c2)
|
#'(union (char-range C1 C2) (/-only-chars C ...))]))
|
||||||
(char-range c1 c2))
|
|
||||||
((_ c1 c2 c ...)
|
|
||||||
(union (char-range c1 c2)
|
|
||||||
(/-only-chars c ...)))))
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,374 +1,297 @@
|
|||||||
(module input-file-parser mzscheme
|
#lang racket/base
|
||||||
|
|
||||||
;; routines for parsing the input to the parser generator and producing a
|
|
||||||
;; grammar (See grammar.rkt)
|
|
||||||
|
|
||||||
(require "yacc-helper.rkt"
|
(require "yacc-helper.rkt"
|
||||||
"../private-lex/token-syntax.rkt"
|
"../private-lex/token-syntax.rkt"
|
||||||
"grammar.rkt"
|
"grammar.rkt"
|
||||||
mzlib/class
|
racket/class
|
||||||
racket/contract)
|
racket/contract
|
||||||
(require-for-template mzscheme)
|
(for-template racket/base))
|
||||||
|
|
||||||
|
;; routines for parsing the input to the parser generator and producing a
|
||||||
|
;; grammar (See grammar.rkt)
|
||||||
|
|
||||||
(define (is-a-grammar%? x) (is-a? x grammar%))
|
(define (is-a-grammar%? x) (is-a? x grammar%))
|
||||||
(provide/contract
|
(provide/contract
|
||||||
(parse-input ((listof identifier?) (listof identifier?) (listof identifier?)
|
[parse-input ((listof identifier?) (listof identifier?) (listof identifier?)
|
||||||
(or/c #f syntax?) syntax? any/c . -> . is-a-grammar%?))
|
(or/c #f syntax?) syntax? any/c . -> . is-a-grammar%?)]
|
||||||
(get-term-list ((listof identifier?) . -> . (listof identifier?))))
|
[get-term-list ((listof identifier?) . -> . (listof identifier?))])
|
||||||
|
|
||||||
(define stx-for-original-property (read-syntax #f (open-input-string "original")))
|
(define stx-for-original-property (read-syntax #f (open-input-string "original")))
|
||||||
|
|
||||||
;; get-args: ??? -> (values (listof syntax) (or/c #f (cons integer? stx)))
|
;; get-args: ??? -> (values (listof syntax) (or/c #f (cons integer? stx)))
|
||||||
(define (get-args i rhs src-pos term-defs)
|
(define (get-args i rhs src-pos term-defs)
|
||||||
(let ((empty-table (make-hash-table))
|
(define empty-table (make-hasheq))
|
||||||
(biggest-pos #f))
|
(define biggest-pos #f)
|
||||||
(hash-table-put! empty-table 'error #t)
|
(hash-set! empty-table 'error #t)
|
||||||
(for-each (lambda (td)
|
(for* ([td (in-list term-defs)]
|
||||||
(let ((v (syntax-local-value td)))
|
[v (in-value (syntax-local-value td))]
|
||||||
(if (e-terminals-def? v)
|
#:when (e-terminals-def? v)
|
||||||
(for-each (lambda (s)
|
[s (in-list (syntax->list (e-terminals-def-t v)))])
|
||||||
(hash-table-put! empty-table (syntax-object->datum s) #t))
|
(hash-set! empty-table (syntax->datum s) #t))
|
||||||
(syntax->list (e-terminals-def-t v))))))
|
(define args
|
||||||
term-defs)
|
(let get-args ([i i][rhs rhs])
|
||||||
(let ([args
|
|
||||||
(let get-args ((i i)
|
|
||||||
(rhs rhs))
|
|
||||||
(cond
|
(cond
|
||||||
((null? rhs) null)
|
[(null? rhs) null]
|
||||||
(else
|
[else
|
||||||
(let ((b (car rhs))
|
(define b (car rhs))
|
||||||
(name (if (hash-table-get empty-table (syntax-object->datum (car rhs)) (lambda () #f))
|
(define name (if (hash-ref empty-table (syntax->datum (car rhs)) #f)
|
||||||
(gensym)
|
(gensym)
|
||||||
(string->symbol (format "$~a" i)))))
|
(string->symbol (format "$~a" i))))
|
||||||
(cond
|
(cond
|
||||||
(src-pos
|
[src-pos
|
||||||
(let ([start-pos-id
|
(define start-pos-id
|
||||||
(datum->syntax-object b (string->symbol (format "$~a-start-pos" i)) b stx-for-original-property)]
|
(datum->syntax b (string->symbol (format "$~a-start-pos" i)) b stx-for-original-property))
|
||||||
[end-pos-id
|
(define end-pos-id
|
||||||
(datum->syntax-object b (string->symbol (format "$~a-end-pos" i)) b stx-for-original-property)])
|
(datum->syntax b (string->symbol (format "$~a-end-pos" i)) b stx-for-original-property))
|
||||||
(set! biggest-pos (cons start-pos-id end-pos-id))
|
(set! biggest-pos (cons start-pos-id end-pos-id))
|
||||||
`(,(datum->syntax-object b name b stx-for-original-property)
|
(list* (datum->syntax b name b stx-for-original-property)
|
||||||
,start-pos-id
|
start-pos-id
|
||||||
,end-pos-id
|
end-pos-id
|
||||||
,@(get-args (add1 i) (cdr rhs)))))
|
(get-args (add1 i) (cdr rhs)))]
|
||||||
(else
|
[else
|
||||||
`(,(datum->syntax-object b name b stx-for-original-property)
|
(list* (datum->syntax b name b stx-for-original-property)
|
||||||
,@(get-args (add1 i) (cdr rhs)))))))))])
|
(get-args (add1 i) (cdr rhs)))])])))
|
||||||
(values args biggest-pos))))
|
(values args biggest-pos))
|
||||||
|
|
||||||
;; Given the list of terminal symbols and the precedence/associativity definitions,
|
;; Given the list of terminal symbols and the precedence/associativity definitions,
|
||||||
;; builds terminal structures (See grammar.rkt)
|
;; builds terminal structures (See grammar.rkt)
|
||||||
;; build-terms: symbol list * symbol list list -> term list
|
;; build-terms: symbol list * symbol list list -> term list
|
||||||
(define (build-terms term-list precs)
|
(define (build-terms term-list precs)
|
||||||
(let ((counter 0)
|
(define counter 0)
|
||||||
|
|
||||||
;;(term-list (cons (gensym) term-list))
|
;;(term-list (cons (gensym) term-list))
|
||||||
|
|
||||||
;; Will map a terminal symbol to its precedence/associativity
|
;; Will map a terminal symbol to its precedence/associativity
|
||||||
(prec-table (make-hash-table)))
|
(define prec-table (make-hasheq))
|
||||||
|
|
||||||
;; Fill the prec table
|
;; Fill the prec table
|
||||||
(for-each
|
(for ([p-decl (in-list precs)])
|
||||||
(lambda (p-decl)
|
(define assoc (car p-decl))
|
||||||
(begin0
|
(for ([term-sym (in-list (cdr p-decl))])
|
||||||
(let ((assoc (car p-decl)))
|
(hash-set! prec-table term-sym (make-prec counter assoc)))
|
||||||
(for-each
|
(set! counter (add1 counter)))
|
||||||
(lambda (term-sym)
|
|
||||||
(hash-table-put! prec-table term-sym (make-prec counter assoc)))
|
|
||||||
(cdr p-decl)))
|
|
||||||
(set! counter (add1 counter))))
|
|
||||||
precs)
|
|
||||||
|
|
||||||
;; Build the terminal structures
|
;; Build the terminal structures
|
||||||
(map
|
(for/list ([term-sym (in-list term-list)])
|
||||||
(lambda (term-sym)
|
|
||||||
(make-term term-sym
|
(make-term term-sym
|
||||||
#f
|
#f
|
||||||
(hash-table-get prec-table term-sym (lambda () #f))))
|
(hash-ref prec-table term-sym (λ () #f)))))
|
||||||
term-list)))
|
|
||||||
|
|
||||||
;; Retrieves the terminal symbols from a terminals-def (See terminal-syntax.rkt)
|
;; Retrieves the terminal symbols from a terminals-def (See terminal-syntax.rkt)
|
||||||
;; get-terms-from-def: identifier? -> (listof identifier?)
|
;; get-terms-from-def: identifier? -> (listof identifier?)
|
||||||
(define (get-terms-from-def term-syn)
|
(define (get-terms-from-def term-syn)
|
||||||
(let ((t (syntax-local-value term-syn (lambda () #f))))
|
(define t (syntax-local-value term-syn #f))
|
||||||
(cond
|
(cond
|
||||||
((terminals-def? t) (syntax->list (terminals-def-t t)))
|
[(terminals-def? t) (syntax->list (terminals-def-t t))]
|
||||||
((e-terminals-def? t) (syntax->list (e-terminals-def-t t)))
|
[(e-terminals-def? t) (syntax->list (e-terminals-def-t t))]
|
||||||
(else
|
[else
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-tokens
|
'parser-tokens
|
||||||
"undefined token group"
|
"undefined token group"
|
||||||
term-syn)))))
|
term-syn)]))
|
||||||
|
|
||||||
(define (get-term-list term-group-names)
|
(define (get-term-list term-group-names)
|
||||||
(remove-duplicates
|
(remove-duplicates
|
||||||
(cons (datum->syntax-object #f 'error)
|
(cons (datum->syntax #f 'error)
|
||||||
(apply append
|
(apply append (map get-terms-from-def term-group-names)))))
|
||||||
(map get-terms-from-def term-group-names)))))
|
|
||||||
|
|
||||||
(define (parse-input term-defs start ends prec-decls prods src-pos)
|
(define (parse-input term-defs start ends prec-decls prods src-pos)
|
||||||
(let* ((start-syms (map syntax-e start))
|
(define start-syms (map syntax-e start))
|
||||||
|
(define list-of-terms (map syntax-e (get-term-list term-defs)))
|
||||||
(list-of-terms (map syntax-e (get-term-list term-defs)))
|
(define end-terms
|
||||||
|
(for/list ([end (in-list ends)])
|
||||||
(end-terms
|
|
||||||
(map
|
|
||||||
(lambda (end)
|
|
||||||
(unless (memq (syntax-e end) list-of-terms)
|
(unless (memq (syntax-e end) list-of-terms)
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-end-tokens
|
'parser-end-tokens
|
||||||
(format "End token ~a not defined as a token"
|
(format "End token ~a not defined as a token"
|
||||||
(syntax-e end))
|
(syntax-e end))
|
||||||
end))
|
end))
|
||||||
(syntax-e end))
|
(syntax-e end)))
|
||||||
ends))
|
|
||||||
|
|
||||||
;; Get the list of terminals out of input-terms
|
;; Get the list of terminals out of input-terms
|
||||||
|
(define list-of-non-terms
|
||||||
(list-of-non-terms
|
|
||||||
(syntax-case prods ()
|
(syntax-case prods ()
|
||||||
(((non-term production ...) ...)
|
[((NON-TERM PRODUCTION ...) ...)
|
||||||
(begin
|
(begin
|
||||||
(for-each
|
(for ([nts (in-list (syntax->list #'(NON-TERM ...)))]
|
||||||
(lambda (nts)
|
#:when (memq (syntax->datum nts) list-of-terms))
|
||||||
(if (memq (syntax-object->datum nts) list-of-terms)
|
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-non-terminals
|
'parser-non-terminals
|
||||||
(format "~a used as both token and non-terminal"
|
(format "~a used as both token and non-terminal" (syntax->datum nts))
|
||||||
(syntax-object->datum nts))
|
nts))
|
||||||
nts)))
|
(let ([dup (duplicate-list? (syntax->datum #'(NON-TERM ...)))])
|
||||||
(syntax->list (syntax (non-term ...))))
|
(when dup
|
||||||
|
|
||||||
(let ((dup (duplicate-list? (syntax-object->datum
|
|
||||||
(syntax (non-term ...))))))
|
|
||||||
(if dup
|
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-non-terminals
|
'parser-non-terminals
|
||||||
(format "non-terminal ~a defined multiple times"
|
(format "non-terminal ~a defined multiple times" dup)
|
||||||
dup)
|
|
||||||
prods)))
|
prods)))
|
||||||
|
(syntax->datum #'(NON-TERM ...)))]
|
||||||
(syntax-object->datum (syntax (non-term ...)))))
|
[_ (raise-syntax-error
|
||||||
(_
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-grammar
|
'parser-grammar
|
||||||
"Grammar must be of the form (grammar (non-terminal productions ...) ...)"
|
"Grammar must be of the form (grammar (non-terminal productions ...) ...)"
|
||||||
prods))))
|
prods)]))
|
||||||
|
|
||||||
;; Check the precedence declarations for errors and turn them into data
|
;; Check the precedence declarations for errors and turn them into data
|
||||||
(precs
|
(define precs
|
||||||
(syntax-case prec-decls ()
|
(syntax-case prec-decls ()
|
||||||
(((type term ...) ...)
|
[((TYPE TERM ...) ...)
|
||||||
(let ((p-terms
|
(let ([p-terms (syntax->datum #'(TERM ... ...))])
|
||||||
(syntax-object->datum (syntax (term ... ...)))))
|
|
||||||
(cond
|
(cond
|
||||||
((duplicate-list? p-terms) =>
|
[(duplicate-list? p-terms) =>
|
||||||
(lambda (d)
|
(λ (d)
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-precedences
|
'parser-precedences
|
||||||
(format "duplicate precedence declaration for token ~a"
|
(format "duplicate precedence declaration for token ~a" d)
|
||||||
d)
|
prec-decls))]
|
||||||
prec-decls)))
|
[else (for ([t (in-list (syntax->list #'(TERM ... ...)))]
|
||||||
(else
|
#:when (not (memq (syntax->datum t) list-of-terms)))
|
||||||
(for-each
|
|
||||||
(lambda (a)
|
|
||||||
(for-each
|
|
||||||
(lambda (t)
|
|
||||||
(if (not (memq (syntax-object->datum t)
|
|
||||||
list-of-terms))
|
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-precedences
|
'parser-precedences
|
||||||
(format
|
(format "Precedence declared for non-token ~a" (syntax->datum t))
|
||||||
"Precedence declared for non-token ~a"
|
t))
|
||||||
(syntax-object->datum t))
|
(for ([type (in-list (syntax->list #'(TYPE ...)))]
|
||||||
t)))
|
#:unless (memq (syntax->datum type) `(left right nonassoc)))
|
||||||
(syntax->list a)))
|
|
||||||
(syntax->list (syntax ((term ...) ...))))
|
|
||||||
(for-each
|
|
||||||
(lambda (type)
|
|
||||||
(if (not (memq (syntax-object->datum type)
|
|
||||||
`(left right nonassoc)))
|
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-precedences
|
'parser-precedences
|
||||||
"Associativity must be left, right or nonassoc"
|
"Associativity must be left, right or nonassoc"
|
||||||
type)))
|
type))
|
||||||
(syntax->list (syntax (type ...))))
|
(syntax->datum prec-decls)]))]
|
||||||
(syntax-object->datum prec-decls)))))
|
[#f null]
|
||||||
(#f null)
|
[_ (raise-syntax-error
|
||||||
(_
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-precedences
|
'parser-precedences
|
||||||
"Precedence declaration must be of the form (precs (assoc term ...) ...) where assoc is left, right or nonassoc"
|
"Precedence declaration must be of the form (precs (assoc term ...) ...) where assoc is left, right or nonassoc"
|
||||||
prec-decls))))
|
prec-decls)]))
|
||||||
|
|
||||||
(terms (build-terms list-of-terms precs))
|
|
||||||
|
|
||||||
(non-terms (map (lambda (non-term) (make-non-term non-term #f))
|
(define terms (build-terms list-of-terms precs))
|
||||||
|
(define non-terms (map (λ (non-term) (make-non-term non-term #f))
|
||||||
list-of-non-terms))
|
list-of-non-terms))
|
||||||
(term-table (make-hash-table))
|
(define term-table (make-hasheq))
|
||||||
(non-term-table (make-hash-table)))
|
(define non-term-table (make-hasheq))
|
||||||
|
|
||||||
(for-each (lambda (t)
|
(for ([t (in-list terms)])
|
||||||
(hash-table-put! term-table (gram-sym-symbol t) t))
|
(hash-set! term-table (gram-sym-symbol t) t))
|
||||||
terms)
|
|
||||||
|
|
||||||
(for-each (lambda (nt)
|
(for ([nt (in-list non-terms)])
|
||||||
(hash-table-put! non-term-table (gram-sym-symbol nt) nt))
|
(hash-set! non-term-table (gram-sym-symbol nt) nt))
|
||||||
non-terms)
|
|
||||||
|
|
||||||
(let* (
|
|
||||||
;; parse-prod: syntax-object -> gram-sym vector
|
;; parse-prod: syntax-object -> gram-sym vector
|
||||||
(parse-prod
|
(define (parse-prod prod-so)
|
||||||
(lambda (prod-so)
|
|
||||||
(syntax-case prod-so ()
|
(syntax-case prod-so ()
|
||||||
((prod-rhs-sym ...)
|
[(PROD-RHS-SYM ...)
|
||||||
(andmap identifier? (syntax->list prod-so))
|
(andmap identifier? (syntax->list prod-so))
|
||||||
(begin
|
(begin
|
||||||
(for-each (lambda (t)
|
(for ([t (in-list (syntax->list prod-so))]
|
||||||
(if (memq (syntax-object->datum t) end-terms)
|
#:when (memq (syntax->datum t) end-terms))
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-production-rhs
|
'parser-production-rhs
|
||||||
(format "~a is an end token and cannot be used in a production"
|
(format "~a is an end token and cannot be used in a production" (syntax->datum t))
|
||||||
(syntax-object->datum t))
|
t))
|
||||||
t)))
|
(for/vector ([s (in-list (syntax->list prod-so))])
|
||||||
(syntax->list prod-so))
|
(cond
|
||||||
(list->vector
|
[(hash-ref term-table (syntax->datum s) #f)]
|
||||||
(map (lambda (s)
|
[(hash-ref non-term-table (syntax->datum s) #f)]
|
||||||
(hash-table-get
|
[else (raise-syntax-error
|
||||||
term-table
|
|
||||||
(syntax-object->datum s)
|
|
||||||
(lambda ()
|
|
||||||
(hash-table-get
|
|
||||||
non-term-table
|
|
||||||
(syntax-object->datum s)
|
|
||||||
(lambda ()
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-production-rhs
|
'parser-production-rhs
|
||||||
(format
|
(format "~a is not declared as a terminal or non-terminal" (syntax->datum s))
|
||||||
"~a is not declared as a terminal or non-terminal"
|
s)])))]
|
||||||
(syntax-object->datum s))
|
[_ (raise-syntax-error
|
||||||
s))))))
|
|
||||||
(syntax->list prod-so)))))
|
|
||||||
(_
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-production-rhs
|
'parser-production-rhs
|
||||||
"production right-hand-side must have form (symbol ...)"
|
"production right-hand-side must have form (symbol ...)"
|
||||||
prod-so)))))
|
prod-so)]))
|
||||||
|
|
||||||
;; parse-action: syntax-object * syntax-object -> syntax-object
|
;; parse-action: syntax-object * syntax-object -> syntax-object
|
||||||
(parse-action
|
(define (parse-action rhs act-in)
|
||||||
(lambda (rhs act)
|
(define-values (args biggest) (get-args 1 (syntax->list rhs) src-pos term-defs))
|
||||||
(let-values ([(args biggest) (get-args 1 (syntax->list rhs) src-pos term-defs)])
|
(define act
|
||||||
(let ([act
|
|
||||||
(if biggest
|
(if biggest
|
||||||
(with-syntax ([$n-start-pos (datum->syntax-object (car biggest) '$n-start-pos)]
|
(with-syntax ([(CAR-BIGGEST . CDR-BIGGEST) biggest]
|
||||||
[$n-end-pos (datum->syntax-object (cdr biggest) '$n-end-pos)])
|
[$N-START-POS (datum->syntax (car biggest) '$n-start-pos)]
|
||||||
#`(let ([$n-start-pos #,(car biggest)]
|
[$N-END-POS (datum->syntax (cdr biggest) '$n-end-pos)]
|
||||||
[$n-end-pos #,(cdr biggest)])
|
[ACT-IN act-in])
|
||||||
#,act))
|
#'(let ([$N-START-POS CAR-BIGGEST]
|
||||||
act)])
|
[$N-END-POS CDR-BIGGEST])
|
||||||
(quasisyntax/loc act
|
ACT-IN))
|
||||||
(lambda #,args
|
act-in))
|
||||||
#,act))))))
|
(with-syntax ([ARGS args][ACT act])
|
||||||
|
(syntax/loc #'ACT (λ ARGS ACT))))
|
||||||
|
|
||||||
;; parse-prod+action: non-term * syntax-object -> production
|
;; parse-prod+action: non-term * syntax-object -> production
|
||||||
(parse-prod+action
|
(define (parse-prod+action nt prod-so)
|
||||||
(lambda (nt prod-so)
|
|
||||||
(syntax-case prod-so ()
|
(syntax-case prod-so ()
|
||||||
((prod-rhs action)
|
[(PROD-RHS ACTION)
|
||||||
(let ((p (parse-prod (syntax prod-rhs))))
|
(let ([p (parse-prod #'PROD-RHS)])
|
||||||
(make-prod
|
(make-prod
|
||||||
nt
|
nt
|
||||||
p
|
p
|
||||||
#f
|
#f
|
||||||
(let loop ((i (sub1 (vector-length p))))
|
(let loop ([i (sub1 (vector-length p))])
|
||||||
(if (>= i 0)
|
(if (>= i 0)
|
||||||
(let ((gs (vector-ref p i)))
|
(let ([gs (vector-ref p i)])
|
||||||
(if (term? gs)
|
(if (term? gs)
|
||||||
(term-prec gs)
|
(term-prec gs)
|
||||||
(loop (sub1 i))))
|
(loop (sub1 i))))
|
||||||
#f))
|
#f))
|
||||||
(parse-action (syntax prod-rhs) (syntax action)))))
|
(parse-action #'PROD-RHS #'ACTION)))]
|
||||||
((prod-rhs (prec term) action)
|
[(PROD-RHS (PREC TERM) ACTION)
|
||||||
(identifier? (syntax term))
|
(identifier? #'TERM)
|
||||||
(let ((p (parse-prod (syntax prod-rhs))))
|
(let ([p (parse-prod #'PROD-RHS)])
|
||||||
(make-prod
|
(make-prod
|
||||||
nt
|
nt
|
||||||
p
|
p
|
||||||
#f
|
#f
|
||||||
(term-prec
|
(term-prec
|
||||||
(hash-table-get
|
(cond
|
||||||
term-table
|
[(hash-ref term-table (syntax->datum #'TERM) #f)]
|
||||||
(syntax-object->datum (syntax term))
|
[else (raise-syntax-error
|
||||||
(lambda ()
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-production-rhs
|
'parser-production-rhs
|
||||||
(format
|
(format
|
||||||
"unrecognized terminal ~a in precedence declaration"
|
"unrecognized terminal ~a in precedence declaration"
|
||||||
(syntax-object->datum (syntax term)))
|
(syntax->datum #'TERM))
|
||||||
(syntax term)))))
|
#'TERM)]))
|
||||||
(parse-action (syntax prod-rhs) (syntax action)))))
|
(parse-action #'PROD-RHS #'ACTION)))]
|
||||||
(_
|
[_ (raise-syntax-error
|
||||||
(raise-syntax-error
|
|
||||||
'parser-production-rhs
|
'parser-production-rhs
|
||||||
"production must have form [(symbol ...) expression] or [(symbol ...) (prec symbol) expression]"
|
"production must have form [(symbol ...) expression] or [(symbol ...) (prec symbol) expression]"
|
||||||
prod-so)))))
|
prod-so)]))
|
||||||
|
|
||||||
;; parse-prod-for-nt: syntax-object -> production list
|
;; parse-prod-for-nt: syntax-object -> production list
|
||||||
(parse-prods-for-nt
|
(define (parse-prods-for-nt prods-so)
|
||||||
(lambda (prods-so)
|
|
||||||
(syntax-case prods-so ()
|
(syntax-case prods-so ()
|
||||||
((nt productions ...)
|
[(NT PRODUCTIONS ...)
|
||||||
(> (length (syntax->list (syntax (productions ...)))) 0)
|
(positive? (length (syntax->list #'(PRODUCTIONS ...))))
|
||||||
(let ((nt (hash-table-get non-term-table
|
(let ([nt (hash-ref non-term-table (syntax->datum #'NT))])
|
||||||
(syntax-object->datum (syntax nt)))))
|
(map (λ (p) (parse-prod+action nt p)) (syntax->list #'(PRODUCTIONS ...))))]
|
||||||
(map (lambda (p) (parse-prod+action nt p))
|
[_ (raise-syntax-error
|
||||||
(syntax->list (syntax (productions ...))))))
|
|
||||||
(_
|
|
||||||
(raise-syntax-error
|
|
||||||
'parser-productions
|
'parser-productions
|
||||||
"A production for a non-terminal must be (non-term right-hand-side ...) with at least 1 right hand side"
|
"A production for a non-terminal must be (non-term right-hand-side ...) with at least 1 right hand side"
|
||||||
prods-so))))))
|
prods-so)]))
|
||||||
|
|
||||||
(for-each
|
(for ([sstx (in-list start)]
|
||||||
(lambda (sstx ssym)
|
[ssym (in-list start-syms)]
|
||||||
(unless (memq ssym list-of-non-terms)
|
#:unless (memq ssym list-of-non-terms))
|
||||||
(raise-syntax-error
|
(raise-syntax-error
|
||||||
'parser-start
|
'parser-start
|
||||||
(format "Start symbol ~a not defined as a non-terminal" ssym)
|
(format "Start symbol ~a not defined as a non-terminal" ssym)
|
||||||
sstx)))
|
sstx))
|
||||||
start start-syms)
|
|
||||||
|
|
||||||
(let* ((starts (map (lambda (x) (make-non-term (gensym) #f)) start-syms))
|
(define starts (map (λ (x) (make-non-term (gensym) #f)) start-syms))
|
||||||
(end-non-terms (map (lambda (x) (make-non-term (gensym) #f)) start-syms))
|
(define end-non-terms (map (λ (x) (make-non-term (gensym) #f)) start-syms))
|
||||||
(parsed-prods (map parse-prods-for-nt (syntax->list prods)))
|
(define parsed-prods (map parse-prods-for-nt (syntax->list prods)))
|
||||||
(start-prods
|
(define start-prods (for/list ([start (in-list starts)]
|
||||||
(map (lambda (start end-non-term)
|
[end-non-term (in-list end-non-terms)])
|
||||||
(list (make-prod start (vector end-non-term) #f #f
|
(list (make-prod start (vector end-non-term) #f #f #'values))))
|
||||||
(syntax (lambda (x) x)))))
|
(define new-prods
|
||||||
starts end-non-terms))
|
(append start-prods
|
||||||
(prods
|
(for/list ([end-nt (in-list end-non-terms)]
|
||||||
`(,@start-prods
|
[start-sym (in-list start-syms)])
|
||||||
,@(map
|
(for/list ([end (in-list end-terms)])
|
||||||
(lambda (end-nt start-sym)
|
|
||||||
(map
|
|
||||||
(lambda (end)
|
|
||||||
(make-prod end-nt
|
(make-prod end-nt
|
||||||
(vector
|
(vector
|
||||||
(hash-table-get non-term-table start-sym)
|
(hash-ref non-term-table start-sym)
|
||||||
(hash-table-get term-table end))
|
(hash-ref term-table end))
|
||||||
#f
|
#f
|
||||||
#f
|
#f
|
||||||
(syntax (lambda (x) x))))
|
#'values)))
|
||||||
end-terms))
|
parsed-prods))
|
||||||
end-non-terms start-syms)
|
|
||||||
,@parsed-prods)))
|
|
||||||
|
|
||||||
(make-object grammar%
|
(make-object grammar%
|
||||||
prods
|
new-prods
|
||||||
(map car start-prods)
|
(map car start-prods)
|
||||||
terms
|
terms
|
||||||
(append starts (append end-non-terms non-terms))
|
(append starts (append end-non-terms non-terms))
|
||||||
(map (lambda (term-name)
|
(map (λ (term-name) (hash-ref term-table term-name)) end-terms)))
|
||||||
(hash-table-get term-table term-name))
|
|
||||||
end-terms)))))))
|
|
||||||
|
@ -1,118 +1,71 @@
|
|||||||
(module yacc-helper mzscheme
|
#lang racket/base
|
||||||
|
(require (prefix-in rl: racket/list)
|
||||||
(require mzlib/list
|
|
||||||
"../private-lex/token-syntax.rkt")
|
"../private-lex/token-syntax.rkt")
|
||||||
|
|
||||||
;; General helper routines
|
;; General helper routines
|
||||||
|
|
||||||
(provide duplicate-list? remove-duplicates overlap? vector-andmap display-yacc)
|
(provide duplicate-list? remove-duplicates overlap? vector-andmap display-yacc)
|
||||||
|
|
||||||
(define (vector-andmap f v)
|
(define (vector-andmap pred vec)
|
||||||
(let loop ((i 0))
|
(for/and ([item (in-vector vec)])
|
||||||
(cond
|
(pred vec)))
|
||||||
((= i (vector-length v)) #t)
|
|
||||||
(else (if (f (vector-ref v i))
|
|
||||||
(loop (add1 i))
|
|
||||||
#f)))))
|
|
||||||
|
|
||||||
;; duplicate-list?: symbol list -> #f | symbol
|
;; duplicate-list?: symbol list -> #f | symbol
|
||||||
;; returns a symbol that exists twice in l, or false if no such symbol
|
;; returns a symbol that exists twice in l, or false if no such symbol
|
||||||
;; exists
|
;; exists
|
||||||
(define (duplicate-list? l)
|
(define (duplicate-list? syms)
|
||||||
(letrec ((t (make-hash-table))
|
(rl:check-duplicates syms eq?))
|
||||||
(dl? (lambda (l)
|
|
||||||
(cond
|
|
||||||
((null? l) #f)
|
|
||||||
((hash-table-get t (car l) (lambda () #f)) =>
|
|
||||||
(lambda (x) x))
|
|
||||||
(else
|
|
||||||
(hash-table-put! t (car l) (car l))
|
|
||||||
(dl? (cdr l)))))))
|
|
||||||
(dl? l)))
|
|
||||||
|
|
||||||
;; remove-duplicates: syntax-object list -> syntax-object list
|
;; remove-duplicates: syntax-object list -> syntax-object list
|
||||||
;; removes the duplicates from the lists
|
;; removes the duplicates from the lists
|
||||||
(define (remove-duplicates sl)
|
(define (remove-duplicates syms)
|
||||||
(let ((t (make-hash-table)))
|
(rl:remove-duplicates syms equal? #:key syntax->datum))
|
||||||
(letrec ((x
|
|
||||||
(lambda (sl)
|
|
||||||
(cond
|
|
||||||
((null? sl) sl)
|
|
||||||
((hash-table-get t (syntax-object->datum (car sl)) (lambda () #f))
|
|
||||||
(x (cdr sl)))
|
|
||||||
(else
|
|
||||||
(hash-table-put! t (syntax-object->datum (car sl)) #t)
|
|
||||||
(cons (car sl) (x (cdr sl))))))))
|
|
||||||
(x sl))))
|
|
||||||
|
|
||||||
;; overlap?: symbol list * symbol list -> #f | symbol
|
;; overlap?: symbol list * symbol list -> #f | symbol
|
||||||
;; Returns an symbol in l1 intersect l2, or #f is no such symbol exists
|
;; Returns an symbol in l1 intersect l2, or #f is no such symbol exists
|
||||||
(define (overlap? l1 l2)
|
(define (overlap? syms1 syms2)
|
||||||
(let/ec ret
|
(for/first ([sym1 (in-list syms1)]
|
||||||
(let ((t (make-hash-table)))
|
#:when (memq sym1 syms2))
|
||||||
(for-each (lambda (s1)
|
sym1))
|
||||||
(hash-table-put! t s1 s1))
|
|
||||||
l1)
|
|
||||||
(for-each (lambda (s2)
|
|
||||||
(cond
|
|
||||||
((hash-table-get t s2 (lambda () #f)) =>
|
|
||||||
(lambda (o) (ret o)))))
|
|
||||||
l2)
|
|
||||||
#f)))
|
|
||||||
|
|
||||||
|
|
||||||
(define (display-yacc grammar tokens start precs port)
|
(define (display-yacc grammar tokens start precs port)
|
||||||
(let-syntax ((p (syntax-rules ()
|
(let-syntax ([p (syntax-rules ()
|
||||||
((_ args ...) (fprintf port args ...)))))
|
((_ args ...) (fprintf port args ...)))])
|
||||||
(let* ((tokens (map syntax-local-value tokens))
|
(let* ([tokens (map syntax-local-value tokens)]
|
||||||
(eterms (filter e-terminals-def? tokens))
|
[eterms (filter e-terminals-def? tokens)]
|
||||||
(terms (filter terminals-def? tokens))
|
[terms (filter terminals-def? tokens)]
|
||||||
(term-table (make-hash-table))
|
[term-table (make-hasheq)]
|
||||||
(display-rhs
|
[display-rhs
|
||||||
(lambda (rhs)
|
(λ (rhs)
|
||||||
(for-each (lambda (sym) (p "~a " (hash-table-get term-table sym (lambda () sym))))
|
(for ([sym (in-list (car rhs))])
|
||||||
(car rhs))
|
(p "~a " (hash-ref term-table sym (λ () sym))))
|
||||||
(if (= 3 (length rhs))
|
(when (= 3 (length rhs))
|
||||||
(p "%prec ~a" (cadadr rhs)))
|
(p "%prec ~a" (cadadr rhs)))
|
||||||
(p "\n"))))
|
(p "\n"))])
|
||||||
(for-each
|
(for* ([t (in-list eterms)]
|
||||||
(lambda (t)
|
[t (in-list (syntax->datum (e-terminals-def-t t)))])
|
||||||
(for-each
|
(hash-set! term-table t (format "'~a'" t)))
|
||||||
(lambda (t)
|
(for* ([t (in-list terms)]
|
||||||
(hash-table-put! term-table t (format "'~a'" t)))
|
[t (in-list (syntax->datum (terminals-def-t t)))])
|
||||||
(syntax-object->datum (e-terminals-def-t t))))
|
|
||||||
eterms)
|
|
||||||
(for-each
|
|
||||||
(lambda (t)
|
|
||||||
(for-each
|
|
||||||
(lambda (t)
|
|
||||||
(p "%token ~a\n" t)
|
(p "%token ~a\n" t)
|
||||||
(hash-table-put! term-table t (format "~a" t)))
|
(hash-set! term-table t (format "~a" t)))
|
||||||
(syntax-object->datum (terminals-def-t t))))
|
(when precs
|
||||||
terms)
|
(for ([prec (in-list precs)])
|
||||||
(if precs
|
|
||||||
(for-each (lambda (prec)
|
|
||||||
(p "%~a " (car prec))
|
(p "%~a " (car prec))
|
||||||
(for-each (lambda (tok)
|
(for ([tok (in-list (cdr prec))])
|
||||||
(p " ~a" (hash-table-get term-table tok)))
|
(p " ~a" (hash-ref term-table tok)))
|
||||||
(cdr prec))
|
(p "\n")))
|
||||||
(p "\n"))
|
|
||||||
precs))
|
|
||||||
(p "%start ~a\n" start)
|
(p "%start ~a\n" start)
|
||||||
(p "%%\n")
|
(p "%%\n")
|
||||||
|
(for ([prod (in-list grammar)])
|
||||||
(for-each (lambda (prod)
|
(define nt (car prod))
|
||||||
(let ((nt (car prod)))
|
|
||||||
(p "~a: " nt)
|
(p "~a: " nt)
|
||||||
(display-rhs (cadr prod))
|
(display-rhs (cadr prod))
|
||||||
(for-each (lambda (rhs)
|
(for ([rhs (in-list (cddr prod))])
|
||||||
(p "| ")
|
(p "| ")
|
||||||
(display-rhs rhs))
|
(display-rhs rhs))
|
||||||
(cddr prod))
|
(p ";\n"))
|
||||||
(p ";\n")))
|
|
||||||
grammar)
|
|
||||||
(p "%%\n"))))
|
(p "%%\n"))))
|
||||||
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue