set up basic-demo-2
parent
d0f83eb24a
commit
c58ac2a806
@ -0,0 +1,61 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(provide (rename-out [b-module-begin #%module-begin])
|
||||||
|
(matching-identifiers-out #rx"^b-" (all-defined-out)))
|
||||||
|
|
||||||
|
(define-macro (b-module-begin (b-program LINE ...))
|
||||||
|
(with-pattern
|
||||||
|
([(LINE-NUM ...)
|
||||||
|
(filter-stx-prop 'b-line-number
|
||||||
|
(stx-flatten #'(LINE ...)))]
|
||||||
|
[(LINE-ID ...) (prefix-ids "line-" #'(LINE-NUM ...))])
|
||||||
|
#'(#%module-begin
|
||||||
|
LINE ...
|
||||||
|
(define line-table
|
||||||
|
(apply hasheqv (append (list LINE-NUM LINE-ID) ...)))
|
||||||
|
(run line-table))))
|
||||||
|
|
||||||
|
(define-macro (b-line LINE-NUMBER STATEMENT ...)
|
||||||
|
(with-pattern
|
||||||
|
([LINE-NUMBER-ID (prefix-id "line-" #'LINE-NUMBER
|
||||||
|
#:source #'LINE-NUMBER)]
|
||||||
|
[ORIG-LOC caller-stx])
|
||||||
|
(syntax/loc caller-stx
|
||||||
|
(define (LINE-NUMBER-ID #:srcloc? [loc #f])
|
||||||
|
(if loc
|
||||||
|
(syntax-srcloc #'ORIG-LOC)
|
||||||
|
(begin (void) STATEMENT ...))))))
|
||||||
|
|
||||||
|
(define b-rem void)
|
||||||
|
(define (b-print [val ""]) (displayln val))
|
||||||
|
(define (b-sum . nums) (apply + nums))
|
||||||
|
(define (b-num-expr expr)
|
||||||
|
(if (integer? expr) (inexact->exact expr) expr))
|
||||||
|
|
||||||
|
(struct $program-end-signal ())
|
||||||
|
(define (b-end) (raise ($program-end-signal)))
|
||||||
|
|
||||||
|
(struct $change-line-signal (val))
|
||||||
|
(define (b-goto expr) (raise ($change-line-signal expr)))
|
||||||
|
|
||||||
|
(define-exn line-not-found exn:fail)
|
||||||
|
|
||||||
|
(define (run line-table)
|
||||||
|
(define line-vec
|
||||||
|
(list->vector (sort (hash-keys line-table) <)))
|
||||||
|
(with-handlers ([$program-end-signal? void])
|
||||||
|
(for/fold ([line-idx 0])
|
||||||
|
([i (in-naturals)])
|
||||||
|
(unless (< line-idx (vector-length line-vec)) (b-end))
|
||||||
|
(define line-num (vector-ref line-vec line-idx))
|
||||||
|
(define line-proc (hash-ref line-table line-num))
|
||||||
|
(with-handlers
|
||||||
|
([$change-line-signal?
|
||||||
|
(λ (cls)
|
||||||
|
(define clsv ($change-line-signal-val cls))
|
||||||
|
(or
|
||||||
|
(and (exact-positive-integer? clsv)
|
||||||
|
(vector-member clsv line-vec))
|
||||||
|
(raise-line-not-found
|
||||||
|
(line-proc #:srcloc? #t))))])
|
||||||
|
(line-proc)
|
||||||
|
(add1 line-idx)))))
|
@ -0,0 +1,85 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(require (for-syntax racket/list sugar/debug))
|
||||||
|
(provide (matching-identifiers-out #rx"^b-" (all-defined-out)))
|
||||||
|
|
||||||
|
(struct line-error (msg))
|
||||||
|
|
||||||
|
(define (handle-line-error num le)
|
||||||
|
(error (format "error in line ~a: ~a" num (line-error-msg le))))
|
||||||
|
|
||||||
|
(define return-ks empty)
|
||||||
|
|
||||||
|
(define (b-gosub num-expr)
|
||||||
|
(let/cc return-k
|
||||||
|
(push! return-ks return-k)
|
||||||
|
(b-goto num-expr)))
|
||||||
|
|
||||||
|
(define (b-return)
|
||||||
|
(unless (pair? return-ks)
|
||||||
|
(raise (line-error "return without gosub")))
|
||||||
|
(define top-return-k (pop! return-ks))
|
||||||
|
(top-return-k))
|
||||||
|
|
||||||
|
(define-macro (b-line NUM STATEMENT ...)
|
||||||
|
(with-pattern ([LINE-NUM (prefix-id "line-" #'NUM
|
||||||
|
#:source #'NUM)])
|
||||||
|
(syntax/loc caller-stx
|
||||||
|
(define (LINE-NUM)
|
||||||
|
(with-handlers ([line-error? (λ (le) (handle-line-error NUM le))])
|
||||||
|
(void) STATEMENT ...)))))
|
||||||
|
|
||||||
|
(define-for-syntax (find-unique-var-names stx)
|
||||||
|
(remove-duplicates
|
||||||
|
(for/list ([var-stx (in-list (syntax-flatten stx))]
|
||||||
|
#:when (syntax-property var-stx 'b-id))
|
||||||
|
var-stx)
|
||||||
|
#:key syntax->datum))
|
||||||
|
|
||||||
|
(define-macro (b-module-begin (b-program LINE ...))
|
||||||
|
(with-pattern
|
||||||
|
([((b-line NUM STMT ...) ...) #'(LINE ...)]
|
||||||
|
[(LINE-FUNC ...) (prefix-id "line-" #'(NUM ...))]
|
||||||
|
[(VAR-NAME ...) (find-unique-var-names #'(LINE ...))])
|
||||||
|
#'(#%module-begin
|
||||||
|
(define VAR-NAME 0) ...
|
||||||
|
LINE ...
|
||||||
|
(define line-table
|
||||||
|
(apply hasheqv (append (list NUM LINE-FUNC) ...)))
|
||||||
|
(void (run line-table)))))
|
||||||
|
(provide (rename-out [b-module-begin #%module-begin]))
|
||||||
|
|
||||||
|
(define-macro (b-let ID VAL)
|
||||||
|
#'(set! ID VAL))
|
||||||
|
|
||||||
|
(struct end-program-signal ())
|
||||||
|
(struct change-line-signal (val))
|
||||||
|
|
||||||
|
(define (b-end) (raise (end-program-signal)))
|
||||||
|
(define (b-goto num-expr) (raise (change-line-signal num-expr)))
|
||||||
|
|
||||||
|
(define (run line-table)
|
||||||
|
(define line-vec
|
||||||
|
(list->vector (sort (hash-keys line-table) <)))
|
||||||
|
(with-handlers ([end-program-signal? (λ (exn-val) (void))])
|
||||||
|
(for/fold ([line-idx 0])
|
||||||
|
([i (in-naturals)]
|
||||||
|
#:break (>= line-idx (vector-length line-vec)))
|
||||||
|
(define line-num (vector-ref line-vec line-idx))
|
||||||
|
(define line-func (hash-ref line-table line-num))
|
||||||
|
(with-handlers
|
||||||
|
([change-line-signal?
|
||||||
|
(λ (cls)
|
||||||
|
(define clsv (change-line-signal-val cls))
|
||||||
|
(or
|
||||||
|
(and (exact-positive-integer? clsv)
|
||||||
|
(vector-member clsv line-vec))
|
||||||
|
(error (format "error in line ~a: line ~a not found"
|
||||||
|
line-num clsv))))])
|
||||||
|
(line-func)
|
||||||
|
(add1 line-idx)))))
|
||||||
|
|
||||||
|
(define (b-rem val) (void))
|
||||||
|
(define (b-print [val ""]) (displayln val))
|
||||||
|
(define (b-sum . nums) (apply + nums))
|
||||||
|
(define (b-num-expr expr)
|
||||||
|
(if (integer? expr) (inexact->exact expr) expr))
|
@ -0,0 +1,3 @@
|
|||||||
|
#lang br
|
||||||
|
(provide b-gosub b-return)
|
||||||
|
|
@ -0,0 +1,4 @@
|
|||||||
|
#lang info
|
||||||
|
|
||||||
|
(define compile-omit-paths 'all)
|
||||||
|
(define test-omit-paths 'all)
|
@ -0,0 +1,58 @@
|
|||||||
|
#lang br
|
||||||
|
(require "lexer.rkt" brag/support rackunit)
|
||||||
|
|
||||||
|
(define (lex str)
|
||||||
|
(apply-lexer basic-lexer str))
|
||||||
|
|
||||||
|
(check-equal? (lex "") empty)
|
||||||
|
(check-equal?
|
||||||
|
(lex " ")
|
||||||
|
(list (srcloc-token (token " " #:skip? #t)
|
||||||
|
(srcloc 'string #f #f 1 1))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "rem ignored\n")
|
||||||
|
(list (srcloc-token (token 'REM "rem ignored")
|
||||||
|
(srcloc 'string #f #f 1 11))
|
||||||
|
(srcloc-token (token 'NEWLINE "\n")
|
||||||
|
(srcloc 'string #f #f 12 1))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "print")
|
||||||
|
(list (srcloc-token "print"
|
||||||
|
(srcloc 'string #f #f 1 5))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "goto")
|
||||||
|
(list (srcloc-token "goto"
|
||||||
|
(srcloc 'string #f #f 1 4))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "end")
|
||||||
|
(list (srcloc-token "end"
|
||||||
|
(srcloc 'string #f #f 1 3))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "+")
|
||||||
|
(list (srcloc-token "+"
|
||||||
|
(srcloc 'string #f #f 1 1))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "12")
|
||||||
|
(list (srcloc-token (token 'INTEGER 12)
|
||||||
|
(srcloc 'string #f #f 1 2))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "1.2")
|
||||||
|
(list (srcloc-token (token 'DECIMAL 1.2)
|
||||||
|
(srcloc 'string #f #f 1 3))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "12.")
|
||||||
|
(list (srcloc-token (token 'DECIMAL 12.)
|
||||||
|
(srcloc 'string #f #f 1 3))))
|
||||||
|
(check-equal?
|
||||||
|
(lex ".12")
|
||||||
|
(list (srcloc-token (token 'DECIMAL .12)
|
||||||
|
(srcloc 'string #f #f 1 3))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "\"foo\"")
|
||||||
|
(list (srcloc-token (token 'STRING "foo")
|
||||||
|
(srcloc 'string #f #f 1 5))))
|
||||||
|
(check-equal?
|
||||||
|
(lex "'foo'")
|
||||||
|
(list (srcloc-token (token 'STRING "foo")
|
||||||
|
(srcloc 'string #f #f 1 5))))
|
||||||
|
(check-exn exn:fail:read? (lambda () (lex "x")))
|
@ -0,0 +1,23 @@
|
|||||||
|
#lang br
|
||||||
|
(require brag/support)
|
||||||
|
|
||||||
|
(define-lex-abbrev digits (:+ (char-set "0123456789")))
|
||||||
|
|
||||||
|
(define basic-lexer
|
||||||
|
(lexer-srcloc
|
||||||
|
[(eof) (return-without-srcloc eof)]
|
||||||
|
["\n" (token 'NEWLINE lexeme)]
|
||||||
|
[whitespace (token lexeme #:skip? #t)]
|
||||||
|
[(from/stop-before "rem" "\n") (token 'REM lexeme)]
|
||||||
|
[(:or "print" "goto" "end" "+" ":" "gosub" "return" "let" "=") lexeme]
|
||||||
|
[(:seq (:+ alphabetic) (:* (:or alphabetic numeric))) (token 'ID (string->symbol lexeme))]
|
||||||
|
[digits (token 'INTEGER (string->number lexeme))]
|
||||||
|
[(:or (:seq (:? digits) "." digits)
|
||||||
|
(:seq digits "."))
|
||||||
|
(token 'DECIMAL (string->number lexeme))]
|
||||||
|
[(:or (from/to "\"" "\"") (from/to "'" "'"))
|
||||||
|
(token 'STRING
|
||||||
|
(substring lexeme
|
||||||
|
1 (sub1 (string-length lexeme))))]))
|
||||||
|
|
||||||
|
(provide basic-lexer)
|
@ -0,0 +1,11 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(require "parser.rkt" "tokenizer.rkt")
|
||||||
|
|
||||||
|
(define (read-syntax path port)
|
||||||
|
(define parse-tree (parse path (make-tokenizer port path)))
|
||||||
|
(strip-bindings
|
||||||
|
#`(module basic-mod basic-demo-2/expander
|
||||||
|
#,parse-tree)))
|
||||||
|
|
||||||
|
(module+ reader
|
||||||
|
(provide read-syntax))
|
@ -0,0 +1,14 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(require "parser.rkt" "tokenizer.rkt")
|
||||||
|
|
||||||
|
(define (read-syntax path port)
|
||||||
|
(define parse-tree (parse path (make-tokenizer port path)))
|
||||||
|
(strip-bindings
|
||||||
|
#`(module basic-parser-mod basic-demo/parse-only
|
||||||
|
#,parse-tree)))
|
||||||
|
(module+ reader (provide read-syntax))
|
||||||
|
|
||||||
|
(define-macro (parser-only-mb PARSE-TREE)
|
||||||
|
#'(#%module-begin
|
||||||
|
'PARSE-TREE))
|
||||||
|
(provide (rename-out [parser-only-mb #%module-begin]))
|
@ -0,0 +1,15 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(require "parser.rkt" "tokenizer.rkt")
|
||||||
|
|
||||||
|
(define (read-syntax path port)
|
||||||
|
(define parse-tree (parse path (make-tokenizer port path)))
|
||||||
|
(strip-bindings
|
||||||
|
#`(module basic-parser-mod basic-demo/parse-stx
|
||||||
|
#'#,parse-tree)))
|
||||||
|
(module+ reader (provide read-syntax))
|
||||||
|
|
||||||
|
(define-macro (parser-only-mb PARSE-STX)
|
||||||
|
#'(#%module-begin
|
||||||
|
PARSE-STX))
|
||||||
|
(provide (rename-out [parser-only-mb #%module-begin]))
|
||||||
|
(provide syntax)
|
@ -0,0 +1,17 @@
|
|||||||
|
#lang brag
|
||||||
|
b-program : [b-line] (/NEWLINE [b-line])*
|
||||||
|
b-line : b-line-number [b-statement] (/":" [b-statement])*
|
||||||
|
@b-line-number : INTEGER
|
||||||
|
@b-statement : b-rem | b-end | b-print | b-goto | b-gosub | b-return | b-let
|
||||||
|
b-rem : REM
|
||||||
|
b-end : /"end"
|
||||||
|
b-print : /"print" [STRING | b-num-expr]
|
||||||
|
b-goto : /"goto" b-num-expr
|
||||||
|
b-gosub : /"gosub" b-num-expr
|
||||||
|
b-return : /"return"
|
||||||
|
b-let : [/"let"] b-id /"=" b-num-expr
|
||||||
|
@b-id : ID
|
||||||
|
b-num-expr : b-sum
|
||||||
|
b-sum : b-value (/"+" b-value)*
|
||||||
|
@b-value : b-id | b-number
|
||||||
|
@b-number : INTEGER | DECIMAL
|
@ -0,0 +1,8 @@
|
|||||||
|
(define (30) (rem print "'ignored'"))
|
||||||
|
(define (35) (void))
|
||||||
|
(define (50) (print "never gets here"))
|
||||||
|
(define (40) (end))
|
||||||
|
(define (60) (print "three") (print (+ 1.0 3)))
|
||||||
|
(define (70) (goto (+ 11 18.5 0.5)))
|
||||||
|
(define (10) (print "one"))
|
||||||
|
(define (20) (print) (goto 60) (end))
|
@ -0,0 +1,10 @@
|
|||||||
|
#lang basic-demo-2
|
||||||
|
10 gosub 41
|
||||||
|
20 print "world"
|
||||||
|
30 gosub 100
|
||||||
|
31 print "hi"
|
||||||
|
35 end
|
||||||
|
40 return
|
||||||
|
41 print "hello" : return
|
||||||
|
100 print "third"
|
||||||
|
110 goto 40
|
@ -0,0 +1,8 @@
|
|||||||
|
#lang basic-demo-2
|
||||||
|
10 a = 1 : a = 5
|
||||||
|
20 gosub 150
|
||||||
|
30 a = 25
|
||||||
|
40 gosub 150
|
||||||
|
50 end
|
||||||
|
150 print a + a + a
|
||||||
|
160 return
|
@ -0,0 +1,11 @@
|
|||||||
|
#lang br
|
||||||
|
(require "tokenizer.rkt" "parser.rkt" brag/support)
|
||||||
|
|
||||||
|
(define str #<<here
|
||||||
|
10 rem print
|
||||||
|
20 end
|
||||||
|
|
||||||
|
here
|
||||||
|
)
|
||||||
|
|
||||||
|
(parse-tree (apply-tokenizer-maker make-tokenizer str))
|
@ -0,0 +1,14 @@
|
|||||||
|
#lang br/quicklang
|
||||||
|
(require brag/support "tokenizer.rkt")
|
||||||
|
|
||||||
|
(define (read-syntax path port)
|
||||||
|
(define tokens (apply-tokenizer make-tokenizer port))
|
||||||
|
(strip-bindings
|
||||||
|
#`(module basic-tokens-mod basic-demo/tokenize-only
|
||||||
|
#,@tokens)))
|
||||||
|
(module+ reader (provide read-syntax))
|
||||||
|
|
||||||
|
(define-macro (parser-only-mb TOKEN ...)
|
||||||
|
#'(#%module-begin
|
||||||
|
(list TOKEN ...)))
|
||||||
|
(provide (rename-out [parser-only-mb #%module-begin]))
|
@ -0,0 +1,10 @@
|
|||||||
|
#lang br
|
||||||
|
(require "lexer.rkt" brag/support)
|
||||||
|
|
||||||
|
(define (make-tokenizer ip [path #f])
|
||||||
|
(port-count-lines! ip)
|
||||||
|
(lexer-file-path path)
|
||||||
|
(define (next-token) (basic-lexer ip))
|
||||||
|
next-token)
|
||||||
|
|
||||||
|
(provide make-tokenizer)
|
Loading…
Reference in New Issue