-
Notifications
You must be signed in to change notification settings - Fork 0
/
lexer.sld
69 lines (64 loc) · 2.02 KB
/
lexer.sld
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
(define-library (lexer)
(import (scheme base)
(scheme char)
(chibi match))
(export tokenize)
(begin
;; convert string to tokens
(define (tokenize str)
(tokenize-aux (string->list str)))
;; split list while condition
(define (list-split-while fn ls)
(let loop ((acc '())
(ls ls))
(cond ((null? ls)
(list (reverse acc) ls))
((fn (car ls))
(loop (cons (car ls) acc) (cdr ls)))
(else
(list (reverse acc) ls)))))
;; get digit token
(define (get-digit hd tl)
(let* ((splitted (list-split-while char-numeric? tl))
(digit (string->number
(list->string
(cons hd (car splitted)))))
(tl (cadr splitted)))
(list digit tl)))
;; err unexpected char
(define (unexpected-char c)
(error (string-append "err unexpected character '"
(string c)
"'")))
;; main tokenizing function
(define (tokenize-aux ls)
(let loop ((acc '())
(ls ls))
(match ls
(()
(reverse acc))
(((? char-whitespace? hd) tl ...)
(loop acc tl))
(((? char-numeric? hd) tl ...)
(let ((splitted (get-digit hd tl)))
(loop (cons (car splitted) acc) (cadr splitted))))
((#\+ tl ...)
(loop (cons 'PLUS acc) tl))
((#\- tl ...)
(loop (cons 'MINUS acc) tl))
((#\* tl ...)
(loop (cons 'STAR acc) tl))
((#\/ tl ...)
(loop (cons 'SLASH acc) tl))
((#\% tl ...)
(loop (cons 'PERCENT acc) tl))
((#\^ tl ...)
(loop (cons 'CARET acc) tl))
((#\( tl ...)
(loop (cons 'LPAREN acc) tl))
((#\) tl ...)
(loop (cons 'RPAREN acc) tl))
((hd tl ...)
(unexpected-char hd))
(_ (error "err lexing error")))))
))