fisl

fisl is scheme lox
git clone git://git.alexkarle.com.com/fisl
Log | Files | Refs | README

commit b7516a8f8ebf4d6d03266992cbebc62ad12dde0f (patch)
parent e2a17cb55d232ccd0e9a4277835d753d9ef1ed0f
Author: Alex Karle <alex@alexkarle.com>
Date:   Sun,  2 Oct 2022 00:29:07 -0400

Add initial attempt at scanning basic tokens

Committing now because I'm planning on doing a heavy refactor!

Diffstat:
Mfisl.scm | 21++++++++++++---------
Ascanner.scm | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Atest.lox | 3+++
Autil.scm | 21+++++++++++++++++++++
4 files changed, 102 insertions(+), 9 deletions(-)

diff --git a/fisl.scm b/fisl.scm @@ -1,28 +1,31 @@ #!/usr/bin/chicken-csi -ss ;; fisl -- fisl is scheme lox +(load "scanner.scm") +(load "util.scm") + (import (chicken io) (chicken base) - (chicken format)) + (chicken format) + scanner + util) -(define (run code) - (print code)) +(define (run code fname) + (let ((exit-code 0)) + (print (scan code fname)) + exit-code)) (define (run-prompt) (display "> ") (let ((l (read-line))) (if (not (eof-object? l)) (begin - (run l) + (run l "repl") (run-prompt)) (exit 0)))) (define (run-file fname) (call-with-input-file fname (lambda (p) - (run (read-string #f p))))) - -(define (die str) - (fprintf (current-error-port) "~A\n" str) - (exit 1)) + (exit (run (read-string #f p) fname))))) (define (main args) (let ((argc (length args))) diff --git a/scanner.scm b/scanner.scm @@ -0,0 +1,66 @@ +(load "util.scm") + +(module scanner (scan make-token) + +(import scheme + util + (chicken base) + (chicken format)) + +(define (make-token type lexeme literal line len) + `((type ,type) + (lexeme ,lexeme) + (literal ,literal) + (line ,line) + (len ,len))) + +(define (scan src fname) + (define (comment i) + ; parse comment until end, return stopping point + (let loop ((curr i)) + (if (and (< curr (string-length src)) + (not (eq? #\newline (string-ref src curr)))) + (loop (add1 curr)) + (- curr i)))) + + (define (peek i) + ; safe string-ref + (if (< i (string-length src)) + (string-ref src i) + 'nil)) + + (define (loop i line) + (define (tok type len) + (make-token type (substring src i (+ i len)) 'nil line len)) + (if (< i (string-length src)) + (begin + (let ((c (string-ref src i)) (n (peek (add1 i)))) + (let ((tok (cond + ((eq? #\( c) (tok 'LEFT_PAREN 1)) + ((eq? #\) c) (tok 'RIGHT_PAREN 1)) + ((eq? #\{ c) (tok 'LEFT_BRACE 1)) + ((eq? #\} c) (tok 'RIGHT_BRACE 1)) + ((eq? #\, c) (tok 'COMMA 1)) + ((eq? #\. c) (tok 'DOT 1)) + ((eq? #\- c) (tok 'MINUS 1)) + ((eq? #\+ c) (tok 'PLUS 1)) + ((eq? #\; c) (tok 'SEMICOLON 1)) + ((eq? #\* c) (tok 'STAR 1)) + ((eq? #\! c) (if (eq? #\= n) (tok 'BANG_EQUAL 2) (tok 'BANG 1))) + ((eq? #\= c) (if (eq? #\= n) (tok 'EQUAL_EQUAL 2) (tok 'EQUAL 1))) + ((eq? #\< c) (if (eq? #\< n) (tok 'LESS_EQUAL 2) (tok 'LESS 1))) + ((eq? #\> c) (if (eq? #\> n) (tok 'GREATER_EQUAL 2) (tok 'GREATER 1))) + ((eq? #\/ c) (if (eq? #\/ n) (tok 'COMMENT (comment i)) (tok 'SLASH 1))) + ((eq? #\space c) #f) + ((eq? #\tab c) #f) + ((eq? #\newline c) #f) + ;; TODO: set/return hadError (keep scanning) + (else (err (format "~A:~A:unexpected character: ~A" fname line c)) #f)))) + (if tok + (begin (print tok) + (loop (+ i (get tok 'len)) line)) + (loop (add1 i) line))))) + 'EOF)) + (loop 0 1)) + +) ; end of module diff --git a/test.lox b/test.lox @@ -0,0 +1,3 @@ +(!=) +// this is a comment +!!! diff --git a/util.scm b/util.scm @@ -0,0 +1,21 @@ +(module util (die get err) +(import scheme + (chicken base) + (chicken io) + (chicken format)) + +(define (err str) + (fprintf (current-error-port) "~A\n" str)) + +(define (die str) + (err str) + (exit 1)) + +(define (get assoc-arr key) + ;; fetch from assoc array and error if key not found + (let ((tup (assoc key assoc-arr))) + (if tup + (cadr tup) + (error (format "bad key ~A" key))))) + +) ; end of module