implement `print` and `goto`

dev-elider-3
Matthew Butterick 9 years ago
parent 36ca9f1442
commit 6962bc331d

@ -6,37 +6,51 @@
(define #'(basic-module-begin PARSE-TREE ...) (define #'(basic-module-begin PARSE-TREE ...)
#'(#%module-begin #'(#%module-begin
'PARSE-TREE ...)) PARSE-TREE ...))
(define #'(basic-program LINE ...) (define #'(basic-program LINE ...)
#'(begin #'(basic-run LINE ...))
(define program-lines (vector LINE ...))
(run program-lines)))
(define (run program-lines) (define (basic-run . lines)
(define program-lines (list->vector (filter (λ(x) x) lines)))
(for/fold ([line-idx 0]) (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 (list line-number proc jump-number) (match-define (cons line-number proc)
(vector-ref program-lines line-idx)) (vector-ref program-lines line-idx))
(when proc (proc)) (define maybe-jump-number (and proc (proc)))
(if jump-number (if (number? maybe-jump-number)
(for/first ([idx (in-range (vector-length program-lines))] (let ([jump-number maybe-jump-number])
#:when (= (car (vector-ref program-lines idx)) jump-number)) (for/or ([idx (in-range (vector-length program-lines))])
idx) (and (= (car (vector-ref program-lines idx)) jump-number)
idx)))
(add1 line-idx)))) (add1 line-idx))))
;; model each line as (list line-number line-thunk jump) ;; model each line as (cons line-number line-thunk)
;; if jump is #f, that means go to the next line
;; a `GOTO` would not have a line-thunk, just a jump
;; what about `GOSUB`? A jump with a return jump ...
(define-cases #'line (define-cases #'line
[#'(line 'end) #'(list #f #f #f)] [#'(line 'end) #'#f]
[#'(_ NUMBER (statement ARG ...) 'end) #'(list NUMBER (statement ARG ...) #f)] [#'(_ NUMBER STATEMENT 'end) #'(cons NUMBER (λ _ STATEMENT))]
[#'(_ (statement ARG ...) 'end) #'(list #f (statement ARG ...) #f)]) [#'(_ STATEMENT 'end) #'(cons #f (λ _ STATEMENT))])
(define #'(statement NAME ARG ...) #'(NAME ARG ...))
(define #'(expression ITEM) #'ITEM)
(define #'(unsignedexpr ITEM) #'ITEM)
(define #'(term ITEM) #'ITEM)
(define #'(factor ITEM) #'ITEM)
(define #'(number ITEM) #'ITEM)
(define #'(printitem EXPR-OR-STRING) #'EXPR-OR-STRING)
(define #'(printlist ITEM-OR-SEPARATOR ...) #'(list ITEM-OR-SEPARATOR ...))
(define (PRINT args)
(for-each display args)
(displayln ""))
(define (GOTO where)
where)
(define-cases #'statement
[#'(_ "PRINT" EXPR-LIST) #'(λ _ (begin (for-each display EXPR-LIST) (displayln "")))])
(define-cases #'expr-list (define-cases #'expr-list
[#'(_ EXPR ...) #'(list EXPR ...)]) [#'(_ EXPR ...) #'(list EXPR ...)])

@ -1,32 +1,55 @@
#lang ragg #lang ragg
;; adapted from http://www.ittybittycomputers.com/IttyBitty/TinyBasic/TBuserMan.txt
basic-program : line* basic-program : line*
line : CR | NUMBER statement CR | statement CR line : NUMBER statement CR | statement CR | CR
| NUMBER statement | statement
statement : "PRINT" expr-list statement : "PRINT" printlist
| "IF" expression relop expression "THEN" statement | "PR" printlist
| "GOTO" expression | "INPUT" varlist
| "INPUT" var-list
| "LET" var "=" expression | "LET" var "=" expression
| var "=" expression
| "GOTO" expression
| "GOSUB" expression | "GOSUB" expression
| "RETURN" | "RETURN"
| "IF" expression relop expression "THEN" statement
| "IF" expression relop expression statement
;| "REM" commentstring ; todo: implement in tokenizer
| "CLEAR" | "CLEAR"
| "LIST"
| "RUN" | "RUN"
| "END" | "RUN" exprlist
| "LIST"
| "LIST" exprlist
printlist : printitem [(":" | separator printlist)]
expr-list : (STRING | expression) ("," (STRING | expression) )* printitem : expression | STRING
var-list : var ("," var)* varlist: var ["," varlist]
expression : term (("+"|"-") term)* exprlist : expression ["," exprlist]
term : factor (("*"|"/") factor)* expression : [("+"|"-")] unsignedexpr
factor : var | NUMBER | (expression) unsignedexpr : term [("+"|"-") unsignedexpr]
term : factor [("*"|"/") term]
factor : var
| number
| "(" expression ")"
| function
function : "RND(" expression ")"
| "USR(" exprlist ")"
number : NUMBER
separator : "," | ";"
var : UPPERCASE var : UPPERCASE
relop : "<" (">"|"="|"ε") | ">" ("<"|"="|"ε") | "=" digit: DIGIT
relop : "<" [("="|">")] | ">" [("="|"<")] | "="

@ -1,2 +1,7 @@
#lang br/basic #lang br/basic
20 GOTO 10 10 PRINT "shit"
20 PRINT "bird"
25 PRINT "dork"
30 GOTO 10

@ -12,7 +12,7 @@
["\n" (token 'CR ''end)] ["\n" (token 'CR ''end)]
[(union "PRINT" "IF" "THEN" "GOTO" [(union "PRINT" "IF" "THEN" "GOTO"
"INPUT" "LET" "GOSUB" "RETURN" "INPUT" "LET" "GOSUB" "RETURN"
"CLEAR" "LIST" "RUN" "END") 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]

Loading…
Cancel
Save