-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlexer.sml
129 lines (110 loc) · 3.66 KB
/
lexer.sml
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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
structure LexerError = struct
exception Illegal of char option
exception IllegalBackSlash of string
end
structure Num : sig
val parse : char list -> int
end = struct
val ASCII_DIGIT_START = 48
fun parse_digit_in_char c = Char.ord c - ASCII_DIGIT_START
fun parse xs =
let
fun f (c, acc) = parse_digit_in_char c + 10 * acc
in
List.foldl f 0 xs
end
end
structure Lexer = MakeLexer (struct
structure Streamable = StreamStreamable
structure Arg = struct
type symbol = char
val ord = Char.ord
datatype t = datatype Token.token
type t = t Streamable.t
type self = { lex : symbol Streamable.t -> t }
type info = {
match : symbol list,
len : int,
start : symbol Streamable.t,
follow : symbol Streamable.t,
self : self
}
open LexerError
fun eager_follow ({self, follow, ...} : info) tok =
let open Stream in
eager (Cons(tok, #lex self follow))
end
fun stream_head s =
case Stream.front s of
Stream.Nil => NONE
| Stream.Cons(x, _) => SOME(x)
fun illegal ({follow, ...} : info) = raise Illegal(stream_head follow)
fun eof _ = Stream.fromList []
fun asterisk info = eager_follow info STAR
fun colon info = eager_follow info COLON
fun comma info = eager_follow info COMMA
fun dot info = eager_follow info DOT
fun slash info = eager_follow info SLASH
fun equal info = eager_follow info EQUAL
fun rarrow info = eager_follow info RARROW
fun larrow info = eager_follow info LARROW
fun seal info = eager_follow info SEAL
fun lparen info = eager_follow info LPAREN
fun rparen info = eager_follow info RPAREN
fun lbrack info = eager_follow info LBRACK
fun rbrack info = eager_follow info RBRACK
fun lwhiteparen info = eager_follow info LWHITEPAREN
fun rwhiteparen info = eager_follow info RWHITEPAREN
fun lwhiteangle info = eager_follow info LWHITEANGLE
fun rwhiteangle info = eager_follow info RWHITEANGLE
fun one info = eager_follow info ONE
fun number ({match, self, follow, ...} : info) =
Stream.lazy (fn () => Stream.Cons(NUMBER(Num.parse match), #lex self follow))
fun whitespace ({self, follow, ...} : info) = #lex self follow
fun quote_ident ({match, self, follow, ...} : info) =
Stream.lazy (fn () => Stream.Cons(QUOTE_IDENT(String.implode (List.tl match)), #lex self follow))
fun backslash_ident ({match, self, follow, ...} : info) =
let val f =
fn "Pi" => CAP_PI
| "Sigma" => CAP_SIGMA
| s => raise IllegalBackSlash(s)
in
Stream.lazy (fn () => Stream.Cons(f (String.implode (List.tl match)), #lex self follow))
end
fun upper_ident ({match, self, follow, ...} : info) =
let val f =
fn "Type" => CAP_TYPE
| "Ext" => CAP_EXT
| "S" => S
| s => UPPER_IDENT s
in
Stream.lazy (fn () => Stream.Cons(f (String.implode match), #lex self follow))
end
fun lower_ident ({match, self, follow, ...} : info) =
let val f =
fn "fun" => FUN
| "fst" => FST
| "snd" => SND
| "forall" => FORALL
| "exist" => EXIST
| "poly" => POLY
| "pack" => PACK
| "unpack" => UNPACK
| "as" => AS
| "in" => IN
| "fix" => FIX
| "let" => LET
| "circ" => CIRC
| "ret" => RET
| "bind" => BIND
| "bool" => BOOL
| "int" => INT
| "if" => IF
| "then" => THEN
| "else" => ELSE
| s => LOWER_IDENT s
in
Stream.lazy (fn () => Stream.Cons(f (String.implode match), #lex self follow))
end
end
end)