pygments.rb 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +6 -1
- data/lexers +0 -0
- data/lib/pygments/version.rb +1 -1
- data/vendor/pygments-main/AUTHORS +15 -0
- data/vendor/pygments-main/CHANGES +28 -1
- data/vendor/pygments-main/LICENSE +1 -1
- data/vendor/pygments-main/external/lasso-builtins-generator-9.lasso +121 -0
- data/vendor/pygments-main/pygments/cmdline.py +1 -1
- data/vendor/pygments-main/pygments/filters/__init__.py +0 -1
- data/vendor/pygments-main/pygments/formatters/_mapping.py +2 -2
- data/vendor/pygments-main/pygments/formatters/img.py +1 -1
- data/vendor/pygments-main/pygments/formatters/latex.py +8 -8
- data/vendor/pygments-main/pygments/formatters/other.py +0 -2
- data/vendor/pygments-main/pygments/lexers/_lassobuiltins.py +5413 -0
- data/vendor/pygments-main/pygments/lexers/_mapping.py +36 -11
- data/vendor/pygments-main/pygments/lexers/_openedgebuiltins.py +551 -0
- data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +0 -1
- data/vendor/pygments-main/pygments/lexers/_robotframeworklexer.py +546 -0
- data/vendor/pygments-main/pygments/lexers/_sourcemodbuiltins.py +1072 -0
- data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +174 -0
- data/vendor/pygments-main/pygments/lexers/_vimbuiltins.py +13 -3
- data/vendor/pygments-main/pygments/lexers/agile.py +145 -33
- data/vendor/pygments-main/pygments/lexers/asm.py +2 -2
- data/vendor/pygments-main/pygments/lexers/compiled.py +328 -36
- data/vendor/pygments-main/pygments/lexers/dalvik.py +104 -0
- data/vendor/pygments-main/pygments/lexers/dotnet.py +8 -14
- data/vendor/pygments-main/pygments/lexers/functional.py +773 -8
- data/vendor/pygments-main/pygments/lexers/jvm.py +184 -36
- data/vendor/pygments-main/pygments/lexers/math.py +349 -23
- data/vendor/pygments-main/pygments/lexers/other.py +315 -492
- data/vendor/pygments-main/pygments/lexers/parsers.py +83 -1
- data/vendor/pygments-main/pygments/lexers/shell.py +4 -1
- data/vendor/pygments-main/pygments/lexers/templates.py +112 -2
- data/vendor/pygments-main/pygments/lexers/text.py +52 -3
- data/vendor/pygments-main/pygments/lexers/web.py +382 -36
- data/vendor/pygments-main/pygments/unistring.py +35 -25
- data/vendor/pygments-main/pygments/util.py +45 -0
- data/vendor/pygments-main/tests/examplefiles/Config.in.cache +1973 -0
- data/vendor/pygments-main/tests/examplefiles/example.Rd +78 -0
- data/vendor/pygments-main/tests/examplefiles/example.bug +54 -0
- data/vendor/pygments-main/tests/examplefiles/example.ceylon +33 -0
- data/vendor/pygments-main/tests/examplefiles/example.jag +48 -0
- data/vendor/pygments-main/tests/examplefiles/example.monkey +152 -0
- data/vendor/pygments-main/tests/examplefiles/example.msc +43 -0
- data/vendor/pygments-main/tests/examplefiles/example.reg +19 -0
- data/vendor/pygments-main/tests/examplefiles/example.rkt +95 -0
- data/vendor/pygments-main/tests/examplefiles/example.rpf +4 -0
- data/vendor/pygments-main/tests/examplefiles/example.stan +97 -0
- data/vendor/pygments-main/tests/examplefiles/example.xtend +34 -0
- data/vendor/pygments-main/tests/examplefiles/example2.msc +79 -0
- data/vendor/pygments-main/tests/examplefiles/garcia-wachs.kk +123 -0
- data/vendor/pygments-main/tests/examplefiles/hello.smali +40 -0
- data/vendor/pygments-main/tests/examplefiles/hello.sp +9 -0
- data/vendor/pygments-main/tests/examplefiles/http_request_example +2 -1
- data/vendor/pygments-main/tests/examplefiles/http_response_example +4 -2
- data/vendor/pygments-main/tests/examplefiles/inet_pton6.dg +71 -0
- data/vendor/pygments-main/tests/examplefiles/json.lasso +301 -0
- data/vendor/pygments-main/tests/examplefiles/json.lasso9 +213 -0
- data/vendor/pygments-main/tests/examplefiles/livescript-demo.ls +41 -0
- data/vendor/pygments-main/tests/examplefiles/matlab_sample +5 -2
- data/vendor/pygments-main/tests/examplefiles/metagrammar.treetop +455 -0
- data/vendor/pygments-main/tests/examplefiles/pytb_test3.pytb +4 -0
- data/vendor/pygments-main/tests/examplefiles/robotframework.txt +39 -0
- data/vendor/pygments-main/tests/examplefiles/rust_example.rs +743 -0
- data/vendor/pygments-main/tests/examplefiles/test.R +149 -115
- data/vendor/pygments-main/tests/examplefiles/test.cu +36 -0
- data/vendor/pygments-main/tests/test_basic_api.py +1 -1
- data/vendor/pygments-main/tests/test_util.py +18 -0
- metadata +34 -3
- data/vendor/pygments-main/REVISION +0 -1
@@ -0,0 +1,39 @@
|
|
1
|
+
*** Settings ***
|
2
|
+
Documentation Simple example demonstrating syntax highlighting.
|
3
|
+
Library ExampleLibrary
|
4
|
+
Test Setup Keyword argument argument with ${VARIABLE}
|
5
|
+
|
6
|
+
*** Variables ***
|
7
|
+
${VARIABLE} Variable value
|
8
|
+
@{LIST} List variable here
|
9
|
+
|
10
|
+
*** Test Cases ***
|
11
|
+
Keyword-driven example
|
12
|
+
Initialize System
|
13
|
+
Do Something
|
14
|
+
Result Should Be 42
|
15
|
+
[Teardown] Cleanup System
|
16
|
+
|
17
|
+
Data-driven example
|
18
|
+
[Template] Keyword
|
19
|
+
argument1 argument2
|
20
|
+
argument ${VARIABLE}
|
21
|
+
@{LIST}
|
22
|
+
|
23
|
+
Gherkin
|
24
|
+
Given system is initialized
|
25
|
+
When something is done
|
26
|
+
Then result should be "42"
|
27
|
+
|
28
|
+
| Pipes |
|
29
|
+
| | [Documentation] | Also pipe separated format is supported. |
|
30
|
+
| | Log | As this example demonstrates. |
|
31
|
+
|
32
|
+
*** Keywords ***
|
33
|
+
Result Should Be
|
34
|
+
[Arguments] ${expected}
|
35
|
+
${actual} = Get Value
|
36
|
+
Should be Equal ${actual} ${expected}
|
37
|
+
|
38
|
+
Then result should be "${expected}"
|
39
|
+
Result Should Be ${expected}
|
@@ -0,0 +1,743 @@
|
|
1
|
+
|
2
|
+
#[doc = "json serialization"];
|
3
|
+
|
4
|
+
import result::{result, ok, err};
|
5
|
+
import io;
|
6
|
+
import io::{reader_util, writer_util};
|
7
|
+
import map;
|
8
|
+
import map::hashmap;
|
9
|
+
|
10
|
+
export json;
|
11
|
+
export error;
|
12
|
+
export to_writer;
|
13
|
+
export to_str;
|
14
|
+
export from_reader;
|
15
|
+
export from_str;
|
16
|
+
export eq;
|
17
|
+
|
18
|
+
export num;
|
19
|
+
export string;
|
20
|
+
export boolean;
|
21
|
+
export list;
|
22
|
+
export dict;
|
23
|
+
export null;
|
24
|
+
|
25
|
+
#[doc = "Represents a json value"]
|
26
|
+
enum json {
|
27
|
+
num(float),
|
28
|
+
string(str),
|
29
|
+
boolean(bool),
|
30
|
+
list([json]),
|
31
|
+
dict(map::hashmap<str,json>),
|
32
|
+
null,
|
33
|
+
}
|
34
|
+
|
35
|
+
type error = {
|
36
|
+
line: uint,
|
37
|
+
col: uint,
|
38
|
+
msg: str,
|
39
|
+
};
|
40
|
+
|
41
|
+
#[doc = "Serializes a json value into a io::writer"]
|
42
|
+
fn to_writer(wr: io::writer, j: json) {
|
43
|
+
alt j {
|
44
|
+
num(n) { wr.write_str(float::to_str(n, 6u)); }
|
45
|
+
string(s) {
|
46
|
+
wr.write_char('"');
|
47
|
+
let mut escaped = "";
|
48
|
+
str::chars_iter(s) { |c|
|
49
|
+
alt c {
|
50
|
+
'"' { escaped += "\\\""; }
|
51
|
+
'\\' { escaped += "\\\\"; }
|
52
|
+
'\x08' { escaped += "\\b"; }
|
53
|
+
'\x0c' { escaped += "\\f"; }
|
54
|
+
'\n' { escaped += "\\n"; }
|
55
|
+
'\r' { escaped += "\\r"; }
|
56
|
+
'\t' { escaped += "\\t"; }
|
57
|
+
_ { escaped += str::from_char(c); }
|
58
|
+
}
|
59
|
+
};
|
60
|
+
wr.write_str(escaped);
|
61
|
+
wr.write_char('"');
|
62
|
+
}
|
63
|
+
boolean(b) {
|
64
|
+
wr.write_str(if b { "true" } else { "false" });
|
65
|
+
}
|
66
|
+
list(v) {
|
67
|
+
wr.write_char('[');
|
68
|
+
let mut first = true;
|
69
|
+
vec::iter(v) { |item|
|
70
|
+
if !first {
|
71
|
+
wr.write_str(", ");
|
72
|
+
}
|
73
|
+
first = false;
|
74
|
+
to_writer(wr, item);
|
75
|
+
};
|
76
|
+
wr.write_char(']');
|
77
|
+
}
|
78
|
+
dict(d) {
|
79
|
+
if d.size() == 0u {
|
80
|
+
wr.write_str("{}");
|
81
|
+
ret;
|
82
|
+
}
|
83
|
+
|
84
|
+
wr.write_str("{ ");
|
85
|
+
let mut first = true;
|
86
|
+
d.items { |key, value|
|
87
|
+
if !first {
|
88
|
+
wr.write_str(", ");
|
89
|
+
}
|
90
|
+
first = false;
|
91
|
+
to_writer(wr, string(key));
|
92
|
+
wr.write_str(": ");
|
93
|
+
to_writer(wr, value);
|
94
|
+
};
|
95
|
+
wr.write_str(" }");
|
96
|
+
}
|
97
|
+
null {
|
98
|
+
wr.write_str("null");
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
#[doc = "Serializes a json value into a string"]
|
104
|
+
fn to_str(j: json) -> str {
|
105
|
+
io::with_str_writer { |wr| to_writer(wr, j) }
|
106
|
+
}
|
107
|
+
|
108
|
+
type parser = {
|
109
|
+
rdr: io::reader,
|
110
|
+
mut ch: char,
|
111
|
+
mut line: uint,
|
112
|
+
mut col: uint,
|
113
|
+
};
|
114
|
+
|
115
|
+
impl parser for parser {
|
116
|
+
fn eof() -> bool { self.ch == -1 as char }
|
117
|
+
|
118
|
+
fn bump() {
|
119
|
+
self.ch = self.rdr.read_char();
|
120
|
+
|
121
|
+
if self.ch == '\n' {
|
122
|
+
self.line += 1u;
|
123
|
+
self.col = 1u;
|
124
|
+
} else {
|
125
|
+
self.col += 1u;
|
126
|
+
}
|
127
|
+
}
|
128
|
+
|
129
|
+
fn next_char() -> char {
|
130
|
+
self.bump();
|
131
|
+
self.ch
|
132
|
+
}
|
133
|
+
|
134
|
+
fn error<T>(msg: str) -> result<T, error> {
|
135
|
+
err({ line: self.line, col: self.col, msg: msg })
|
136
|
+
}
|
137
|
+
|
138
|
+
fn parse() -> result<json, error> {
|
139
|
+
alt self.parse_value() {
|
140
|
+
ok(value) {
|
141
|
+
// Skip trailing whitespaces.
|
142
|
+
self.parse_whitespace();
|
143
|
+
// Make sure there is no trailing characters.
|
144
|
+
if self.eof() {
|
145
|
+
ok(value)
|
146
|
+
} else {
|
147
|
+
self.error("trailing characters")
|
148
|
+
}
|
149
|
+
}
|
150
|
+
e { e }
|
151
|
+
}
|
152
|
+
}
|
153
|
+
|
154
|
+
fn parse_value() -> result<json, error> {
|
155
|
+
self.parse_whitespace();
|
156
|
+
|
157
|
+
if self.eof() { ret self.error("EOF while parsing value"); }
|
158
|
+
|
159
|
+
alt self.ch {
|
160
|
+
'n' { self.parse_ident("ull", null) }
|
161
|
+
't' { self.parse_ident("rue", boolean(true)) }
|
162
|
+
'f' { self.parse_ident("alse", boolean(false)) }
|
163
|
+
'0' to '9' | '-' { self.parse_number() }
|
164
|
+
'"' {
|
165
|
+
alt self.parse_str() {
|
166
|
+
ok(s) { ok(string(s)) }
|
167
|
+
err(e) { err(e) }
|
168
|
+
}
|
169
|
+
}
|
170
|
+
'[' { self.parse_list() }
|
171
|
+
'{' { self.parse_object() }
|
172
|
+
_ { self.error("invalid syntax") }
|
173
|
+
}
|
174
|
+
}
|
175
|
+
|
176
|
+
fn parse_whitespace() {
|
177
|
+
while char::is_whitespace(self.ch) { self.bump(); }
|
178
|
+
}
|
179
|
+
|
180
|
+
fn parse_ident(ident: str, value: json) -> result<json, error> {
|
181
|
+
if str::all(ident, { |c| c == self.next_char() }) {
|
182
|
+
self.bump();
|
183
|
+
ok(value)
|
184
|
+
} else {
|
185
|
+
self.error("invalid syntax")
|
186
|
+
}
|
187
|
+
}
|
188
|
+
|
189
|
+
fn parse_number() -> result<json, error> {
|
190
|
+
let mut neg = 1f;
|
191
|
+
|
192
|
+
if self.ch == '-' {
|
193
|
+
self.bump();
|
194
|
+
neg = -1f;
|
195
|
+
}
|
196
|
+
|
197
|
+
let mut res = alt self.parse_integer() {
|
198
|
+
ok(res) { res }
|
199
|
+
err(e) { ret err(e); }
|
200
|
+
};
|
201
|
+
|
202
|
+
if self.ch == '.' {
|
203
|
+
alt self.parse_decimal(res) {
|
204
|
+
ok(r) { res = r; }
|
205
|
+
err(e) { ret err(e); }
|
206
|
+
}
|
207
|
+
}
|
208
|
+
|
209
|
+
if self.ch == 'e' || self.ch == 'E' {
|
210
|
+
alt self.parse_exponent(res) {
|
211
|
+
ok(r) { res = r; }
|
212
|
+
err(e) { ret err(e); }
|
213
|
+
}
|
214
|
+
}
|
215
|
+
|
216
|
+
ok(num(neg * res))
|
217
|
+
}
|
218
|
+
|
219
|
+
fn parse_integer() -> result<float, error> {
|
220
|
+
let mut res = 0f;
|
221
|
+
|
222
|
+
alt self.ch {
|
223
|
+
'0' {
|
224
|
+
self.bump();
|
225
|
+
|
226
|
+
// There can be only one leading '0'.
|
227
|
+
alt self.ch {
|
228
|
+
'0' to '9' { ret self.error("invalid number"); }
|
229
|
+
_ {}
|
230
|
+
}
|
231
|
+
}
|
232
|
+
'1' to '9' {
|
233
|
+
while !self.eof() {
|
234
|
+
alt self.ch {
|
235
|
+
'0' to '9' {
|
236
|
+
res *= 10f;
|
237
|
+
res += ((self.ch as int) - ('0' as int)) as float;
|
238
|
+
|
239
|
+
self.bump();
|
240
|
+
}
|
241
|
+
_ { break; }
|
242
|
+
}
|
243
|
+
}
|
244
|
+
}
|
245
|
+
_ { ret self.error("invalid number"); }
|
246
|
+
}
|
247
|
+
|
248
|
+
ok(res)
|
249
|
+
}
|
250
|
+
|
251
|
+
fn parse_decimal(res: float) -> result<float, error> {
|
252
|
+
self.bump();
|
253
|
+
|
254
|
+
// Make sure a digit follows the decimal place.
|
255
|
+
alt self.ch {
|
256
|
+
'0' to '9' {}
|
257
|
+
_ { ret self.error("invalid number"); }
|
258
|
+
}
|
259
|
+
|
260
|
+
let mut res = res;
|
261
|
+
let mut dec = 1f;
|
262
|
+
while !self.eof() {
|
263
|
+
alt self.ch {
|
264
|
+
'0' to '9' {
|
265
|
+
dec /= 10f;
|
266
|
+
res += (((self.ch as int) - ('0' as int)) as float) * dec;
|
267
|
+
|
268
|
+
self.bump();
|
269
|
+
}
|
270
|
+
_ { break; }
|
271
|
+
}
|
272
|
+
}
|
273
|
+
|
274
|
+
ok(res)
|
275
|
+
}
|
276
|
+
|
277
|
+
fn parse_exponent(res: float) -> result<float, error> {
|
278
|
+
self.bump();
|
279
|
+
|
280
|
+
let mut res = res;
|
281
|
+
let mut exp = 0u;
|
282
|
+
let mut neg_exp = false;
|
283
|
+
|
284
|
+
alt self.ch {
|
285
|
+
'+' { self.bump(); }
|
286
|
+
'-' { self.bump(); neg_exp = true; }
|
287
|
+
_ {}
|
288
|
+
}
|
289
|
+
|
290
|
+
// Make sure a digit follows the exponent place.
|
291
|
+
alt self.ch {
|
292
|
+
'0' to '9' {}
|
293
|
+
_ { ret self.error("invalid number"); }
|
294
|
+
}
|
295
|
+
|
296
|
+
while !self.eof() {
|
297
|
+
alt self.ch {
|
298
|
+
'0' to '9' {
|
299
|
+
exp *= 10u;
|
300
|
+
exp += (self.ch as uint) - ('0' as uint);
|
301
|
+
|
302
|
+
self.bump();
|
303
|
+
}
|
304
|
+
_ { break; }
|
305
|
+
}
|
306
|
+
}
|
307
|
+
|
308
|
+
let exp = float::pow_with_uint(10u, exp);
|
309
|
+
if neg_exp {
|
310
|
+
res /= exp;
|
311
|
+
} else {
|
312
|
+
res *= exp;
|
313
|
+
}
|
314
|
+
|
315
|
+
ok(res)
|
316
|
+
}
|
317
|
+
|
318
|
+
fn parse_str() -> result<str, error> {
|
319
|
+
let mut escape = false;
|
320
|
+
let mut res = "";
|
321
|
+
|
322
|
+
while !self.eof() {
|
323
|
+
self.bump();
|
324
|
+
|
325
|
+
if (escape) {
|
326
|
+
alt self.ch {
|
327
|
+
'"' { str::push_char(res, '"'); }
|
328
|
+
'\\' { str::push_char(res, '\\'); }
|
329
|
+
'/' { str::push_char(res, '/'); }
|
330
|
+
'b' { str::push_char(res, '\x08'); }
|
331
|
+
'f' { str::push_char(res, '\x0c'); }
|
332
|
+
'n' { str::push_char(res, '\n'); }
|
333
|
+
'r' { str::push_char(res, '\r'); }
|
334
|
+
't' { str::push_char(res, '\t'); }
|
335
|
+
'u' {
|
336
|
+
// Parse \u1234.
|
337
|
+
let mut i = 0u;
|
338
|
+
let mut n = 0u;
|
339
|
+
while i < 4u {
|
340
|
+
alt self.next_char() {
|
341
|
+
'0' to '9' {
|
342
|
+
n = n * 10u +
|
343
|
+
(self.ch as uint) - ('0' as uint);
|
344
|
+
}
|
345
|
+
_ { ret self.error("invalid \\u escape"); }
|
346
|
+
}
|
347
|
+
i += 1u;
|
348
|
+
}
|
349
|
+
|
350
|
+
// Error out if we didn't parse 4 digits.
|
351
|
+
if i != 4u {
|
352
|
+
ret self.error("invalid \\u escape");
|
353
|
+
}
|
354
|
+
|
355
|
+
str::push_char(res, n as char);
|
356
|
+
}
|
357
|
+
_ { ret self.error("invalid escape"); }
|
358
|
+
}
|
359
|
+
escape = false;
|
360
|
+
} else if self.ch == '\\' {
|
361
|
+
escape = true;
|
362
|
+
} else {
|
363
|
+
if self.ch == '"' {
|
364
|
+
self.bump();
|
365
|
+
ret ok(res);
|
366
|
+
}
|
367
|
+
str::push_char(res, self.ch);
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
371
|
+
self.error("EOF while parsing string")
|
372
|
+
}
|
373
|
+
|
374
|
+
fn parse_list() -> result<json, error> {
|
375
|
+
self.bump();
|
376
|
+
self.parse_whitespace();
|
377
|
+
|
378
|
+
let mut values = [];
|
379
|
+
|
380
|
+
if self.ch == ']' {
|
381
|
+
self.bump();
|
382
|
+
ret ok(list(values));
|
383
|
+
}
|
384
|
+
|
385
|
+
loop {
|
386
|
+
alt self.parse_value() {
|
387
|
+
ok(v) { vec::push(values, v); }
|
388
|
+
e { ret e; }
|
389
|
+
}
|
390
|
+
|
391
|
+
self.parse_whitespace();
|
392
|
+
if self.eof() {
|
393
|
+
ret self.error("EOF while parsing list");
|
394
|
+
}
|
395
|
+
|
396
|
+
alt self.ch {
|
397
|
+
',' { self.bump(); }
|
398
|
+
']' { self.bump(); ret ok(list(values)); }
|
399
|
+
_ { ret self.error("expecting ',' or ']'"); }
|
400
|
+
}
|
401
|
+
};
|
402
|
+
}
|
403
|
+
|
404
|
+
fn parse_object() -> result<json, error> {
|
405
|
+
self.bump();
|
406
|
+
self.parse_whitespace();
|
407
|
+
|
408
|
+
let values = map::str_hash();
|
409
|
+
|
410
|
+
if self.ch == '}' {
|
411
|
+
self.bump();
|
412
|
+
ret ok(dict(values));
|
413
|
+
}
|
414
|
+
|
415
|
+
while !self.eof() {
|
416
|
+
self.parse_whitespace();
|
417
|
+
|
418
|
+
if self.ch != '"' {
|
419
|
+
ret self.error("key must be a string");
|
420
|
+
}
|
421
|
+
|
422
|
+
let key = alt self.parse_str() {
|
423
|
+
ok(key) { key }
|
424
|
+
err(e) { ret err(e); }
|
425
|
+
};
|
426
|
+
|
427
|
+
self.parse_whitespace();
|
428
|
+
|
429
|
+
if self.ch != ':' {
|
430
|
+
if self.eof() { break; }
|
431
|
+
ret self.error("expecting ':'");
|
432
|
+
}
|
433
|
+
self.bump();
|
434
|
+
|
435
|
+
alt self.parse_value() {
|
436
|
+
ok(value) { values.insert(key, value); }
|
437
|
+
e { ret e; }
|
438
|
+
}
|
439
|
+
self.parse_whitespace();
|
440
|
+
|
441
|
+
alt self.ch {
|
442
|
+
',' { self.bump(); }
|
443
|
+
'}' { self.bump(); ret ok(dict(values)); }
|
444
|
+
_ {
|
445
|
+
if self.eof() { break; }
|
446
|
+
ret self.error("expecting ',' or '}'");
|
447
|
+
}
|
448
|
+
}
|
449
|
+
}
|
450
|
+
|
451
|
+
ret self.error("EOF while parsing object");
|
452
|
+
}
|
453
|
+
}
|
454
|
+
|
455
|
+
#[doc = "Deserializes a json value from an io::reader"]
|
456
|
+
fn from_reader(rdr: io::reader) -> result<json, error> {
|
457
|
+
let parser = {
|
458
|
+
rdr: rdr,
|
459
|
+
mut ch: rdr.read_char(),
|
460
|
+
mut line: 1u,
|
461
|
+
mut col: 1u,
|
462
|
+
};
|
463
|
+
|
464
|
+
parser.parse()
|
465
|
+
}
|
466
|
+
|
467
|
+
#[doc = "Deserializes a json value from a string"]
|
468
|
+
fn from_str(s: str) -> result<json, error> {
|
469
|
+
io::with_str_reader(s, from_reader)
|
470
|
+
}
|
471
|
+
|
472
|
+
#[doc = "Test if two json values are equal"]
|
473
|
+
fn eq(value0: json, value1: json) -> bool {
|
474
|
+
alt (value0, value1) {
|
475
|
+
(num(f0), num(f1)) { f0 == f1 }
|
476
|
+
(string(s0), string(s1)) { s0 == s1 }
|
477
|
+
(boolean(b0), boolean(b1)) { b0 == b1 }
|
478
|
+
(list(l0), list(l1)) { vec::all2(l0, l1, eq) }
|
479
|
+
(dict(d0), dict(d1)) {
|
480
|
+
if d0.size() == d1.size() {
|
481
|
+
let mut equal = true;
|
482
|
+
d0.items { |k, v0|
|
483
|
+
alt d1.find(k) {
|
484
|
+
some(v1) {
|
485
|
+
if !eq(v0, v1) { equal = false; } }
|
486
|
+
none { equal = false; }
|
487
|
+
}
|
488
|
+
};
|
489
|
+
equal
|
490
|
+
} else {
|
491
|
+
false
|
492
|
+
}
|
493
|
+
}
|
494
|
+
(null, null) { true }
|
495
|
+
_ { false }
|
496
|
+
}
|
497
|
+
}
|
498
|
+
|
499
|
+
#[cfg(test)]
|
500
|
+
mod tests {
|
501
|
+
fn mk_dict(items: [(str, json)]) -> json {
|
502
|
+
let d = map::str_hash();
|
503
|
+
|
504
|
+
vec::iter(items) { |item|
|
505
|
+
let (key, value) = item;
|
506
|
+
d.insert(key, value);
|
507
|
+
};
|
508
|
+
|
509
|
+
dict(d)
|
510
|
+
}
|
511
|
+
|
512
|
+
#[test]
|
513
|
+
fn test_write_null() {
|
514
|
+
assert to_str(null) == "null";
|
515
|
+
}
|
516
|
+
|
517
|
+
#[test]
|
518
|
+
fn test_write_num() {
|
519
|
+
assert to_str(num(3f)) == "3";
|
520
|
+
assert to_str(num(3.1f)) == "3.1";
|
521
|
+
assert to_str(num(-1.5f)) == "-1.5";
|
522
|
+
assert to_str(num(0.5f)) == "0.5";
|
523
|
+
}
|
524
|
+
|
525
|
+
#[test]
|
526
|
+
fn test_write_str() {
|
527
|
+
assert to_str(string("")) == "\"\"";
|
528
|
+
assert to_str(string("foo")) == "\"foo\"";
|
529
|
+
}
|
530
|
+
|
531
|
+
#[test]
|
532
|
+
fn test_write_bool() {
|
533
|
+
assert to_str(boolean(true)) == "true";
|
534
|
+
assert to_str(boolean(false)) == "false";
|
535
|
+
}
|
536
|
+
|
537
|
+
#[test]
|
538
|
+
fn test_write_list() {
|
539
|
+
assert to_str(list([])) == "[]";
|
540
|
+
assert to_str(list([boolean(true)])) == "[true]";
|
541
|
+
assert to_str(list([
|
542
|
+
boolean(false),
|
543
|
+
null,
|
544
|
+
list([string("foo\nbar"), num(3.5f)])
|
545
|
+
])) == "[false, null, [\"foo\\nbar\", 3.5]]";
|
546
|
+
}
|
547
|
+
|
548
|
+
#[test]
|
549
|
+
fn test_write_dict() {
|
550
|
+
assert to_str(mk_dict([])) == "{}";
|
551
|
+
assert to_str(mk_dict([("a", boolean(true))])) == "{ \"a\": true }";
|
552
|
+
assert to_str(mk_dict([
|
553
|
+
("a", boolean(true)),
|
554
|
+
("b", list([
|
555
|
+
mk_dict([("c", string("\x0c\r"))]),
|
556
|
+
mk_dict([("d", string(""))])
|
557
|
+
]))
|
558
|
+
])) ==
|
559
|
+
"{ " +
|
560
|
+
"\"a\": true, " +
|
561
|
+
"\"b\": [" +
|
562
|
+
"{ \"c\": \"\\f\\r\" }, " +
|
563
|
+
"{ \"d\": \"\" }" +
|
564
|
+
"]" +
|
565
|
+
" }";
|
566
|
+
}
|
567
|
+
|
568
|
+
#[test]
|
569
|
+
fn test_trailing_characters() {
|
570
|
+
assert from_str("nulla") ==
|
571
|
+
err({line: 1u, col: 5u, msg: "trailing characters"});
|
572
|
+
assert from_str("truea") ==
|
573
|
+
err({line: 1u, col: 5u, msg: "trailing characters"});
|
574
|
+
assert from_str("falsea") ==
|
575
|
+
err({line: 1u, col: 6u, msg: "trailing characters"});
|
576
|
+
assert from_str("1a") ==
|
577
|
+
err({line: 1u, col: 2u, msg: "trailing characters"});
|
578
|
+
assert from_str("[]a") ==
|
579
|
+
err({line: 1u, col: 3u, msg: "trailing characters"});
|
580
|
+
assert from_str("{}a") ==
|
581
|
+
err({line: 1u, col: 3u, msg: "trailing characters"});
|
582
|
+
}
|
583
|
+
|
584
|
+
#[test]
|
585
|
+
fn test_read_identifiers() {
|
586
|
+
assert from_str("n") ==
|
587
|
+
err({line: 1u, col: 2u, msg: "invalid syntax"});
|
588
|
+
assert from_str("nul") ==
|
589
|
+
err({line: 1u, col: 4u, msg: "invalid syntax"});
|
590
|
+
|
591
|
+
assert from_str("t") ==
|
592
|
+
err({line: 1u, col: 2u, msg: "invalid syntax"});
|
593
|
+
assert from_str("truz") ==
|
594
|
+
err({line: 1u, col: 4u, msg: "invalid syntax"});
|
595
|
+
|
596
|
+
assert from_str("f") ==
|
597
|
+
err({line: 1u, col: 2u, msg: "invalid syntax"});
|
598
|
+
assert from_str("faz") ==
|
599
|
+
err({line: 1u, col: 3u, msg: "invalid syntax"});
|
600
|
+
|
601
|
+
assert from_str("null") == ok(null);
|
602
|
+
assert from_str("true") == ok(boolean(true));
|
603
|
+
assert from_str("false") == ok(boolean(false));
|
604
|
+
assert from_str(" null ") == ok(null);
|
605
|
+
assert from_str(" true ") == ok(boolean(true));
|
606
|
+
assert from_str(" false ") == ok(boolean(false));
|
607
|
+
}
|
608
|
+
|
609
|
+
#[test]
|
610
|
+
fn test_read_num() {
|
611
|
+
assert from_str("+") ==
|
612
|
+
err({line: 1u, col: 1u, msg: "invalid syntax"});
|
613
|
+
assert from_str(".") ==
|
614
|
+
err({line: 1u, col: 1u, msg: "invalid syntax"});
|
615
|
+
|
616
|
+
assert from_str("-") ==
|
617
|
+
err({line: 1u, col: 2u, msg: "invalid number"});
|
618
|
+
assert from_str("00") ==
|
619
|
+
err({line: 1u, col: 2u, msg: "invalid number"});
|
620
|
+
assert from_str("1.") ==
|
621
|
+
err({line: 1u, col: 3u, msg: "invalid number"});
|
622
|
+
assert from_str("1e") ==
|
623
|
+
err({line: 1u, col: 3u, msg: "invalid number"});
|
624
|
+
assert from_str("1e+") ==
|
625
|
+
err({line: 1u, col: 4u, msg: "invalid number"});
|
626
|
+
|
627
|
+
assert from_str("3") == ok(num(3f));
|
628
|
+
assert from_str("3.1") == ok(num(3.1f));
|
629
|
+
assert from_str("-1.2") == ok(num(-1.2f));
|
630
|
+
assert from_str("0.4") == ok(num(0.4f));
|
631
|
+
assert from_str("0.4e5") == ok(num(0.4e5f));
|
632
|
+
assert from_str("0.4e+15") == ok(num(0.4e15f));
|
633
|
+
assert from_str("0.4e-01") == ok(num(0.4e-01f));
|
634
|
+
assert from_str(" 3 ") == ok(num(3f));
|
635
|
+
}
|
636
|
+
|
637
|
+
#[test]
|
638
|
+
fn test_read_str() {
|
639
|
+
assert from_str("\"") ==
|
640
|
+
err({line: 1u, col: 2u, msg: "EOF while parsing string"});
|
641
|
+
assert from_str("\"lol") ==
|
642
|
+
err({line: 1u, col: 5u, msg: "EOF while parsing string"});
|
643
|
+
|
644
|
+
assert from_str("\"\"") == ok(string(""));
|
645
|
+
assert from_str("\"foo\"") == ok(string("foo"));
|
646
|
+
assert from_str("\"\\\"\"") == ok(string("\""));
|
647
|
+
assert from_str("\"\\b\"") == ok(string("\x08"));
|
648
|
+
assert from_str("\"\\n\"") == ok(string("\n"));
|
649
|
+
assert from_str("\"\\r\"") == ok(string("\r"));
|
650
|
+
assert from_str("\"\\t\"") == ok(string("\t"));
|
651
|
+
assert from_str(" \"foo\" ") == ok(string("foo"));
|
652
|
+
}
|
653
|
+
|
654
|
+
#[test]
|
655
|
+
fn test_read_list() {
|
656
|
+
assert from_str("[") ==
|
657
|
+
err({line: 1u, col: 2u, msg: "EOF while parsing value"});
|
658
|
+
assert from_str("[1") ==
|
659
|
+
err({line: 1u, col: 3u, msg: "EOF while parsing list"});
|
660
|
+
assert from_str("[1,") ==
|
661
|
+
err({line: 1u, col: 4u, msg: "EOF while parsing value"});
|
662
|
+
assert from_str("[1,]") ==
|
663
|
+
err({line: 1u, col: 4u, msg: "invalid syntax"});
|
664
|
+
assert from_str("[6 7]") ==
|
665
|
+
err({line: 1u, col: 4u, msg: "expecting ',' or ']'"});
|
666
|
+
|
667
|
+
assert from_str("[]") == ok(list([]));
|
668
|
+
assert from_str("[ ]") == ok(list([]));
|
669
|
+
assert from_str("[true]") == ok(list([boolean(true)]));
|
670
|
+
assert from_str("[ false ]") == ok(list([boolean(false)]));
|
671
|
+
assert from_str("[null]") == ok(list([null]));
|
672
|
+
assert from_str("[3, 1]") == ok(list([num(3f), num(1f)]));
|
673
|
+
assert from_str("\n[3, 2]\n") == ok(list([num(3f), num(2f)]));
|
674
|
+
assert from_str("[2, [4, 1]]") ==
|
675
|
+
ok(list([num(2f), list([num(4f), num(1f)])]));
|
676
|
+
}
|
677
|
+
|
678
|
+
#[test]
|
679
|
+
fn test_read_dict() {
|
680
|
+
assert from_str("{") ==
|
681
|
+
err({line: 1u, col: 2u, msg: "EOF while parsing object"});
|
682
|
+
assert from_str("{ ") ==
|
683
|
+
err({line: 1u, col: 3u, msg: "EOF while parsing object"});
|
684
|
+
assert from_str("{1") ==
|
685
|
+
err({line: 1u, col: 2u, msg: "key must be a string"});
|
686
|
+
assert from_str("{ \"a\"") ==
|
687
|
+
err({line: 1u, col: 6u, msg: "EOF while parsing object"});
|
688
|
+
assert from_str("{\"a\"") ==
|
689
|
+
err({line: 1u, col: 5u, msg: "EOF while parsing object"});
|
690
|
+
assert from_str("{\"a\" ") ==
|
691
|
+
err({line: 1u, col: 6u, msg: "EOF while parsing object"});
|
692
|
+
|
693
|
+
assert from_str("{\"a\" 1") ==
|
694
|
+
err({line: 1u, col: 6u, msg: "expecting ':'"});
|
695
|
+
assert from_str("{\"a\":") ==
|
696
|
+
err({line: 1u, col: 6u, msg: "EOF while parsing value"});
|
697
|
+
assert from_str("{\"a\":1") ==
|
698
|
+
err({line: 1u, col: 7u, msg: "EOF while parsing object"});
|
699
|
+
assert from_str("{\"a\":1 1") ==
|
700
|
+
err({line: 1u, col: 8u, msg: "expecting ',' or '}'"});
|
701
|
+
assert from_str("{\"a\":1,") ==
|
702
|
+
err({line: 1u, col: 8u, msg: "EOF while parsing object"});
|
703
|
+
|
704
|
+
assert eq(result::get(from_str("{}")), mk_dict([]));
|
705
|
+
assert eq(result::get(from_str("{\"a\": 3}")),
|
706
|
+
mk_dict([("a", num(3.0f))]));
|
707
|
+
|
708
|
+
assert eq(result::get(from_str("{ \"a\": null, \"b\" : true }")),
|
709
|
+
mk_dict([("a", null), ("b", boolean(true))]));
|
710
|
+
assert eq(result::get(from_str("\n{ \"a\": null, \"b\" : true }\n")),
|
711
|
+
mk_dict([("a", null), ("b", boolean(true))]));
|
712
|
+
assert eq(result::get(from_str("{\"a\" : 1.0 ,\"b\": [ true ]}")),
|
713
|
+
mk_dict([
|
714
|
+
("a", num(1.0)),
|
715
|
+
("b", list([boolean(true)]))
|
716
|
+
]));
|
717
|
+
assert eq(result::get(from_str(
|
718
|
+
"{" +
|
719
|
+
"\"a\": 1.0, " +
|
720
|
+
"\"b\": [" +
|
721
|
+
"true," +
|
722
|
+
"\"foo\\nbar\", " +
|
723
|
+
"{ \"c\": {\"d\": null} } " +
|
724
|
+
"]" +
|
725
|
+
"}")),
|
726
|
+
mk_dict([
|
727
|
+
("a", num(1.0f)),
|
728
|
+
("b", list([
|
729
|
+
boolean(true),
|
730
|
+
string("foo\nbar"),
|
731
|
+
mk_dict([
|
732
|
+
("c", mk_dict([("d", null)]))
|
733
|
+
])
|
734
|
+
]))
|
735
|
+
]));
|
736
|
+
}
|
737
|
+
|
738
|
+
#[test]
|
739
|
+
fn test_multiline_errors() {
|
740
|
+
assert from_str("{\n \"foo\":\n \"bar\"") ==
|
741
|
+
err({line: 3u, col: 8u, msg: "EOF while parsing object"});
|
742
|
+
}
|
743
|
+
}
|