Adding basic parser of rash language
This commit is contained in:
parent
ffd808fbd6
commit
b8a0eecba7
51
rash-lang.rkt
Normal file
51
rash-lang.rkt
Normal file
|
@ -0,0 +1,51 @@
|
|||
#lang racket/base
|
||||
|
||||
(require syntax/readerr
|
||||
(prefix-in rash: "rash.rkt"))
|
||||
|
||||
(define (rash-read in)
|
||||
(syntax->datum (rash-read-syntax #f in)))
|
||||
|
||||
(define (rash-read-syntax src in)
|
||||
(define-values (start-line start-col start-pos) (port-next-location in))
|
||||
(define (list->rash-syntax l span)
|
||||
(datum->syntax #f
|
||||
(cons 'start l)
|
||||
(vector src start-line start-col start-pos span)))
|
||||
|
||||
(let loop ([words '()]
|
||||
[delta 0])
|
||||
(define-values (line col pos) (port-next-location in))
|
||||
(cond
|
||||
[(regexp-try-match #px"^[[:alnum:]]+" in) =>
|
||||
(λ (r)
|
||||
(define m (bytes->string/utf-8 (car r)))
|
||||
(define len (string-length m))
|
||||
(define word (datum->syntax #f m (vector src line col pos len)))
|
||||
(loop (cons word words) len))]
|
||||
[(regexp-try-match #px"^\n" in) => (λ (m) (list->rash-syntax
|
||||
(reverse words)
|
||||
delta))]
|
||||
[(regexp-try-match #px"^[ \t]+" in) => (λ (r)
|
||||
(define m
|
||||
(bytes->string/utf-8 (car r)))
|
||||
(displayln m)
|
||||
(loop words (string-length m)))]
|
||||
[(eof-object? (peek-char in)) (list->rash-syntax (reverse words) delta)]
|
||||
[else (raise-read-error
|
||||
(string-append "Unknown character " (read-char in))
|
||||
src line col pos 1)])))
|
||||
|
||||
(module+ test
|
||||
(require rackunit)
|
||||
|
||||
(define (2port str)
|
||||
(open-input-string str))
|
||||
|
||||
(test-case
|
||||
"Read alphanumeric words with EOF"
|
||||
(check equal? '(start "echo" "hello1") (rash-read (2port "echo hello1"))))
|
||||
|
||||
(test-case
|
||||
"Read string with newline"
|
||||
(check equal? '(start "echo") (rash-read (2port "echo\n")))))
|
Loading…
Reference in New Issue
Block a user