use syntax/parse for parsing honu forms
svn: r17620
This commit is contained in:
parent
91629fd31a
commit
9c2ea4c1cf
|
@ -5,7 +5,13 @@
|
||||||
|
|
||||||
(provide (rename-out (#%dynamic-honu-module-begin #%module-begin))
|
(provide (rename-out (#%dynamic-honu-module-begin #%module-begin))
|
||||||
#%datum
|
#%datum
|
||||||
)
|
true
|
||||||
|
false
|
||||||
|
display
|
||||||
|
else
|
||||||
|
(rename-out
|
||||||
|
(honu-if if)
|
||||||
|
))
|
||||||
|
|
||||||
#;
|
#;
|
||||||
(provide int real bool obj
|
(provide int real bool obj
|
||||||
|
|
|
@ -1,25 +1,28 @@
|
||||||
#lang scheme/base
|
#lang scheme/base
|
||||||
|
|
||||||
(require (rename-in typed-scheme/minimal (#%module-begin #%module-begin-typed-scheme)))
|
(require (rename-in typed-scheme (#%module-begin #%module-begin-typed-scheme)))
|
||||||
(require (for-syntax scheme/base
|
(require (for-syntax scheme/base
|
||||||
syntax/stx
|
syntax/stx
|
||||||
|
syntax/name
|
||||||
|
syntax/define
|
||||||
syntax/parse
|
syntax/parse
|
||||||
"contexts.ss"
|
"contexts.ss"
|
||||||
"util.ss"
|
"util.ss"
|
||||||
"ops.ss"
|
"ops.ss"
|
||||||
))
|
)
|
||||||
|
;; "typed-utils.ss"
|
||||||
|
)
|
||||||
|
|
||||||
(provide (all-defined-out))
|
(provide (all-defined-out))
|
||||||
|
|
||||||
;; macro for defining literal tokens that can be used in macros
|
;; macro for defining literal tokens that can be used in macros
|
||||||
(define-syntax-rule (define-literal name)
|
(define-syntax-rule (define-literal name)
|
||||||
(define-syntax name (lambda (stx)
|
(define-syntax name (lambda (stx)
|
||||||
(raise-syntax-error 'name
|
(raise-syntax-error 'name
|
||||||
"this is a literal and cannot be used outside a macro"))))
|
"this is a literal and cannot be used outside a macro"))))
|
||||||
|
|
||||||
(define-literal honu-return)
|
(define-literal honu-return)
|
||||||
|
|
||||||
|
|
||||||
(begin-for-syntax
|
(begin-for-syntax
|
||||||
|
|
||||||
(define-values (prop:honu-transformer honu-transformer? honu-transformer-ref)
|
(define-values (prop:honu-transformer honu-transformer? honu-transformer-ref)
|
||||||
|
@ -40,6 +43,8 @@
|
||||||
proc))
|
proc))
|
||||||
(make-honu-trans proc))
|
(make-honu-trans proc))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(define operator?
|
(define operator?
|
||||||
(let ([sym-chars (string->list "+-_=?:<>.!%^&*/~|")])
|
(let ([sym-chars (string->list "+-_=?:<>.!%^&*/~|")])
|
||||||
(lambda (stx)
|
(lambda (stx)
|
||||||
|
@ -313,13 +318,14 @@
|
||||||
parse-tail-expr
|
parse-tail-expr
|
||||||
parse-expr)]
|
parse-expr)]
|
||||||
[code (parser expr-stxs)])
|
[code (parser expr-stxs)])
|
||||||
(with-syntax ([top-expr ((if (top-block-context? context)
|
(with-syntax ([code code])
|
||||||
(lambda (x)
|
(with-syntax ([top-expr (if (top-block-context? context)
|
||||||
`(show-top-result ,x))
|
#'(let ([v code])
|
||||||
values)
|
(unless (void? v)
|
||||||
code)])
|
(printf "~s\n" v)))
|
||||||
(combine-k #'(#%expression top-expr)
|
#'code)])
|
||||||
(stx-cdr after-expr)))))
|
(combine-k #'(#%expression top-expr)
|
||||||
|
(stx-cdr after-expr))))))
|
||||||
(cond
|
(cond
|
||||||
[(stx-null? body) (done-k)]
|
[(stx-null? body) (done-k)]
|
||||||
[(get-transformer body) =>
|
[(get-transformer body) =>
|
||||||
|
@ -329,12 +335,172 @@
|
||||||
[else (call-values parse-one (extract-until body (list #'\;
|
[else (call-values parse-one (extract-until body (list #'\;
|
||||||
)))]))
|
)))]))
|
||||||
|
|
||||||
|
(define (parse-block stx ctx)
|
||||||
|
(let loop ([stx stx])
|
||||||
|
(parse-block-one ctx
|
||||||
|
stx
|
||||||
|
(lambda (code rest)
|
||||||
|
(cons code (loop rest)))
|
||||||
|
(lambda ()
|
||||||
|
null))))
|
||||||
|
|
||||||
|
(define (expression-result ctx expr rest)
|
||||||
|
(if (top-block-context? ctx)
|
||||||
|
(values #`(#%expression (show-top-result #,expr)) rest)
|
||||||
|
(values #`(#%expression #,expr) rest)))
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
(define-syntax (define-honu-syntax stx)
|
||||||
|
(let-values ([(id rhs) (normalize-definition stx #'lambda #f)])
|
||||||
|
(with-syntax ([id id]
|
||||||
|
[rhs rhs])
|
||||||
|
#'(define-syntax id (make-honu-transformer rhs)))))
|
||||||
|
|
||||||
|
|
||||||
|
#|
|
||||||
|
|
||||||
|
Yes, check out head patterns and splicing syntax classes.
|
||||||
|
|
||||||
|
For example, if 'display' is a special kind of statement, you might have something like this:
|
||||||
|
|
||||||
|
(define-splicing-syntax-class statement
|
||||||
|
(pattern (~seq (~literal display) something (~literal \;)))
|
||||||
|
___ <other alternatives> ___)
|
||||||
|
|
||||||
|
Then, in the pattern above for 'if', 'then' would be bound to the following syntax list:
|
||||||
|
(display (#%braces "hello world") \;)
|
||||||
|
|
||||||
|
(if expr block else statement rest)
|
||||||
|
(if expr block rest)
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
(define-honu-syntax honu-if
|
||||||
|
(lambda (stx ctx)
|
||||||
|
(define (parse-complete-block stx)
|
||||||
|
;; (printf "Parsing complete block ~a\n" (syntax->datum stx))
|
||||||
|
(with-syntax ([(exprs ...) (parse-block stx ctx)])
|
||||||
|
#'(begin exprs ...))
|
||||||
|
#;
|
||||||
|
(let-values ([(a b)
|
||||||
|
(parse-block-one
|
||||||
|
(if (block-context-return? ctx)
|
||||||
|
the-expression-return-block-context
|
||||||
|
the-expression-block-context)
|
||||||
|
stx
|
||||||
|
(lambda (expr rest)
|
||||||
|
(values expr rest))
|
||||||
|
(lambda ()
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"expected a braced block or a statement"
|
||||||
|
)))])
|
||||||
|
(printf "Result is ~a and ~a\n" a b)
|
||||||
|
a))
|
||||||
|
;; TODO: move these syntax classes to a module
|
||||||
|
(define-syntax-class expr
|
||||||
|
[pattern e])
|
||||||
|
(define-syntax-class paren-expr
|
||||||
|
[pattern (#%parens expr:expr)])
|
||||||
|
(define-syntax-class block
|
||||||
|
[pattern (#%braces statement ...)
|
||||||
|
#:with line (parse-complete-block #'(statement ...))])
|
||||||
|
;; (printf "Original syntax ~a\n" (syntax->datum stx))
|
||||||
|
(syntax-parse stx
|
||||||
|
#:literals (else)
|
||||||
|
[(_ condition:paren-expr on-true:block else on-false:block . rest)
|
||||||
|
;; (printf "used if with else\n")
|
||||||
|
(let ([result #'(if condition.expr on-true.line on-false.line)])
|
||||||
|
(expression-result ctx result #'rest))]
|
||||||
|
[(_ condition:paren-expr on-true:block . rest)
|
||||||
|
;; (printf "used if with no else\n")
|
||||||
|
(let ([result #'(when condition.expr on-true.line)])
|
||||||
|
(expression-result ctx result #'rest))])))
|
||||||
|
|
||||||
|
#|
|
||||||
|
if (foo){
|
||||||
|
blah..
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
#;
|
||||||
|
(define-honu-syntax honu-if
|
||||||
|
(lambda (stx ctx)
|
||||||
|
(define (get-block-or-statement kw rest)
|
||||||
|
(syntax-parse rest (#%braces)
|
||||||
|
[((#%braces then ...) . rrest)
|
||||||
|
(values
|
||||||
|
#`(honu-unparsed-block #f obj 'obj #f #,(and (block-context-return? ctx)
|
||||||
|
(stx-null? rest))
|
||||||
|
. #,(stx-cdr (stx-car rest)))
|
||||||
|
#'rrest)]
|
||||||
|
[else
|
||||||
|
(parse-block-one (if (block-context-return? ctx)
|
||||||
|
the-expression-return-block-context
|
||||||
|
the-expression-block-context)
|
||||||
|
rest
|
||||||
|
(lambda (expr rest)
|
||||||
|
(values expr rest))
|
||||||
|
(lambda ()
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"expected a braced block or a statement"
|
||||||
|
kw)))]))
|
||||||
|
|
||||||
|
(unless (block-context? ctx)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"allowed only in a block context"
|
||||||
|
(stx-car stx)))
|
||||||
|
|
||||||
|
(syntax-parse stx (#%parens)
|
||||||
|
[(_ (#%parens test ...) . rest)
|
||||||
|
(let* ([tests #'(test ...)])
|
||||||
|
(when (stx-null? tests)
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"missing test expression"
|
||||||
|
(stx-car stx)
|
||||||
|
(stx-car (stx-cdr stx))))
|
||||||
|
(let ([test-expr (parse-expr (syntax->list tests))])
|
||||||
|
(let-values ([(then-exprs rest) (get-block-or-statement (stx-car stx) #'rest)])
|
||||||
|
(syntax-case rest (else)
|
||||||
|
[(else . rest2)
|
||||||
|
(let-values ([(else-exprs rest) (get-block-or-statement (stx-car rest) #'rest2)])
|
||||||
|
(expression-result ctx
|
||||||
|
#`(if (as-test #,test-expr) #,then-exprs #,else-exprs)
|
||||||
|
rest))]
|
||||||
|
[_else
|
||||||
|
(expression-result ctx #`(if (as-test #,test-expr) #,then-exprs (void)) rest)]))))]
|
||||||
|
[_else
|
||||||
|
(raise-syntax-error
|
||||||
|
#f
|
||||||
|
"expected a parenthesized test after `if' keyword"
|
||||||
|
(stx-car stx))])))
|
||||||
|
|
||||||
|
(define true #t)
|
||||||
|
(define false #f)
|
||||||
|
|
||||||
(define (show-top-result v)
|
(define (show-top-result v)
|
||||||
(unless (void? v)
|
(unless (void? v)
|
||||||
(printf "~s\n" v)))
|
(printf "~s\n" v)))
|
||||||
|
|
||||||
|
(define-syntax (op-app stx)
|
||||||
|
(syntax-case stx (#%parens #%angles)
|
||||||
|
[(_ #%parens a (b ...))
|
||||||
|
#'(a b ...)
|
||||||
|
#;
|
||||||
|
#'(honu-app a b ...)]
|
||||||
|
[(_ #%angles a (b ...))
|
||||||
|
#'(honu-type-app a b ...)]
|
||||||
|
[(_ a b ...)
|
||||||
|
(datum->syntax #'a
|
||||||
|
(cons #'a #'(b ...))
|
||||||
|
#'a)]))
|
||||||
|
|
||||||
(define-syntax (honu-unparsed-begin stx)
|
(define-syntax (honu-unparsed-begin stx)
|
||||||
(syntax-case stx ()
|
(syntax-case stx ()
|
||||||
[(_) #'(begin)]
|
[(_) #'(begin)]
|
||||||
|
@ -348,6 +514,8 @@
|
||||||
#'(begin code (honu-unparsed-begin rest ...))))]))
|
#'(begin code (honu-unparsed-begin rest ...))))]))
|
||||||
|
|
||||||
(define-syntax-rule (#%dynamic-honu-module-begin forms ...)
|
(define-syntax-rule (#%dynamic-honu-module-begin forms ...)
|
||||||
(#%module-begin-typed-scheme (honu-unparsed-begin forms ...))
|
|
||||||
#;
|
#;
|
||||||
|
(#%module-begin-typed-scheme
|
||||||
|
;; (require honu/private/typed-utils)
|
||||||
|
(honu-unparsed-begin forms ...))
|
||||||
(#%plain-module-begin (honu-unparsed-begin forms ...)))
|
(#%plain-module-begin (honu-unparsed-begin forms ...)))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user