35
36:- module(json_grammar,
37 [ json_token//1
38 ]). 39:- use_module(library(dcg/basics)). 40:- use_module(library(pure_input)). 41:- set_prolog_flag(double_quotes, codes).
59json_token(Type) -->
60 token(Type).
69token(comment) --> comment, !.
70token(string) --> string_literal, !.
71token(number) --> numeric_literal, !.
72token(identifier(Id)) --> identifier_name(Id), !.
73token(regex) --> regex_literal, !.
74token(ws) --> blank, !, blanks.
75token(punct(Char)) --> [Code], { char_code(Char, Code) }.
79comment -->
80 "/*",
81 !,
82 ( string(_), "*/"
83 -> []
84 ; syntax_error(eof_in_comment)
85 ).
86comment -->
87 "//",
88 !,
89 ( string(_), eol
90 -> []
91 ; string(_), eof
92 -> []
93 ).
100string_literal -->
101 "\"",
102 !,
103 ( q_codes, "\""
104 -> []
105 ; syntax_error(eof_in_string)
106 ).
107string_literal -->
108 "\'",
109 !,
110 ( q_codes, "\'"
111 -> []
112 ; syntax_error(eof_in_string)
113 ).
120numeric_literal -->
121 ( decimal_literal
122 -> []
123 ; hex_integer
124 ),
125 ( ( decimal_digit
126 ; js_id_start(_)
127 )
128 -> syntax_error(js(illegal_number))
129 ; []
130 ).
131
132decimal_literal -->
133 decimal_integer, ".", opt_decimal_digits, opt_exponent.
134decimal_literal -->
135 ".", decimal_digits, opt_exponent.
136decimal_literal -->
137 decimal_integer,
138 opt_exponent.
139
140decimal_integer -->
141 "0",
142 !.
143decimal_integer -->
144 non_zero_digit, opt_decimal_digits.
145
146decimal_digits -->
147 decimal_digit,
148 !,
149 opt_decimal_digits.
150
151opt_decimal_digits -->
152 decimal_digit,
153 !,
154 opt_decimal_digits.
155opt_decimal_digits -->
156 [].
157
158decimal_digit --> [C], { code_type(C, digit) }.
159non_zero_digit --> [C], { code_type(C, digit), C \== 0'0 }.
160
161opt_exponent -->
162 exponent,
163 !.
164opt_exponent -->
165 [].
166
167exponent -->
168 exponent_indictor,
169 signed_integer.
170
171exponent_indictor --> "e", !.
172exponent_indictor --> "E".
173
174signed_integer --> "+", !, decimal_digits.
175signed_integer --> "-", !, decimal_digits.
176signed_integer --> decimal_digits.
177
178hex_integer --> "0", x, hex_digit, hex_digits.
179
180x --> "x".
181x --> "X".
188regex_literal -->
189 "/", regex_body, "/", !, regex_flags.
190
191regex_body -->
192 regex_first_char,
193 regex_chars.
194
195regex_chars --> regex_char, !, regex_chars.
196regex_chars --> [].
197
198regex_first_char -->
199 regex_backslash_sequence.
200regex_first_char -->
201 regex_non_terminator(C),
202 !,
203 { \+ memberchk(C, "*\\/[") }.
204regex_first_char -->
205 regex_class.
206
207regex_char -->
208 regex_backslash_sequence.
209regex_char -->
210 regex_non_terminator(C),
211 !,
212 { \+ memberchk(C, "\\/[") }.
213regex_char -->
214 regex_class.
215
216regex_backslash_sequence -->
217 "\\", !, regex_non_terminator(_).
218
219regex_class -->
220 "[", regex_class_chars, "]".
221
222regex_class_chars --> regex_class_char, !, regex_class_chars.
223regex_class_chars --> "".
224
225regex_class_char -->
226 regex_non_terminator(C),
227 !,
228 { \+ memberchk(C, "]\\") }.
229
230regex_non_terminator(_) -->
231 eol, !, {fail}.
232regex_non_terminator(C) -->
233 source_char(C).
234
235regex_flags -->
236 js_id_conts(_).
237
238source_char(C) -->
239 [C].
246q_codes --> [] ; q_code, q_codes.
247
248q_code --> "\\", !, char_esc.
249q_code --> eol, !, {fail}.
250q_code --> [_].
251
252char_esc --> single_escape_char, !.
253char_esc --> "x", !, hex_digit, hex_digit.
254char_esc --> "u", !, hex_digit, hex_digit, hex_digit, hex_digit.
255char_esc --> eol, !.
256
257hex_digits --> hex_digit, !, hex_digits.
258hex_digits --> [].
259
260hex_digit --> [C], {code_type(C, xdigit(_))}.
261
262single_escape_char --> "'".
263single_escape_char --> "\"".
264single_escape_char --> "\\".
265single_escape_char --> "b".
266single_escape_char --> "f".
267single_escape_char --> "n".
268single_escape_char --> "r".
269single_escape_char --> "t".
270single_escape_char --> "v".
271
272eof -->
273 \+ [_].
274
275
278
279identifier_name(Id) -->
280 js_id_start(C0),
281 !,
282 js_id_conts(Rest),
283 { atom_codes(Id, [C0|Rest]),
284 ( keyword(Id)
285 -> fail, syntax_error(reserved(Id))
286 ; true
287 )
288 }.
289
290
291js_id_start(C) --> [C], {js_id_start(C)}.
292
293js_id_start(C) :- code_type(C, prolog_var_start), !.
294js_id_start(C) :- code_type(C, prolog_atom_start), !.
295js_id_start(0'$).
296
297js_id_conts([H|T]) --> js_id_cont(H), !, js_id_conts(T).
298js_id_conts([]) --> [].
299
300js_id_cont(C) --> [C], {js_id_cont(C)}.
301
302js_id_cont(C) :- code_type(C, prolog_identifier_continue), !.
303js_id_cont(0'$) :- !.
304
305
306keyword(break). 307keyword(do).
308keyword(instanceof).
309keyword(typeof).
310keyword(case).
311keyword(else).
312keyword(new).
313keyword(var).
314keyword(catch).
315keyword(finally).
316keyword(return).
317keyword(void).
318keyword(continue).
319keyword(for).
320keyword(switch).
321keyword(while).
322keyword(debugger).
323keyword(function).
324keyword(this).
325keyword(with).
326keyword(default).
327keyword(if).
328keyword(throw).
329keyword(delete).
330keyword(in).
331keyword(try).
332
333keyword(class). 334keyword(enum).
335keyword(extends).
336keyword(super).
337keyword(const).
338keyword(export).
339keyword(import).
340
341keyword(implements). 342keyword(let).
343keyword(private).
344keyword(public).
345keyword(yield).
346keyword(interface).
347keyword(package).
348keyword(protected).
349keyword(static)
JavaScript grammar
This file provides a tokenizer for JavaScript (EcmaScript). This code supports the quasi quotation syntax
javascript, defined in library(http/js_write).