dolos 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68d26c878ffd86122b9c12273645cf351f5b20d6e1306e140c53727c29e49b2b
4
- data.tar.gz: 6bda399416128f5692e2966a46194591209f61602408e6873cb4e41f37a22ec4
3
+ metadata.gz: bdfe6ab9b41e2783d7a0f6fa530bccf44cecc1aaaf2dff900bc346ef980d8fef
4
+ data.tar.gz: 29ee6fd6ff4bdc45a8d165a54e5a0a6bc57d3ae7068a60049d00385b37011fa7
5
5
  SHA512:
6
- metadata.gz: 7ae6b3a4750cc5bfb5f54a84d518f8d4176eaf10dfef4482f45aaadc3db422a14f04cabb65ee0e1fe85b7dfb95fa1b54c8daf4f91083f4f39beac32c70c25616
7
- data.tar.gz: e4ab436619a690d257fdaba829fcbc00ec74c56cd8fda0c754fd5f1985fe2d3b21adcda1db69f7ca116437ccf8cf9c6455f03cb05ab44b8107033db590266398
6
+ metadata.gz: 239dcd2a22ae2bcbd85e2915e28fe67eec4f0e75e9d7c7e4668ec930b30781cac256628833c8f5ca19cdafec1d31642098b27e5ba5a83c43e0abe08ae1277766
7
+ data.tar.gz: 0c5698dd2cd7b91b9861125e6306ba99a7406bcaf4b1314eac5218fdc789235cc91d3794c67f0f82ff9cf32956b52f788e1c20607215f04586919a3988e75dad
data/README.md CHANGED
@@ -23,30 +23,34 @@ require 'dolos'
23
23
  include Dolos
24
24
 
25
25
  ws = c(" ")
26
- parser = c("Parsers") >> ws >> c("are") >> ws >> c("great!")
26
+ parser = c("Parsers") & ws & c("are") & ws & c("great!")
27
27
  parser.run("Parsers are great!") # <Result::Success>
28
28
 
29
29
  greeter = c("Hello")
30
- greet_and_speak = greeter >> c(", ") >> parser
30
+ greet_and_speak = greeter & c(", ") & parser
31
31
  greet_and_speak.run("Hello, Parsers are great!") # <Result::Success>
32
32
  ```
33
33
 
34
34
  ### Letter address parser example
35
+
35
36
  ```ruby
36
37
  require 'dolos'
37
38
  require 'dolos_common_parsers/common_parsers'
38
39
 
40
+ include Dolos
41
+ # frozen_string_literal: true
42
+ require_relative 'dolos'
43
+ require_relative 'dolos_common_parsers/common_parsers'
44
+
39
45
  include Dolos
40
46
 
41
47
  # Include common parsers
42
- # In future this can be more structured,
43
- # moved them to separate module to prevent breaking changes
48
+ # In future this can be more structured, moved them to separate module to prevent breaking changes
44
49
  include Dolos::CommonParsers
45
50
 
46
51
  # Library usage example
47
52
  # Parse out a name and address from a letter
48
- # For higher difficulty, we will not split this into multiple lines,
49
- # but instead parse it all at once
53
+ # For higher difficulty, we will not split this into multiple lines, but instead parse it all at once
50
54
  letter = <<-LETTER
51
55
  Mr. Vardeniui Pavardeniui
52
56
  AB „Lietuvos Paštas“
@@ -63,12 +67,12 @@ alpha_with_lt = char_in("ąčęėįšųūžĄČĘĖĮŠŲŪŽ") | alpha
63
67
 
64
68
  # Capture all letters in a row and join them,
65
69
  # because they are captured as elements of array by each alpha_with_lt parser.
66
- first_name = alpha_with_lt.rep.capture!.map(&:join)
67
- last_name = alpha_with_lt.rep.capture!.map(&:join)
70
+ first_name = alpha_with_lt.rep.map(&:join).capture!
71
+ last_name = alpha_with_lt.rep.map(&:join).capture!
68
72
 
69
73
  # Combine first line parsers
70
74
  # Consume zero or more whitespace, after that honorific must follow and so on
71
- name_line = ws.rep0 >> honorific >> first_name >> ws >> last_name >> eol
75
+ name_line = ws.rep0 & honorific & first_name & ws & last_name & eol
72
76
 
73
77
  # Next line is company info
74
78
  # We could choose to accept UAB and AB or just AB and etc.
@@ -78,9 +82,9 @@ quote_open = c("„")
78
82
  quote_close = c("“")
79
83
 
80
84
  # Consume LT alphabet with whitespace
81
- company_name = (alpha_with_lt | ws).rep.capture!.map(&:join)
82
- company_info = company_type >> ws.rep0 >> quote_open >> company_name >> quote_close
83
- second_line = ws.rep0 >> company_info >> eol
85
+ company_name = (alpha_with_lt | ws).rep.map(&:join).capture!
86
+ company_info = company_type & ws.rep0 & quote_open & company_name & quote_close
87
+ second_line = ws.rep0 & company_info & eol
84
88
 
85
89
  # Address line
86
90
  # 'char_while' will consume characters while passed predicate is true
