dolos 0.1.2 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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