diff options
Diffstat (limited to 'src/modules/lexer/driver.scm')
-rw-r--r-- | src/modules/lexer/driver.scm | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/modules/lexer/driver.scm b/src/modules/lexer/driver.scm new file mode 100644 index 0000000..e1a4f6e --- /dev/null +++ b/src/modules/lexer/driver.scm @@ -0,0 +1,86 @@ +(define-module (modules lexer driver) + #:export (read-tokens)) + +(define (read-tokens) + "Returns a stream of tokens from the +current input port." + (define (read-tokens-loop tokens-so-far) + (let ((token (read-token))) + (if token + (read-tokens-loop (cons token tokens-so-far)) + (reverse tokens-so-far)))) + (read-tokens-loop '())) + +(define (read-token) + (let ((chr (read-char))) + (cond + ((eof-object? chr) #f) + ((char-whitespace? chr) + (read-token)) + + ((eqv? chr #\() + 'left-paren) + ((eqv? chr #\)) + 'right-paren) + ((eqv? chr #\{) + 'open-brace) + ((eqv? chr #\}) + 'close-brace) + ((eqv? chr #\;) + 'semi-colon) + ((eqv? chr #\~) + 'not) + + ((eqv? chr #\+) + (if (take-double? chr) + '++ + '+)) + + ((eqv? chr #\-) + (if (take-double? chr) + '-- + 'neg)) + + ((char-numeric? chr) + (read-constant chr)) + + ((char-alphabetic? chr) + (lookup-keyword (read-identifier chr))) + + (#t (error "illegal lexical syntax"))))) + +(define (read-constant chr) + (define (read-constant-helper chrs-so-far) + (let ((chr (peek-char))) + (cond ((and (not (eof-object? chr)) (char-numeric? chr)) + (read-constant-helper (cons (read-char) chrs-so-far))) + ((and (not (eof-object? chr)) (char-alphabetic? chr)) + (error "identifier starting with digit")) + (#t (reverse chrs-so-far))))) + (string->number (list->string (read-constant-helper (list chr))))) + +(define (read-identifier chr) + (define (read-identifier-helper chrs-so-far) + (let ((chr (peek-char))) + (cond ((and (not (eof-object? chr)) + (or (char-alphabetic? chr) + (char-numeric? chr) + (eqv? chr #\_))) + (read-identifier-helper (cons (read-char) chrs-so-far))) + (#t (reverse chrs-so-far))))) + (list->string (read-identifier-helper (list chr)))) + +(define (take-double? chr) + (if (eqv? chr (peek-char)) + (read-char) + #f)) + +(define (lookup-keyword id) + "Given identifier ID, converts it to a keyword +if one is known." + (let ((found (assoc + id + '(("int" . int) + ("void" . void) + ("return" . return))))) + (if found (cdr found) id))) |