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.
Files changed (70) hide show
  1. data/README.md +6 -1
  2. data/lexers +0 -0
  3. data/lib/pygments/version.rb +1 -1
  4. data/vendor/pygments-main/AUTHORS +15 -0
  5. data/vendor/pygments-main/CHANGES +28 -1
  6. data/vendor/pygments-main/LICENSE +1 -1
  7. data/vendor/pygments-main/external/lasso-builtins-generator-9.lasso +121 -0
  8. data/vendor/pygments-main/pygments/cmdline.py +1 -1
  9. data/vendor/pygments-main/pygments/filters/__init__.py +0 -1
  10. data/vendor/pygments-main/pygments/formatters/_mapping.py +2 -2
  11. data/vendor/pygments-main/pygments/formatters/img.py +1 -1
  12. data/vendor/pygments-main/pygments/formatters/latex.py +8 -8
  13. data/vendor/pygments-main/pygments/formatters/other.py +0 -2
  14. data/vendor/pygments-main/pygments/lexers/_lassobuiltins.py +5413 -0
  15. data/vendor/pygments-main/pygments/lexers/_mapping.py +36 -11
  16. data/vendor/pygments-main/pygments/lexers/_openedgebuiltins.py +551 -0
  17. data/vendor/pygments-main/pygments/lexers/_postgres_builtins.py +0 -1
  18. data/vendor/pygments-main/pygments/lexers/_robotframeworklexer.py +546 -0
  19. data/vendor/pygments-main/pygments/lexers/_sourcemodbuiltins.py +1072 -0
  20. data/vendor/pygments-main/pygments/lexers/_stan_builtins.py +174 -0
  21. data/vendor/pygments-main/pygments/lexers/_vimbuiltins.py +13 -3
  22. data/vendor/pygments-main/pygments/lexers/agile.py +145 -33
  23. data/vendor/pygments-main/pygments/lexers/asm.py +2 -2
  24. data/vendor/pygments-main/pygments/lexers/compiled.py +328 -36
  25. data/vendor/pygments-main/pygments/lexers/dalvik.py +104 -0
  26. data/vendor/pygments-main/pygments/lexers/dotnet.py +8 -14
  27. data/vendor/pygments-main/pygments/lexers/functional.py +773 -8
  28. data/vendor/pygments-main/pygments/lexers/jvm.py +184 -36
  29. data/vendor/pygments-main/pygments/lexers/math.py +349 -23
  30. data/vendor/pygments-main/pygments/lexers/other.py +315 -492
  31. data/vendor/pygments-main/pygments/lexers/parsers.py +83 -1
  32. data/vendor/pygments-main/pygments/lexers/shell.py +4 -1
  33. data/vendor/pygments-main/pygments/lexers/templates.py +112 -2
  34. data/vendor/pygments-main/pygments/lexers/text.py +52 -3
  35. data/vendor/pygments-main/pygments/lexers/web.py +382 -36
  36. data/vendor/pygments-main/pygments/unistring.py +35 -25
  37. data/vendor/pygments-main/pygments/util.py +45 -0
  38. data/vendor/pygments-main/tests/examplefiles/Config.in.cache +1973 -0
  39. data/vendor/pygments-main/tests/examplefiles/example.Rd +78 -0
  40. data/vendor/pygments-main/tests/examplefiles/example.bug +54 -0
  41. data/vendor/pygments-main/tests/examplefiles/example.ceylon +33 -0
  42. data/vendor/pygments-main/tests/examplefiles/example.jag +48 -0
  43. data/vendor/pygments-main/tests/examplefiles/example.monkey +152 -0
  44. data/vendor/pygments-main/tests/examplefiles/example.msc +43 -0
  45. data/vendor/pygments-main/tests/examplefiles/example.reg +19 -0
  46. data/vendor/pygments-main/tests/examplefiles/example.rkt +95 -0
  47. data/vendor/pygments-main/tests/examplefiles/example.rpf +4 -0
  48. data/vendor/pygments-main/tests/examplefiles/example.stan +97 -0
  49. data/vendor/pygments-main/tests/examplefiles/example.xtend +34 -0
  50. data/vendor/pygments-main/tests/examplefiles/example2.msc +79 -0
  51. data/vendor/pygments-main/tests/examplefiles/garcia-wachs.kk +123 -0
  52. data/vendor/pygments-main/tests/examplefiles/hello.smali +40 -0
  53. data/vendor/pygments-main/tests/examplefiles/hello.sp +9 -0
  54. data/vendor/pygments-main/tests/examplefiles/http_request_example +2 -1
  55. data/vendor/pygments-main/tests/examplefiles/http_response_example +4 -2
  56. data/vendor/pygments-main/tests/examplefiles/inet_pton6.dg +71 -0
  57. data/vendor/pygments-main/tests/examplefiles/json.lasso +301 -0
  58. data/vendor/pygments-main/tests/examplefiles/json.lasso9 +213 -0
  59. data/vendor/pygments-main/tests/examplefiles/livescript-demo.ls +41 -0
  60. data/vendor/pygments-main/tests/examplefiles/matlab_sample +5 -2
  61. data/vendor/pygments-main/tests/examplefiles/metagrammar.treetop +455 -0
  62. data/vendor/pygments-main/tests/examplefiles/pytb_test3.pytb +4 -0
  63. data/vendor/pygments-main/tests/examplefiles/robotframework.txt +39 -0
  64. data/vendor/pygments-main/tests/examplefiles/rust_example.rs +743 -0
  65. data/vendor/pygments-main/tests/examplefiles/test.R +149 -115
  66. data/vendor/pygments-main/tests/examplefiles/test.cu +36 -0
  67. data/vendor/pygments-main/tests/test_basic_api.py +1 -1
  68. data/vendor/pygments-main/tests/test_util.py +18 -0
  69. metadata +34 -3
  70. data/vendor/pygments-main/REVISION +0 -1
@@ -0,0 +1,4 @@
1
+ >>> 3/"3"
2
+ Traceback (most recent call last):
3
+ File "<stdin>", line 1, in <module>
4
+ TypeError: unsupported operand type(s) for /: 'int' and 'str'
@@ -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
+ }