-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathjson.lex
79 lines (68 loc) · 2.22 KB
/
json.lex
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
(* json.lex
*
* COPYRIGHT (c) 2008 The Fellowship of SML/NJ (http://www.smlnj.org)
* All rights reserved.
*
* Lexer for JSON files.
*
* TODO:
* EOF rules for strings
* newlines in strings
* error messages for unknown characters
*)
%name JSONLexer;
%defs (
structure T = JSONTokens
type lex_result = T.token
fun eof () = T.EOF
fun int s = T.INT(valOf(IntInf.fromString s))
fun float s = T.FLOAT(valOf(LargeReal.fromString s))
(* support for incremental construction of strings *)
val sbuf : string list ref = ref []
fun addStr s = sbuf := s :: !sbuf
fun addUChr lit = let
(* trim the "\u" prefix *)
val digits = Substring.triml 2 (Substring.full lit)
val SOME(w, _) = Word.scan StringCvt.HEX Substring.getc digits
in
addStr(UTF8.encode w)
end
fun finishString () = (T.STRING(String.concat(List.rev(!sbuf))) before sbuf := [])
);
%let digit1_9 = [1-9];
%let digit = [0-9];
%let digits = {digit}+;
%let int = "-"?({digit} | {digit1_9}{digits}+);
%let frac = "."{digits};
%let exp = [eE][+-]?{digits};
%let xdigit = {digit}|[a-fA-F];
%states S;
<INITIAL>[\ \t\n\r]+ => ( skip() );
<INITIAL>"{" => ( T.LCB );
<INITIAL>"}" => ( T.RCB );
<INITIAL>"[" => ( T.LB );
<INITIAL>"]" => ( T.RB );
<INITIAL>"," => ( T.COMMA );
<INITIAL>":" => ( T.COLON );
<INITIAL>"null" => ( T.KW_null );
<INITIAL>"true" => ( T.KW_true );
<INITIAL>"false" => ( T.KW_false );
<INITIAL>{int} => ( T.INT(valOf(IntInf.fromString yytext)) );
<INITIAL>{int}{frac} => ( float yytext );
<INITIAL>{int}{exp} => ( float yytext );
<INITIAL>{int}{frac}{exp} => ( float yytext );
<INITIAL>"\"" => ( YYBEGIN S; continue() );
<S>"\\\\" => ( addStr "\\"; continue() );
<S>"\\\"" => ( addStr "\""; continue() );
<S>"\\/" => ( addStr "/"; continue() );
<S>"\\b" => ( addStr "\b"; continue() );
<S>"\\f" => ( addStr "\f"; continue() );
<S>"\\n" => ( addStr "\n"; continue() );
<S>"\\r" => ( addStr "\r"; continue() );
<S>"\\t" => ( addStr "\t"; continue() );
<S>"\\u"{xdigit}{4} => ( addUChr yytext; continue() );
<S>[^\\"]+ => ( addStr yytext; continue() );
<S>"\"" => ( YYBEGIN INITIAL; finishString() );
<INITIAL>"/*"(~(.*"*/".*))"*/" => ( skip() );
(* FIXME: add some error reporting *)
<INITIAL>. => ( skip() );