dev-elider-3
Matthew Butterick 9 years ago
parent 7d8d34eab3
commit a0108d27bf

@ -3,9 +3,11 @@
#%top-interaction #%top-interaction
#%datum #%datum
(rename-out [basic-module-begin #%module-begin])) (rename-out [basic-module-begin #%module-begin]))
(require (for-syntax racket/string))
(define #'(basic-module-begin PARSE-TREE ...) (define #'(basic-module-begin PARSE-TREE ...)
#'(#%module-begin #'(#%module-begin
(println (quote PARSE-TREE ...))
PARSE-TREE ...)) PARSE-TREE ...))
(define #'(basic-program LINE ...) (define #'(basic-program LINE ...)
@ -13,24 +15,27 @@
(define (basic-run . lines) (define (basic-run . lines)
(define program-lines (list->vector (filter (λ(x) x) lines))) (define program-lines (list->vector (filter (λ(x) x) lines)))
(for/fold ([line-idx 0]) (void (for/fold ([line-idx 0])
([i (in-naturals)] ([i (in-naturals)]
#:break (= line-idx (vector-length program-lines))) #:break (= line-idx (vector-length program-lines)))
(match-define (cons line-number proc) (match-define (cons line-number proc)
(vector-ref program-lines line-idx)) (vector-ref program-lines line-idx))
(define maybe-jump-number (and proc (proc))) (define maybe-jump-number (and proc (proc)))
(if (number? maybe-jump-number) (if (number? maybe-jump-number)
(let ([jump-number maybe-jump-number]) (let ([jump-number maybe-jump-number])
(for/or ([idx (in-range (vector-length program-lines))]) (for/or ([idx (in-range (vector-length program-lines))])
(and (= (car (vector-ref program-lines idx)) jump-number) (and (= (car (vector-ref program-lines idx)) jump-number)
idx))) idx)))
(add1 line-idx)))) (add1 line-idx)))))
(define #'(CR) #'#f)
(define #'(REM ARG ...) #'(void (list 'ARG ...)))
;; model each line as (cons line-number line-thunk) ;; model each line as (cons line-number line-thunk)
(define-cases #'line (define-cases #'line
[#'(line 'end) #'#f] [#'(_ NUMBER STATEMENT) #'(cons NUMBER (λ _ STATEMENT))]
[#'(_ NUMBER STATEMENT 'end) #'(cons NUMBER (λ _ STATEMENT))] [#'(_ STATEMENT) #'(cons #f (λ _ STATEMENT))])
[#'(_ STATEMENT 'end) #'(cons #f (λ _ STATEMENT))])
(define #'(statement NAME ARG ...) #'(NAME ARG ...)) (define #'(statement NAME ARG ...) #'(NAME ARG ...))
@ -42,11 +47,24 @@
(define #'(printitem EXPR-OR-STRING) #'EXPR-OR-STRING) (define #'(printitem EXPR-OR-STRING) #'EXPR-OR-STRING)
(define #'(printlist ITEM-OR-SEPARATOR ...) #'(list ITEM-OR-SEPARATOR ...)) ;; skip separators
(define #'(printlist . SEPARATED-ITEMS) #`(list #,@(for/list ([(item idx) (in-indexed (syntax->list #'SEPARATED-ITEMS))]
#:when (even? idx))
item)))
(define #'(separator SEP) #'(void))
(define #'(function NAME EXP ")") #`(#,(string->symbol (string-trim (syntax->datum #'NAME) "(")) EXP))
(define (TAB expr)
(make-string expr #\space))
(define (PRINT args) (define (PRINT . args)
(for-each display args) (if (and (= (length args) 1) (list? (car args)))
(displayln "")) (begin
(for-each display (car args))
(displayln ""))
(filter (λ(i) (and (equal? i ":") (displayln ""))) args)))
(define (GOTO where) (define (GOTO where)
where) where)

@ -1,11 +1,18 @@
#lang ragg #lang ragg
;; adapted from http://www.ittybittycomputers.com/IttyBitty/TinyBasic/TBuserMan.txt ;; adapted from http://www.ittybittycomputers.com/IttyBitty/TinyBasic/TBuserMan.txt
basic-program : line* ;; MS Basic extensions
;; http://www.atariarchives.org/basicgames/showpage.php?page=i12
line : NUMBER statement CR | statement CR | CR ;; games
;; http://www.vintage-basic.net/games.html
statement : "PRINT" printlist
basic-program : [CR] line (CR line)* [CR]
line: [NUMBER] statement (":" statement)*
statement : "PRINT" printlist*
| "PR" printlist | "PR" printlist
| "INPUT" varlist | "INPUT" varlist
| "LET" var "=" expression | "LET" var "=" expression
@ -15,20 +22,20 @@ statement : "PRINT" printlist
| "RETURN" | "RETURN"
| "IF" expression relop expression "THEN" statement | "IF" expression relop expression "THEN" statement
| "IF" expression relop expression statement | "IF" expression relop expression statement
;| "REM" commentstring ; todo: implement in tokenizer
| "CLEAR" | "CLEAR"
| "RUN" | "RUN"
| "RUN" exprlist | "RUN" exprlist
| "LIST" | "LIST"
| "LIST" exprlist | "LIST" exprlist
printlist : printitem [(":" | separator printlist)] ; formerly printlist : printitem [(":" | (separator printitem)*)]
printlist : printitem (separator printitem)*
printitem : expression | STRING printitem : expression | STRING
varlist: var ["," varlist] varlist: var ("," var)*
exprlist : expression ["," exprlist] exprlist : expression ("," expression)*
expression : [("+"|"-")] unsignedexpr expression : [("+"|"-")] unsignedexpr
@ -43,12 +50,13 @@ factor : var
function : "RND(" expression ")" function : "RND(" expression ")"
| "USR(" exprlist ")" | "USR(" exprlist ")"
| "TAB(" expression ")"
number : NUMBER number : NUMBER
separator : "," | ";" separator : "," | ";"
var : UPPERCASE var : "A" | "B" | "C" | "D" | "T"
digit: DIGIT digit: DIGIT

@ -0,0 +1,9 @@
#lang br/demo/basic
REM program listing from
REM http://www.vintage-basic.net/bcg/change.bas
2 PRINT TAB(33);"CHANGE"
4 PRINT TAB(15);"CREATIVE COMPUTING MORRISTOWN, NEW JERSEY"
REM 10 PRINT:PRINT

@ -9,13 +9,17 @@
(define (next-token) (define (next-token)
(define get-token (define get-token
(lexer (lexer
["\n" (token 'CR ''end)] [(:seq "REM" (repetition 1 +inf.0 (char-complement "\n")) (repetition 0 +inf.0 "\n"))
(token 'COMMENT lexeme #:skip? #t)]
[(repetition 1 +inf.0 "\n") (token 'CR '(CR))]
[(union "PRINT" "IF" "THEN" "GOTO" [(union "PRINT" "IF" "THEN" "GOTO"
"INPUT" "LET" "GOSUB" "RETURN" "INPUT" "LET" "GOSUB" "RETURN"
"CLEAR" "LIST" "RUN" "END") (string->symbol lexeme)] "CLEAR" "LIST" "RUN" "END") (string->symbol lexeme)]
;; this only matches integers ;; this only matches integers
[(repetition 1 +inf.0 numeric) (token 'NUMBER (string->number lexeme))] [(repetition 1 +inf.0 numeric) (token 'NUMBER (string->number lexeme))]
[(char-set ",+-ε*/<>=") lexeme] [(char-set ",;:+-ε*/<>=()") lexeme]
[(:seq (repetition 1 +inf.0 upper-case) "(") lexeme]
[upper-case (token 'UPPERCASE lexeme)] [upper-case (token 'UPPERCASE lexeme)]
[whitespace (token 'WHITESPACE lexeme #:skip? #t)] [whitespace (token 'WHITESPACE lexeme #:skip? #t)]
[(:seq "\"" (complement (:: any-string "\"" any-string)) "\"") (token 'STRING (string-trim lexeme "\""))] [(:seq "\"" (complement (:: any-string "\"" any-string)) "\"") (token 'STRING (string-trim lexeme "\""))]

Loading…
Cancel
Save