@@ -88,31 +92,38 @@ second_line = ws.rep0 >> company_info >> eol
88
92
  # After that result is captured and mapped to hash
89
93
  # Mapping to hash so at the end its easy to tell tuples apart
90
94
  # Also while mapping, doing some cleaning with '.strip'
91
- street_name = char_while(->(char) { !char.match(/\d/) })
92
- .capture!
93
- .map(&:first)
94
- .map { |s| { street: s.strip } }
95
- building = digits.capture!.map(&:first).map { |s| { building: s.strip } }
96
- address_line = ws.rep0 >> street_name >> building >> eol
95
+ street_name = char_while(->(char) { !char.match(/\d/) }).map { |s| { street: s.strip } }.capture!
96
+ building = digits.map { |s| { building: s.strip } }.capture!
97
+ address_line = ws.rep0 & street_name & building & eol
97
98
 
98
99
  # City line
99
- # All digits can be matched here or 'digits.rep(5)' could be used.
100
- # Also joining with map results.
101
- postcode = digits.capture!.map(&:join).map { |s| { postcode: s.strip } }
102
- city = alpha_with_lt.rep.capture!.map(&:join).map { |s| { city: s.strip } }
103
- city_line = ws.rep0 >> postcode >> ws >> city >> eol
104
-
105
- # Full letter parser which is combined from all previous parsers.
106
- # Also, all previous parsers can be ran separately.
107
- letter_parser = name_line >> second_line >> address_line >> city_line
100
+ # All digits can be matched here or 'digits.rep(5)' could be used. Also joining with map.
101
+ postcode = digits.map { |s| { postcode: s.strip } }.capture!
102
+ city = alpha_with_lt.rep.map(&:join).map { |s| { city: s.strip } }.capture!
103
+ city_line = ws.rep0 & postcode & ws & city & eol
104
+
105
+ # Full letter parser which is combined from all previous parsers. All previous parsers can be ran separately.
106
+ letter_parser = name_line & second_line & address_line & city_line
108
107
  result = letter_parser.run(letter)
109
108
 
110
- # List of tuples
111
109
  pp result.captures
112
- # ["Vardeniui", "Pavardeniui", "Lietuvos Paštas", {:street=>"Totorių g."},
113
- # {:building=>"8"}, {:postcode=>"01121"}, {:city=>"Vilnius"}]
114
110
 
115
111
  ```
112
+ ### Roadmap
113
+ - Better error handling
114
+ - Benchmarks & parser tests
115
+ - Documentation
116
+ - Performance
117
+
118
+ ### Benchmarks
119
+ `bundle exec ruby benchmarks/json/json.rb`
120
+ ```
121
+ Calculating -------------------------------------
122
+ nested json benchmark
123
+ 0.090 (± 0.0%) i/s - 6.000 in 66.952366s
124
+ ```
125
+ Its very slow, not ready for use yet. API is unstable is as well.
126
+
116
127
 
117
128
  ### Contributing
118
129
  Contributors are welcome. Note: since library is not yet stable, I recommend getting in touch with me before starting to work on something.
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'benchmark/ips'
4
+ require 'dolos'
5
+ require 'dolos_common_parsers/common_parsers'
6
+
7
+ include Dolos
8
+ include Dolos::CommonParsers
9
+
10
+ def ws_rep0 = ws.rep0
11
+
12
+ def comma = c(",")
13
+
14
+ def string_literal = (c("\"") >> char_while(->(ch) { ch != "\"" }).opt << c("\""))
15
+
16
+ def boolean = (c("true").map { true } | c("false").map { false })
17
+
18
+ def null = c("null").map { nil }
19
+
20
+ def array = recursive do |arr|
21
+ c("[") >> ws_rep0 >> value.repeat(n_min: 0, separator: (comma << ws_rep0)) << ws_rep0 << c("]")
22
+ end
23
+
24
+ def negative_sign = c("-").opt
25
+
26
+ def decimal_point = c('.').opt
27
+
28
+ def number = (negative_sign & digits & decimal_point & digits.opt).map do |tuple|
29
+ tuple.join.to_f
30
+ end
31
+
32
+ def value = number | object | string_literal | boolean | null | array
33
+
34
+ def key_line = ((string_literal << ws_rep0) << c(":") & ws_rep0 >> value).map do |tuple|
35
+ { tuple[0] => tuple[1] }
36
+ end
37
+
38
+ def key_lines = (key_line << ws_rep0).repeat(n_min: 1, separator: (comma << ws_rep0 << eol.opt)).map do |arr|
39
+ arr.reduce({}) do |acc, hash|
40
+ acc.merge(hash)
41
+ end
42
+ end
43
+
44
+ def object = recursive do |obj|
45
+ c("{") >> ws_rep0 >> key_lines.opt << ws_rep0 << c("}")
46
+ end
47
+
48
+ def json_parser = ws_rep0 >> value
49
+
50
+ json_from_file = File.read('benchmarks/json/random.json')
51
+
52
+ Benchmark.ips do |x|
53
+ x.time = 60
54
+ x.warmup = 15
55
+
56
+ x.report('nested json benchmark') do
57
+ json_parser.run(json_from_file)
58
+ end
59
+ x.compare!
60
+ end