-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtokens.sld
67 lines (64 loc) · 2.56 KB
/
tokens.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
(define-library (tokens)
(export tokenize)
(import (scheme base)
(scheme char)
(srfi 1)
(table))
(begin
; convert an input string into a list of terminals
(define (tokenize input)
(let ((input-list (concatenate `(,(string->list input) (#\null)))))
(tokenize-impl input-list 'start '() '())))
(define (tokenize-impl input state stack output)
(if (null? input)
(reverse output)
(let ((lookahead (car input)))
(let-values (((state action) (token-machine state lookahead)))
(case action
((push) ; push the character onto the stack
(tokenize-impl (cdr input) state (cons lookahead stack) output))
((integer real complex) ; convert the stack into a number
(tokenize-impl input state '() (cons (string->number (list->string (reverse stack))) output)))
((symbol) ; convert the stack into a symbol
(let ((symbol (table-ref char-to-symbol (car stack))))
(tokenize-impl input state '() (cons symbol output))))
((skip)
(tokenize-impl (cdr input) state stack output))
(else
(error "cannot parse character" lookahead state stack)))))))
(define (token-machine state input)
; a mealy machine that takes a state and an input character
; and returns a new state and an action
(case state
((start)
(cond
((eqv? #\null input) (values 'start 'skip))
((eqv? #\. input) (values 'integer 'push))
((char-numeric? input) (values 'integer 'push))
((table-has-key? char-to-symbol input) (values 'symbol 'push))
((char-whitespace? input) (values 'start 'skip))
(else (values 'error 'error))))
((integer)
(cond
((char-numeric? input) (values 'integer 'push))
((eqv? #\. input) (values 'real 'push))
((eqv? #\i input) (values 'complex 'push))
(else (values 'start 'integer))))
((real)
(cond
((char-numeric? input) (values 'real 'push))
((eqv? #\i input) (values 'complex 'push))
(else (values 'start 'real))))
((complex)
(values 'start 'complex))
((symbol)
(values 'start 'symbol))
(else (values 'error 'error))))
(define char-to-symbol (table ()
((#\+) '+)
((#\-) '-)
((#\*) '*)
((#\/) '/)
((#\() 'lpar)
((#\)) 'rpar)
((#\^) 'expt)))))