forked from standardml/cmlib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lex-engine.sml
executable file
·156 lines (136 loc) · 5.34 KB
/
lex-engine.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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
functor LexEngineFun (structure Streamable : STREAMABLE
type symbol
val ord : symbol -> int)
:> LEX_ENGINE
where type 'a Streamable.t = 'a Streamable.t
and type symbol = symbol
=
struct
structure Streamable = Streamable
type symbol = symbol
(* Next state function for 7-bit symbols, with 1-byte results. *)
fun next7x1 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 128 * state + symbol
in
Char.ord (String.sub (table, i))
end
fun next8x1 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 256 * state + symbol
in
Char.ord (String.sub (table, i))
end
fun next9x1 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 512 * state + symbol
in
Char.ord (String.sub (table, i))
end
fun next10x1 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 1024 * state + symbol
in
Char.ord (String.sub (table, i))
end
fun next7x2 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 256 * state + 2 * symbol
in
Char.ord (String.sub (table, i)) * 256 +
Char.ord (String.sub (table, i+1))
end
fun next8x2 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 512 * state + 2 * symbol
in
Char.ord (String.sub (table, i)) * 256 +
Char.ord (String.sub (table, i+1))
end
fun next9x2 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 1024 * state + 2 * symbol
in
Char.ord (String.sub (table, i)) * 256 +
Char.ord (String.sub (table, i+1))
end
fun next10x2 symbolLimit table state symbol =
if symbol >= symbolLimit then
0
else
let
val i = 2048 * state + 2 * symbol
in
Char.ord (String.sub (table, i)) * 256 +
Char.ord (String.sub (table, i+1))
end
(* Next state function for end-of-stream, with 1-byte results. *)
fun next0x1 table state =
Char.ord (String.sub (table, state))
fun next0x2 table state =
let
val i = 2 * state
in
Char.ord (String.sub (table, i)) * 256 +
Char.ord (String.sub (table, i+1))
end
type ('a, 'b) action = { match : symbol list,
len : int,
start : symbol Streamable.t,
follow : symbol Streamable.t,
self : 'b } -> 'a
type ('a, 'b) table =
int * int * int * ('a, 'b) action vector * (int -> int -> int) * (int -> int)
fun lex self (initial, lastAcceptSink, lastAccept, acceptTable, next, nextEos) s =
let
fun loop candidate candLen candChars candStream state len chars s =
if state = 0 then
(candidate, candLen, candChars, candStream)
else if state <= lastAccept then
if state <= lastAcceptSink then
(state, len, chars, s)
else
(case Streamable.front s of
Streamable.Nil =>
loop state len chars s (nextEos state) len chars s
| Streamable.Cons (ch, s') =>
loop state len chars s (next state (ord ch)) (len+1) (ch :: chars) s')
else
(case Streamable.front s of
Streamable.Nil =>
loop candidate candLen candChars candStream (nextEos state) len chars s
| Streamable.Cons (ch, s') =>
loop candidate candLen candChars candStream (next state (ord ch)) (len+1) (ch :: chars) s')
val (acceptingState, len, chars, s') =
(* By construction, initial is an accepting state. *)
loop initial 0 [] s initial 0 [] s
val f = Vector.sub (acceptTable, acceptingState-1)
in
f { match = rev chars,
len = len,
start = s,
follow = s',
self = self }
end
end