refac scriptish

pull/21/head
Matthew Butterick 5 years ago
parent 37bc753b27
commit 944c543db7

@ -1,50 +1,60 @@
#lang br/quicklang #lang br/quicklang
(require racket/stxparam) (require racket/stxparam)
(provide (all-defined-out) (all-from-out br/quicklang)) (provide (all-defined-out))
(define-macro top #'begin) (define-macro top #'#%module-begin)
(define-macro (assignment ID VAL) #'(define ID VAL)) (define-macro (var ID VAL) #'(define ID VAL))
(define (add/concat . xs) (define (add/concat . xs)
(cond (cond
[(andmap number? xs) (apply + xs)] [(andmap number? xs) (apply + xs)]
[(ormap string? xs) (string-join (map ~a xs) "")])) [(ormap string? xs) (string-join (map ~a xs) "")]))
(define-macro-cases sumlike (define-macro-cases add-or-sub
[(_ VAL) #'VAL] [(_ VAL) #'VAL]
[(_ . VALS) #'(add/concat . VALS)]) [(_ . VALS) #'(add/concat . VALS)])
(define-macro (object (K V) ...) (define-macro (object (K V) ...)
#'(make-hash (list (cons K V) ...))) #'(make-hash (list (cons K V) ...)))
(define-macro (func-def (ARG ...) STMT ...) (define-syntax-parameter return
(λ (stx) (error 'not-parameterized)))
(define-macro (fun (ARG ...) STMT ...)
(syntax/loc caller-stx (syntax/loc caller-stx
(λ (ARG ...) (λ (ARG ...)
(let/cc return-cc (let/cc return-cc
(syntax-parameterize ([return (make-rename-transformer #'return-cc)]) (syntax-parameterize ([return (make-rename-transformer #'return-cc)])
STMT ... (void)))))) STMT ... (void))))))
(define-syntax-parameter return (define (resolve-deref base . keys)
(λ (stx) (error 'not-parameterized))) (for/fold ([val base])
([key (in-list keys)])
(cond
[(and
(hash? val)
(cond
[(hash-ref val key #f)]
[(hash-ref val (symbol->string key) #f)]
[else #f]))]
[else (error 'deref-failure)])))
(define-macro (dotted-id (BASE KEY ...)) (define-macro (deref (BASE KEY ...))
#'(for/fold ([val BASE]) #'(resolve-deref BASE 'KEY ...))
([key (in-list (list 'KEY ...))])
(cond
[(hash-ref val key #f)]
[(hash-ref val (symbol->string key) #f)]
[else (error 'dotted-failure)])))
(define-macro func-app #'#%app) (define-macro app #'#%app)
(define-macro (if COND . STMTS) (define-macro-cases if
#'(when COND . STMTS)) [(_ COND TSTMT ... "else" FSTMT ...) #'(cond
[COND TSTMT ...]
[else FSTMT ...])]
[(_ COND STMT ...) #'(when COND STMT ...)])
(define-macro-cases comparison (define-macro-cases comparison
[(_ VAL) #'VAL] [(_ VAL) #'VAL]
[(_ L == R) #'(equal? L R)] [(_ L "==" R) #'(equal? L R)]
[(_ L != R) #'(not (equal? L R))]) [(_ L "!=" R) #'(not (equal? L R))])
(define-macro (while COND STMT ...) (define-macro (while COND STMT ...)
#'(let loop () #'(let loop ()

@ -0,0 +1,24 @@
#lang brag
top : @statement*
statement : (var | expr | return) /";" | if | while
var : /"var" id /"=" expr
@expr : comparison
comparison : [comparison ("!=" | "==")] add-or-sub
add-or-sub : [@add-or-sub /"+"] value
@value : id | INTEGER | STRING | object
| fun | app | increment
increment : id /"++"
object : /"{" @kvs /"}"
kvs : [kv (/"," kv)*]
/kv : expr /":" expr
fun : /"function" /"(" ids /")" @block
/ids : [id (/"," id)*]
@id : ID | deref
deref : DEREF
block : /"{" @statement* /"}"
return : /"return" expr
app : id /"(" @exprs /")"
exprs : [expr (/"," expr)*]
if : /"if" /"(" expr /")" @block ["else" @block]
while : /"while" /"(" expr /")" @block

@ -1,5 +1,5 @@
#lang br/quicklang #lang br/quicklang
(require "parser.rkt" brag/support) (require "grammar.rkt" brag/support)
(module+ reader (module+ reader
(provide read-syntax)) (provide read-syntax))
@ -7,35 +7,29 @@
(define-lex-abbrev reserved-terms (define-lex-abbrev reserved-terms
(:or "var" "=" ";" "+" "{" "}" "'" "\"" (:or "var" "=" ";" "+" "{" "}" "'" "\""
":" "," "(" ")" "//" "/*" "*/" ":" "," "(" ")" "//" "/*" "*/"
"if" "while" "==" "!=" "function" "return" "++")) "if" "else" "while" "==" "!=" "function" "return" "++"))
(define scriptish-lexer (define tokenize-1
(lexer-srcloc (lexer-srcloc
[(:or (from/stop-before "//" "\n") [(:or (from/stop-before "//" "\n")
(from/to "/*" "*/")) (token 'COMMENT #:skip? #t)] (from/to "/*" "*/")) (token 'COMMENT #:skip? #t)]
[reserved-terms (token lexeme (string->symbol lexeme))] [reserved-terms lexeme]
[(:+ (:- (:or alphabetic punctuation) "." reserved-terms)) [(:+ (:- (:or alphabetic punctuation) "." reserved-terms))
(token 'ID (string->symbol lexeme))] (token 'ID (string->symbol lexeme))]
[(:+ (:- (:or alphabetic punctuation) reserved-terms)) [(:+ (:- (:or alphabetic punctuation) reserved-terms))
(token 'DOTTED-ID (map string->symbol (string-split lexeme ".")))] (token 'DEREF (map string->symbol (string-split lexeme ".")))]
[(:+ (char-set "0123456789")) [(:+ (char-set "0123456789"))
(token 'INTEGER (string->number lexeme))] (token 'INTEGER (string->number lexeme))]
[(:or (from/to "\"" "\"") (from/to "'" "'")) [(:or (from/to "\"" "\"") (from/to "'" "'"))
(let () (token 'STRING (string-trim lexeme (substring lexeme 0 1)))]
(token 'STRING (string-trim lexeme (substring lexeme 0 1))))]
[whitespace (token 'WHITE #:skip? #t)] [whitespace (token 'WHITE #:skip? #t)]
[any-char lexeme])) [any-char lexeme]))
(define (make-tokenizer ip [src #f])
(port-count-lines! ip)
(lexer-file-path src)
(define (next-token) (scriptish-lexer ip))
next-token)
(define (read-syntax src ip) (define (read-syntax src ip)
(println src) (port-count-lines! ip)
(define parse-tree (parse src (make-tokenizer ip src))) (lexer-file-path ip)
(strip-context (define parse-tree (parse src (λ () (tokenize-1 ip))))
(strip-bindings
(with-syntax ([PT parse-tree]) (with-syntax ([PT parse-tree])
#'(module scriptish-mod scriptish-demo/expander #'(module scriptish-mod scriptish-demo/expander
PT)))) PT))))

@ -1,24 +0,0 @@
#lang brag
top : @statement*
statement : (assignment | expr | return) /";" | if | while
assignment : /"var" id /"=" expr
@expr : comparison
comparison : [comparison ("!=" | "==")] sumlike
sumlike : [@sumlike /"+"] value
@value : id | INTEGER | STRING | object
| func-def | func-app | increment
increment : id /"++"
object : /"{" @kvs /"}"
kvs : [kv (/"," kv)*]
/kv : expr /":" expr
func-def : /"function" /"(" ids /")" @block
/ids : [id (/"," id)*]
@id : ID | dotted-id
dotted-id : DOTTED-ID
block : /"{" @statement* /"}"
return : /"return" expr
func-app : id /"(" @exprs /")"
exprs : [expr (/"," expr)*]
if : /"if" /"(" expr /")" @block
while : /"while" /"(" expr /")" @block

@ -20,6 +20,8 @@ thing.bar(3); // prints 18
if ( thing.foo == 42 ) { if ( thing.foo == 42 ) {
// prints "The correct answer is 42" // prints "The correct answer is 42"
alert("The correct answer is " + thing.foo); alert("The correct answer is " + thing.foo);
} else {
alert("Nope");
} }
var idx = 0; var idx = 0;

Loading…
Cancel
Save