(module deriv-parser mzscheme (require "yacc-ext.ss" "yacc-interrupted.ss" "deriv.ss" "deriv-util.ss" "deriv-tokens.ss") (provide parse-derivation) (define (deriv-error ok? name value start end) (if ok? (error 'derivation-parser "error on token #~a: <~s, ~s>" start name value) (error 'derivation-parser "bad token #~a" start))) ;; PARSER (define (parse-derivation x) (parameterize ((current-sequence-number 0)) (parse-derivation* x))) (define current-sequence-number (make-parameter #f)) (define (new-sequence-number) (let ([seq (current-sequence-number)]) (current-sequence-number (add1 seq)) seq)) (define parse-derivation* (parser (options (start Expansion) (src-pos) (tokens basic-tokens prim-tokens renames-tokens) (end EOF) (error deriv-error) #;(debug "debug-parser.txt")) ;; Required (non-hygienically) by productions/I (productions #;(Error [(syntax-error) $1]) (NoError [() #f])) ;; tokens (skipped-token-values visit resolve next next-group return enter-macro macro-pre-transform macro-post-transform exit-macro enter-prim exit-prim enter-block block->list block->letrec splice enter-list exit-list enter-check exit-check local-post exit-local exit-local/expr phase-up module-body renames-lambda renames-case-lambda renames-let renames-letrec-syntaxes renames-block IMPOSSIBLE) ;; Entry point (productions (Expansion [(start EE/Lifts) $2] [(start EE/Lifts/Interrupted) $2])) (productions/I ;; Expansion of an expression ;; EE Answer = Derivation (I) (EE (#:no-wrap) [(visit (? PrimStep 'prim) return) $2] [(visit (? TaggedPrimStep 'prim) return) ($2 $1)] [(visit VariableStep return) ($2 $1 $3)] [((? EE/Macro)) $1]) (EE/Macro [(visit (? MacroStep 'macro) (? EE 'next)) (make-mrule $1 (and (deriv? $3) (deriv-e2 $3)) $2 $3)]) ;; Expand/Lifts ;; Expand/Lifts Answer = Derivation (I) (EE/Lifts (#:no-wrap) [((? EE)) $1] [((? EE/Lifts+)) $1]) (EE/Lifts+ [(EE lift-loop (? EE/Lifts)) (let ([initial (deriv-e1 $1)] [final (and (deriv? $3) (deriv-e2 $3))]) (make-lift-deriv initial final $1 $2 $3))]) ;; Expand/LetLifts ;; Expand/LetLifts Answer = Derivation (I) ;; Used for expand_lift_to_let (rhs of define-syntaxes, mostly) (EE/LetLifts (#:no-wrap) [((? EE)) $1] [((? EE/LetLifts+)) $1]) (EE/LetLifts+ [(EE lift/let-loop (? EE/LetLifts)) (let ([initial (deriv-e1 $1)] [final (and (deriv? $3) (deriv-e2 $3))]) (make-lift/let-deriv initial final $1 $2 $3))]) ;; Evaluation (Eval (#:no-wrap) [() #f] [(start (? EE) (? Eval)) #f] [(start (? CheckImmediateMacro) (? Eval)) #f]) ;; Expansion of an expression to primitive form ;; CheckImmediateMacro Answer = Derivation (I) (CheckImmediateMacro (#:no-wrap) [(enter-check (? CheckImmediateMacro/Inner) exit-check) ($2 $1 $3 (lambda (ce1 ce2) (make-p:stop ce1 ce2 null)))]) (CheckImmediateMacro/Inner (#:args e1 e2 k) [() (k e1 e2)] [(visit (? MacroStep 'macro) return (? CheckImmediateMacro/Inner 'next)) (let ([next ($4 $3 e2 k)]) (make-mrule $1 (and (deriv? next) (deriv-e2 next)) $2 next))]) ;; Expansion of multiple expressions, next-separated ;; NextEEs Answer = (listof Derivation) (NextEEs (#:no-wrap) (#:skipped null) [() null] [(next (? EE 'first) (? NextEEs 'rest)) (cons $2 $3)]) ;; Keyword resolution ;; Resolves Answer = (listof identifier) (Resolves [() null] [(resolve Resolves) (cons $1 $2)]) ;; Single macro step (may contain local-expand calls) ;; MacroStep Answer = Transformation (I,E) (MacroStep [(Resolves enter-macro (! 'bad-transformer) macro-pre-transform (? LocalActions 'locals) (! 'transform) macro-post-transform exit-macro) (make-transformation $2 $8 $1 $4 $7 $5 (new-sequence-number))]) ;; Local actions taken by macro ;; LocalAction Answer = (list-of LocalAction) (LocalActions (#:no-wrap) (#:skipped null) [() null] [((? LocalAction) (? LocalActions)) (cons $1 $2)] [((? NotReallyLocalAction) (? LocalActions)) $2]) (LocalAction (#:no-wrap) [(enter-local local-pre start (? EE) local-post exit-local) (make-local-expansion $1 $6 $2 $5 #f $4)] [(enter-local phase-up local-pre start (? EE) local-post exit-local) (make-local-expansion $1 $7 $3 $6 #t $5)] [(enter-local/expr local-pre start (? EE) local-post exit-local/expr) (make-local-expansion/expr $1 (car $6) $2 $5 #f (cdr $6) $4)] [(enter-local/expr local-pre phase-up start (? EE) local-post exit-local/expr) (make-local-expansion/expr $1 (car $7) $3 $6 #t (cdr $7) $5)] [(lift) (make-local-lift (cdr $1) (car $1))] [(lift-statement) (make-local-lift-end $1)] [(phase-up (? EE/LetLifts)) (make-local-bind $2)]) (NotReallyLocalAction (#:no-wrap) ;; called 'expand' (not 'local-expand') within transformer [(start (? EE)) (make-local-expansion (lift/deriv-e1 $2) (lift/deriv-e2 $2) (lift/deriv-e1 $2) (lift/deriv-e2 $2) #f $2)]) ;; Multiple calls to local-expand ;; EEs Answer = (listof Derivation) (EEs (#:skipped null) (#:no-wrap) [() null] [((? EE 'first) (? EEs 'rest)) (cons $1 $2)]) ;; Primitive syntax step ;; PrimStep Answer = PRule (PrimStep (#:no-wrap) [(Resolves NoError enter-prim (? Prim) exit-prim) ($4 $3 $5 $1)]) (VariableStep (#:no-wrap) (#:args e1 e2) [(Resolves variable) (make-p:variable e1 e2 $1)]) ;; Tagged Primitive syntax ;; TaggedPrimStep Answer = syntax -> PRule (TaggedPrimStep (#:no-wrap) (#:args orig-stx) [(Resolves ! IMPOSSIBLE) (make-p:unknown orig-stx #f $1)] [(Resolves NoError enter-prim ! IMPOSSIBLE) (make-p:unknown orig-stx #f $1)] [(Resolves NoError enter-prim (? TaggedPrim) exit-prim) ($4 orig-stx $5 $1 $3)]) ;; Primitive ;; Prim Answer = syntax syntax (listof identifier) -> PRule (Prim (#:args e1 e2 rs) (#:no-wrap) [((? PrimModule)) ($1 e1 e2 rs)] [((? Prim#%ModuleBegin)) ($1 e1 e2 rs)] [((? PrimDefineSyntaxes)) ($1 e1 e2 rs)] [((? PrimDefineValues)) ($1 e1 e2 rs)] [((? PrimExpression)) ($1 e1 e2 rs)] [((? PrimIf)) ($1 e1 e2 rs)] [((? PrimWCM)) ($1 e1 e2 rs)] [((? PrimSet)) ($1 e1 e2 rs)] [((? PrimBegin)) ($1 e1 e2 rs)] [((? PrimBegin0)) ($1 e1 e2 rs)] [((? PrimLambda)) ($1 e1 e2 rs)] [((? PrimCaseLambda)) ($1 e1 e2 rs)] [((? PrimLetValues)) ($1 e1 e2 rs)] [((? PrimLet*Values)) ($1 e1 e2 rs)] [((? PrimLetrecValues)) ($1 e1 e2 rs)] [((? PrimLetrecSyntaxes+Values)) ($1 e1 e2 rs)] [((? PrimSTOP)) ($1 e1 e2 rs)] [((? PrimQuote)) ($1 e1 e2 rs)] [((? PrimQuoteSyntax)) ($1 e1 e2 rs)] [((? PrimRequire)) ($1 e1 e2 rs)] [((? PrimRequireForSyntax)) ($1 e1 e2 rs)] [((? PrimRequireForTemplate)) ($1 e1 e2 rs)] [((? PrimProvide)) ($1 e1 e2 rs)]) ;; Tagged Primitive ;; TaggedPrim Answer = syntax syntax (list-of identifier) syntax -> PRule (TaggedPrim (#:args e1 e2 rs tagged-stx) (#:no-wrap) [((? Prim#%App)) ($1 e1 e2 rs tagged-stx)] [((? Prim#%Datum)) ($1 e1 e2 rs tagged-stx)] [((? Prim#%Top)) ($1 e1 e2 rs tagged-stx)]) ;; Modules (PrimModule (#:args e1 e2 rs) ;; Multiple forms after language ;; #%module-begin tagging done automatically [(prim-module ! (? Eval) (? EE 'body)) (make-p:module e1 e2 rs #f $4)] ;; One form after language ... macro that expands into #%module-begin [(prim-module NoError next enter-check (? CheckImmediateMacro/Inner) exit-check (! 'module-begin) next (? EE)) (make-p:module e1 e2 rs #t ($5 $4 (and (deriv? $9) (deriv-e2 $9)) (lambda (ce1 ce2) $9)))]) (Prim#%ModuleBegin (#:args e1 e2 rs) [(prim-#%module-begin (! 'malformed) (? ModulePass1 'pass1) next-group (? ModulePass2 'pass2) (! 'provides)) (make-p:#%module-begin e1 e2 rs $3 $5)]) (ModulePass1 (#:skipped null) (#:no-wrap) [() null] [(next (? ModulePass1-Part) (? ModulePass1)) (cons $2 $3)] [(module-lift-end-loop (? ModulePass1)) (cons (make-mod:lift-end $1) $2)]) (ModulePass1-Part (#:no-wrap) [((? EE) (? ModulePass1/Prim)) (make-mod:prim $1 $2)] [(EE NoError module-lift-loop) (make-mod:lift $1 $2)] [(EE ! splice) (make-mod:splice $1 $3)]) (ModulePass1/Prim [(enter-prim prim-define-values ! exit-prim) (make-p:define-values $1 $4 null #f)] [(enter-prim prim-define-syntaxes ! phase-up (? EE/LetLifts) (? Eval) exit-prim) (make-p:define-syntaxes $1 $7 null $5)] [(enter-prim prim-require ! (? Eval) exit-prim) (make-p:require $1 $5 null)] [(enter-prim prim-require-for-syntax ! (? Eval) exit-prim) (make-p:require-for-syntax $1 $5 null)] [(enter-prim prim-require-for-template ! (? Eval) exit-prim) (make-p:require-for-template $1 $5 null)] [(enter-prim prim-provide ! exit-prim) (make-p:provide $1 $4 null)] [() #f]) (ModulePass2 (#:skipped null) (#:no-wrap) [() null] [(next (? ModulePass2-Part) (? ModulePass2)) (cons $2 $3)] [(module-lift-end-loop (? ModulePass2)) (cons (make-mod:lift-end $1) $2)]) (ModulePass2-Part (#:no-wrap) ;; not normal; already handled [() (make-mod:skip)] ;; normal: expand completely [((? EE)) (make-mod:cons $1)] ;; catch lifts [(EE module-lift-loop) (make-mod:lift $1 $2)]) ;; Definitions (PrimDefineSyntaxes (#:args e1 e2 rs) [(prim-define-syntaxes ! (? EE/LetLifts) (? Eval)) (make-p:define-syntaxes e1 e2 rs $3)]) (PrimDefineValues (#:args e1 e2 rs) [(prim-define-values ! (? EE)) (make-p:define-values e1 e2 rs $3)]) ;; Simple expressions (PrimExpression (#:args e1 e2 rs) [(prim-expression ! (? EE 'inner)) (make-p:expression e1 e2 rs $3)]) (PrimIf (#:args e1 e2 rs) [(prim-if ! (? EE 'test) next (? EE 'then) next (? EE 'else)) (make-p:if e1 e2 rs #t $3 $5 $7)] [(prim-if NoError next-group (? EE 'test) next (? EE 'then)) (make-p:if e1 e2 rs #f $4 $6 #f)]) (PrimWCM (#:args e1 e2 rs) [(prim-wcm ! (? EE 'key) next (? EE 'mark) next (? EE 'body)) (make-p:wcm e1 e2 rs $3 $5 $7)]) ;; Sequence-containing expressions (PrimBegin (#:args e1 e2 rs) [(prim-begin ! (? EL)) (make-p:begin e1 e2 rs $3)]) (PrimBegin0 (#:args e1 e2 rs) [(prim-begin0 ! next (? EE) next (? EL)) (make-p:begin0 e1 e2 rs $4 $6)]) (Prim#%App (#:args e1 e2 rs tagged-stx) [(prim-#%app !) (make-p:#%app e1 e2 rs tagged-stx (make-lderiv null null null))] [(prim-#%app NoError (? EL)) (make-p:#%app e1 e2 rs tagged-stx $3)]) ;; Binding expressions (PrimLambda (#:args e1 e2 rs) [(prim-lambda ! renames-lambda (? EB)) (make-p:lambda e1 e2 rs $3 $4)]) (PrimCaseLambda (#:args e1 e2 rs) [(prim-case-lambda ! (? NextCaseLambdaClauses)) (make-p:case-lambda e1 e2 rs $3)]) (NextCaseLambdaClauses (#:skipped null) [(next ! renames-case-lambda (? EB 'first) (? NextCaseLambdaClauses 'rest)) (cons (cons $3 $4) $5)] [() null]) (PrimLetValues (#:args e1 e2 rs) [(prim-let-values ! renames-let (? NextEEs 'rhss) next-group (? EB 'body)) (make-p:let-values e1 e2 rs $3 $4 $6)]) (PrimLet*Values (#:args e1 e2 rs) ;; let*-values with bindings is "macro-like" [(prim-let*-values ! (? EE)) (let ([next-e1 (lift/deriv-e1 $3)]) (make-mrule e1 e2 (make-transformation e1 next-e1 rs e1 next-e1 null (new-sequence-number)) $3))] ;; No bindings... model as "let" [(prim-let*-values NoError renames-let (? NextEEs 'rhss) next-group (? EB 'body)) (make-p:let-values e1 e2 rs $3 $4 $6)]) (PrimLetrecValues (#:args e1 e2 rs) [(prim-letrec-values ! renames-let (? NextEEs 'rhss) next-group (? EB 'body)) (make-p:letrec-values e1 e2 rs $3 $4 $6)]) (PrimLetrecSyntaxes+Values (#:args e1 e2 rs) [(prim-letrec-syntaxes+values (! 'bad-syntax) renames-letrec-syntaxes (? NextBindSyntaxess 'srhss) next-group (? EB 'body)) (make-p:letrec-syntaxes+values e1 e2 rs $3 $4 #f null $6)] [(prim-letrec-syntaxes+values NoError renames-letrec-syntaxes NextBindSyntaxess next-group prim-letrec-values (! 'impossible?) renames-let (? NextEEs 'vrhss) next-group (? EB 'body)) (make-p:letrec-syntaxes+values e1 e2 rs $3 $4 $8 $9 $11)]) ;; Atomic expressions (Prim#%Datum (#:args e1 e2 rs tagged-stx) [(prim-#%datum !) (make-p:#%datum e1 e2 rs tagged-stx)]) (Prim#%Top (#:args e1 e2 rs tagged-stx) [(prim-#%top !) (make-p:#%top e1 e2 rs tagged-stx)]) (PrimSTOP (#:args e1 e2 rs) [(prim-stop !) (make-p:stop e1 e2 rs)]) (PrimQuote (#:args e1 e2 rs) [(prim-quote !) (make-p:quote e1 e2 rs)]) (PrimQuoteSyntax (#:args e1 e2 rs) [(prim-quote-syntax !) (make-p:quote-syntax e1 e2 rs)]) (PrimRequire (#:args e1 e2 rs) [(prim-require ! (? Eval)) (make-p:require e1 e2 rs)]) (PrimRequireForSyntax (#:args e1 e2 rs) [(prim-require-for-syntax ! (? Eval)) (make-p:require-for-syntax e1 e2 rs)]) (PrimRequireForTemplate (#:args e1 e2 rs) [(prim-require-for-template ! (? Eval)) (make-p:require-for-template e1 e2 rs)]) (PrimProvide (#:args e1 e2 rs) [(prim-provide !) (make-p:provide e1 e2 rs)]) (PrimSet (#:args e1 e2 rs) [(prim-set! ! Resolves next (? EE)) (make-p:set! e1 e2 rs $3 $5)] [(prim-set! NoError (? MacroStep 'macro) (? EE 'continue)) (make-p:set!-macro e1 e2 rs (make-mrule e1 (and (deriv? $4) (deriv-e2 $4)) $3 $4))]) ;; Blocks ;; EB Answer = BlockDerivation (EB [(enter-block (? BlockPass1 'pass1) block->list (? EL 'pass2)) (make-bderiv $1 (and (lderiv? $4) (lderiv-es2 $4)) $2 'list $4)] [(enter-block BlockPass1 block->letrec (? EL 'pass2)) (make-bderiv $1 (and (lderiv? $4) (lderiv-es2 $4)) $2 'letrec $4)]) ;; BlockPass1 Answer = (list-of BRule) (BlockPass1 (#:no-wrap) (#:skipped null) [() null] [((? BRule) (? BlockPass1)) (cons $1 $2)]) ;; BRule Answer = BRule (BRule [(next ! IMPOSSIBLE) #f] [(next NoError renames-block (? CheckImmediateMacro 'check)) (make-b:expr $3 $4)] [(next NoError renames-block CheckImmediateMacro prim-begin ! splice !) (make-b:splice $3 $4 $7)] [(next NoError renames-block CheckImmediateMacro prim-define-values !) (make-b:defvals $3 $4)] [(next NoError renames-block CheckImmediateMacro prim-define-syntaxes (? BindSyntaxes 'bind)) (make-b:defstx $3 $4 $6)]) ;; BindSyntaxes Answer = Derivation (BindSyntaxes [(phase-up (? EE/LetLifts) ! (? Eval)) $2]) ;; NextBindSyntaxess Answer = (list-of Derivation) (NextBindSyntaxess (#:skipped null) (#:no-wrap) [() null] [(next (? BindSyntaxes 'first) (? NextBindSyntaxess 'rest)) (cons $2 $3)]) ;; Lists ;; EL Answer = ListDerivation (EL (#:skipped #f) [(enter-list ! (? EL*) exit-list) (make-lderiv $1 $4 $3)]) ;; EL* Answer = (listof Derivation) (EL* (#:no-wrap) (#:skipped null) [() null] [(next (? EE 'first) (? EL* 'rest)) (cons $2 $3)]) ))) )