start basic interpreter
parent
739269f889
commit
158fd4a561
@ -0,0 +1,4 @@
|
||||
#lang br
|
||||
(module reader br
|
||||
(require br/basic/reader)
|
||||
(provide (all-from-out br/basic/reader)))
|
@ -0,0 +1,39 @@
|
||||
#lang br
|
||||
(provide (all-defined-out)
|
||||
#%top-interaction
|
||||
#%datum
|
||||
(rename-out [basic-module-begin #%module-begin]))
|
||||
|
||||
(define #'(basic-module-begin PARSE-TREE ...)
|
||||
#'(#%module-begin
|
||||
'PARSE-TREE ...))
|
||||
|
||||
(define #'(basic-program LINE ...)
|
||||
#'(begin
|
||||
(define program-lines (vector LINE ...))
|
||||
(run program-lines)))
|
||||
|
||||
(define (run program-lines)
|
||||
(for/fold ([line-idx 0])
|
||||
([i (in-naturals)]
|
||||
#:break (= line-idx (vector-length program-lines)))
|
||||
(match-define (list line-number proc jump-number)
|
||||
(vector-ref program-lines line-idx))
|
||||
(when proc (proc))
|
||||
(if jump-number
|
||||
(for/first ([idx (in-range (vector-length program-lines))]
|
||||
#:when (= (car (vector-ref program-lines idx)) jump-number))
|
||||
idx)
|
||||
(add1 line-idx))))
|
||||
|
||||
(define-cases #'line
|
||||
[#'(line 'end) #'(list #f #f #f)]
|
||||
[#'(_ NUMBER (statement ARG ...) 'end) #'(list NUMBER (statement ARG ...) #f)]
|
||||
[#'(_ (statement ARG ...) 'end) #'(list #f (statement ARG ...) #f)])
|
||||
|
||||
(define-cases #'statement
|
||||
[#'(_ "PRINT" EXPR-LIST) #'(λ _ (begin (for-each display EXPR-LIST) (displayln "")))])
|
||||
|
||||
(define-cases #'expr-list
|
||||
[#'(_ EXPR ...) #'(list EXPR ...)])
|
||||
|
@ -0,0 +1,32 @@
|
||||
#lang ragg
|
||||
|
||||
basic-program : line*
|
||||
|
||||
line : CR | NUMBER statement CR | statement CR
|
||||
| NUMBER statement | statement
|
||||
|
||||
statement : "PRINT" expr-list
|
||||
| "IF" expression relop expression "THEN" statement
|
||||
| "GOTO" expression
|
||||
| "INPUT" var-list
|
||||
| "LET" var "=" expression
|
||||
| "GOSUB" expression
|
||||
| "RETURN"
|
||||
| "CLEAR"
|
||||
| "LIST"
|
||||
| "RUN"
|
||||
| "END"
|
||||
|
||||
expr-list : (STRING | expression) ("," (STRING | expression) )*
|
||||
|
||||
var-list : var ("," var)*
|
||||
|
||||
expression : term (("+"|"-") term)*
|
||||
|
||||
term : factor (("*"|"/") factor)*
|
||||
|
||||
factor : var | NUMBER | (expression)
|
||||
|
||||
var : UPPERCASE
|
||||
|
||||
relop : "<" (">"|"="|"ε") | ">" ("<"|"="|"ε") | "="
|
@ -0,0 +1,7 @@
|
||||
#lang br
|
||||
(require br/reader-utils br/basic/parser br/basic/tokenizer)
|
||||
|
||||
(define-read-and-read-syntax (source-path input-port)
|
||||
(strip-context
|
||||
#`(module bf-mod br/basic/expander
|
||||
#,(parse source-path (tokenize input-port)))))
|
@ -0,0 +1,2 @@
|
||||
#lang br/basic
|
||||
20 GOTO 10
|
@ -0,0 +1,24 @@
|
||||
#lang br
|
||||
(require parser-tools/lex
|
||||
(prefix-in : parser-tools/lex-sre)
|
||||
ragg/support
|
||||
racket/string)
|
||||
(provide tokenize)
|
||||
|
||||
(define (tokenize input-port)
|
||||
(define (next-token)
|
||||
(define get-token
|
||||
(lexer
|
||||
["\n" (token 'CR ''end)]
|
||||
[(union "PRINT" "IF" "THEN" "GOTO"
|
||||
"INPUT" "LET" "GOSUB" "RETURN"
|
||||
"CLEAR" "LIST" "RUN" "END") lexeme]
|
||||
;; this only matches integers
|
||||
[(repetition 1 +inf.0 numeric) (token 'NUMBER (string->number lexeme))]
|
||||
[(char-set ",+-ε*/<>=") lexeme]
|
||||
[upper-case (token 'UPPERCASE lexeme)]
|
||||
[whitespace (token 'WHITESPACE lexeme #:skip? #t)]
|
||||
[(:seq "\"" (complement (:: any-string "\"" any-string)) "\"") (token 'STRING (string-trim lexeme "\""))]
|
||||
[(eof) eof]))
|
||||
(get-token input-port))
|
||||
next-token)
|
Loading…
Reference in New Issue