1 -- ---------------------------------------------------------
6 CREATE FUNCTION reader.
tokenize(str
varchar) RETURNS varchar[] AS $$
8 re
varchar = E
'[[:space:] ,]*(~@|[\\[\\]{}()\'`~@]|"(?:[\\\\].|[^\\\\"])*"|;[^\n]*|[^\\s \\[\\]{}()\'"`~@,;]*)';
10 RETURN ARRAY(SELECT tok
FROM
11 (SELECT (regexp_matches(str
, re
, 'g'))[1] AS tok
) AS x
12 WHERE tok
<> '' AND tok
NOT LIKE ';%');
13 END; $$
LANGUAGE plpgsql
IMMUTABLE;
16 -- takes a tokens array and position
17 -- returns new position and value_id
18 CREATE FUNCTION reader.
read_atom(tokens
varchar[],
19 INOUT pos
integer, OUT result integer) AS $$
27 -- RAISE NOTICE 'read_atom: %', token;
28 IF token = 'nil' THEN -- nil
30 ELSIF
token = 'false' THEN -- false
32 ELSIF
token = 'true' THEN -- true
34 ELSIF
token ~
'^-?[0-9][0-9]*$' THEN -- integer
36 INSERT INTO types.
value (type_id
, val_int
)
37 VALUES (3, CAST(token AS integer))
38 RETURNING value_id
INTO result;
39 ELSIF
token ~
'^".*"' THEN -- string
41 str
:= substring(token FROM 2 FOR (char_length(token)-2));
42 str
:= replace(str
, '\"', '"');
43 str
:= replace(str
, '\n', E
'\n');
44 str
:= replace(str
, '\\', E
'\\');
45 result := types.
_stringv(str
);
46 ELSIF
token ~
'^:.*' THEN -- keyword
48 result := types.
_keywordv(substring(token FROM 2 FOR (char_length(token)-1)));
51 result := types.
_symbolv(token);
53 END; $$
LANGUAGE plpgsql
;
56 -- takes a tokens array, type (8, 9, 10), first and last characters
58 -- returns new position and value_id for a list (8), vector (9) or
60 CREATE FUNCTION reader.
read_seq(tokens
varchar[], first varchar, last varchar,
61 INOUT p
integer, OUT items
integer[]) AS $$
69 IF token <> first THEN
70 RAISE
EXCEPTION 'expected ''%''', first;
72 items
:= ARRAY[]::integer[];
74 IF p
> array_length(tokens
, 1) THEN
75 RAISE
EXCEPTION 'expected ''%''', last;
78 IF token = last THEN EXIT
; END IF;
79 SELECT * FROM reader.
read_form(tokens
, p
) INTO p
, item_id
;
80 items
:= array_append(items
, item_id
);
84 END; $$
LANGUAGE plpgsql
;
87 -- takes a tokens array and position
88 -- returns new position and value_id
89 CREATE FUNCTION reader.
read_form(tokens
varchar[],
90 INOUT pos
integer, OUT result integer) AS $$
96 token := tokens
[pos
]; -- peek
98 WHEN token = '''' THEN
101 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
102 result := types.
_list(ARRAY[types.
_symbolv('quote'), vid
]);
104 WHEN token = '`' THEN
107 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
108 result := types.
_list(ARRAY[types.
_symbolv('quasiquote'), vid
]);
110 WHEN token = '~' THEN
113 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
114 result := types.
_list(ARRAY[types.
_symbolv('unquote'), vid
]);
116 WHEN token = '~@' THEN
119 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
120 result := types.
_list(ARRAY[types.
_symbolv('splice-unquote'), vid
]);
122 WHEN token = '^' THEN
125 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, meta
;
126 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
127 result := types.
_list(ARRAY[types.
_symbolv('with-meta'), vid
, meta
]);
129 WHEN token = '@' THEN
132 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, vid
;
133 result := types.
_list(ARRAY[types.
_symbolv('deref'), vid
]);
137 WHEN token = ')' THEN
138 RAISE
EXCEPTION 'unexpected '')''';
139 WHEN token = '(' THEN
141 SELECT p
, types.
_list(items
)
142 FROM reader.
read_seq(tokens
, '(', ')', pos
) INTO pos
, result;
146 WHEN token = ']' THEN
147 RAISE
EXCEPTION 'unexpected '']''';
148 WHEN token = '[' THEN
150 SELECT p
, types.
_vector(items
)
151 FROM reader.
read_seq(tokens
, '[', ']', pos
) INTO pos
, result;
155 WHEN token = '}' THEN
156 RAISE
EXCEPTION 'unexpected ''}''';
157 WHEN token = '{' THEN
159 SELECT p
, types.
_hash_map(items
)
160 FROM reader.
read_seq(tokens
, '{', '}', pos
) INTO pos
, result;
165 SELECT * FROM reader.
read_atom(tokens
, pos
) INTO pos
, result;
167 END; $$
LANGUAGE plpgsql
;
171 -- returns a new value_id
172 CREATE FUNCTION reader.
read_str(str
varchar) RETURNS integer AS $$
178 tokens
:= reader.
tokenize(str
);
179 -- RAISE NOTICE 'read_str first: %', tokens[1];
181 SELECT * FROM reader.
read_form(tokens
, pos
) INTO pos
, ast
;
182 -- RAISE NOTICE 'pos after read_atom: %', pos;
184 END; $$
LANGUAGE plpgsql
;