ingreedy 0.0.5 → 0.0.6

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
  SHA1:
3
- metadata.gz: b9b4b6105807082714db4a684b0667635a6c0a82
4
- data.tar.gz: 85c9ab384b6c419520723d9719b9f82d6ebca495
3
+ metadata.gz: e72a77814ed8f70d4de6ea053c9574de0e1c9723
4
+ data.tar.gz: 08e41cd39042f6699d75f635ff5ca036a5ebec31
5
5
  SHA512:
6
- metadata.gz: 3321ead5195bc89f49a38e9b9fd762f624e9dfed41486a703d05d4ffade3a5f4f1ea3898b16b99d598a0790ea3f108940851e3b6ab831abc388d1160cf095771
7
- data.tar.gz: 545113b12845639fb146fe26d9e263044452bcab8be636f5d83937752b0e74aaa07dbf6050550684e6ce444c5acdb6f3ff74ace23068c3cb7754af46e4ef6053
6
+ metadata.gz: 22cc38a7b4866f6058a97494e038fe97b450110e89f689188b4ddb4e675bd8832a521827d05191cc620bf69bdd34907936db194fcd4e657652b6cba73cef6668
7
+ data.tar.gz: 23b3d8af25501391647bc8bf73ef57f00d84ff6193a14014f551271cc5a0e531a7d717b12a893abb965ae72f18799e0a6e40f42d67ccba1f9c04fb7bc34fb926
@@ -5,14 +5,6 @@ module Ingreedy
5
5
  class AmountParser < Parslet::Parser
6
6
  include CaseInsensitiveParser
7
7
 
8
- def initialize(options = {})
9
- @key_prefix = options[:key_prefix] ? "#{options[:key_prefix]}_" : ''
10
- end
11
-
12
- def capture_key(key)
13
- (@key_prefix + key.to_s).to_sym
14
- end
15
-
16
8
  rule(:whitespace) do
17
9
  match("\s")
18
10
  end
@@ -23,12 +15,33 @@ module Ingreedy
23
15
 
24
16
  rule(:float) do
25
17
  integer.maybe >>
26
- str('.') >> integer
18
+ float_delimiter >> integer
19
+ end
20
+
21
+ rule(:float_delimiter) do
22
+ str(',') | str('.')
27
23
  end
28
24
 
29
25
  rule(:fraction) do
30
- (integer.as(capture_key(:integer_amount)) >> whitespace).maybe >>
31
- (integer >> match('/') >> integer).as(capture_key(:fraction_amount))
26
+ compound_simple_fraction | compound_vulgar_fraction
27
+ end
28
+
29
+ rule(:compound_simple_fraction) do
30
+ (integer.as(:integer_amount) >> whitespace).maybe >>
31
+ simple_fraction.as(:fraction_amount)
32
+ end
33
+
34
+ rule(:simple_fraction) do
35
+ integer >> match('/') >> integer
36
+ end
37
+
38
+ rule(:compound_vulgar_fraction) do
39
+ (integer.as(:integer_amount) >> whitespace.maybe).maybe >>
40
+ vulgar_fraction.as(:fraction_amount)
41
+ end
42
+
43
+ rule(:vulgar_fraction) do
44
+ vulgar_fractions.map { |f| str(f) }.inject(:|)
32
45
  end
33
46
 
34
47
  rule(:word_digit) do
@@ -41,20 +54,21 @@ module Ingreedy
41
54
 
42
55
  rule(:amount) do
43
56
  fraction |
44
- float.as(capture_key(:float_amount)) |
45
- integer.as(capture_key(:integer_amount)) |
46
- word_digit.as(capture_key(:word_integer_amount)) >> amount_unit_separator
57
+ float.as(:float_amount) |
58
+ integer.as(:integer_amount) |
59
+ word_digit.as(:word_integer_amount) >> amount_unit_separator
47
60
  end
48
61
 
49
62
  root(:amount)
50
63
 
51
64
  private
52
65
 
53
- def word_digits
54
- Ingreedy.dictionaries.current.numbers.keys
55
- end
66
+ def word_digits
67
+ Ingreedy.dictionaries.current.numbers.keys
68
+ end
56
69
 
70
+ def vulgar_fractions
71
+ Ingreedy.dictionaries.current.vulgar_fractions.keys
72
+ end
57
73
  end
58
-
59
-
60
74
  end
@@ -7,5 +7,29 @@ module Ingreedy
7
7
  @numbers = entries[:numbers] || {}
8
8
  @prepositions = entries[:prepositions] || []
9
9
  end
10
+
11
+ # https://en.wikipedia.org/wiki/Number_Forms
12
+ def vulgar_fractions
13
+ {
14
+ "\u00BC" => '1/4',
15
+ "\u00BD" => '1/2',
16
+ "\u00BE" => '3/4',
17
+ "\u2150" => '1/7',
18
+ "\u2151" => '1/9',
19
+ "\u2152" => '1/10',
20
+ "\u2153" => '1/3',
21
+ "\u2154" => '2/3',
22
+ "\u2155" => '1/5',
23
+ "\u2156" => '2/5',
24
+ "\u2157" => '3/5',
25
+ "\u2158" => '4/5',
26
+ "\u2159" => '1/6',
27
+ "\u215A" => '5/6',
28
+ "\u215B" => '1/8',
29
+ "\u215C" => '3/8',
30
+ "\u215D" => '5/8',
31
+ "\u215E" => '7/8'
32
+ }
33
+ end
10
34
  end
11
35
  end
@@ -2,7 +2,6 @@ require 'parslet'
2
2
 
3
3
  require_relative 'amount_parser'
4
4
  require_relative 'rationalizer'
5
- require_relative 'unit_parser'
6
5
  require_relative 'unit_variation_mapper'
7
6
 
8
7
  module Ingreedy
@@ -10,7 +9,15 @@ module Ingreedy
10
9
  class Parser < Parslet::Parser
11
10
 
12
11
  attr_reader :original_query
13
- Result = Struct.new(:amount, :unit, :ingredient, :original_query)
12
+ Result = Struct.new(:amount, :unit, :container_amount, :container_unit, :ingredient, :original_query)
13
+
14
+ rule(:range) do
15
+ AmountParser.new.as(:amount) >>
16
+ whitespace.maybe >>
17
+ str('-') >>
18
+ whitespace.maybe >>
19
+ AmountParser.new.as(:amount_end)
20
+ end
14
21
 
15
22
  rule(:amount) do
16
23
  AmountParser.new.as(:amount)
@@ -21,18 +28,30 @@ module Ingreedy
21
28
  end
22
29
 
23
30
  rule(:container_amount) do
24
- AmountParser.new(key_prefix: 'container')
31
+ AmountParser.new
25
32
  end
26
33
 
27
34
  rule(:unit) do
28
- UnitParser.new
35
+ if unit_matches.any?
36
+ unit_matches.map { |u| str(u) }.inject(:|)
37
+ else
38
+ str('')
39
+ end
40
+ end
41
+
42
+ rule(:container_unit) do
43
+ unit
29
44
  end
30
45
 
31
46
  rule(:unit_and_preposition) do
47
+ unit.as(:unit) >> (preposition_or_whitespace | any.absent?)
48
+ end
49
+
50
+ rule(:preposition_or_whitespace) do
32
51
  if prepositions.empty?
33
- unit.as(:unit) >> (whitespace | any.absent?)
52
+ whitespace
34
53
  else
35
- unit.as(:unit) >> (preposition | whitespace | any.absent?)
54
+ preposition | whitespace
36
55
  end
37
56
  end
38
57
 
@@ -42,10 +61,6 @@ module Ingreedy
42
61
  whitespace
43
62
  end
44
63
 
45
- rule(:container_unit) do
46
- UnitParser.new
47
- end
48
-
49
64
  rule(:amount_unit_separator) do
50
65
  whitespace | str('-')
51
66
  end
@@ -55,12 +70,12 @@ module Ingreedy
55
70
  str('(').maybe >>
56
71
  container_amount.as(:container_amount) >>
57
72
  amount_unit_separator.maybe >>
58
- container_unit.as(:unit) >>
59
- str(')').maybe >> whitespace
73
+ container_unit.as(:container_unit) >>
74
+ str(')').maybe >> preposition_or_whitespace
60
75
  end
61
76
 
62
77
  rule(:amount_and_unit) do
63
- amount >>
78
+ (range | amount) >>
64
79
  whitespace.maybe >>
65
80
  unit_and_preposition.maybe >>
66
81
  container_size.maybe
@@ -94,21 +109,26 @@ module Ingreedy
94
109
  result = Result.new
95
110
  result[:original_query] = original_query
96
111
 
97
- parslet_output = super(original_query)
112
+ parslet = super(original_query)
98
113
 
99
- result[:amount] = rationalize_total_amount(parslet_output[:amount], parslet_output[:container_amount])
114
+ result[:amount] = rationalize parslet[:amount]
115
+ result[:amount] = [result[:amount], rationalize(parslet[:amount_end])] if parslet[:amount_end]
116
+ result[:container_amount] = rationalize(parslet[:container_amount])
100
117
 
101
- if parslet_output[:unit]
102
- result[:unit] = convert_unit_variation_to_canonical(parslet_output[:unit].to_s)
103
- end
118
+ result[:unit] = convert_unit_variation_to_canonical(parslet[:unit].to_s) if parslet[:unit]
119
+ result[:container_unit] = convert_unit_variation_to_canonical(parslet[:container_unit].to_s) if parslet[:container_unit]
104
120
 
105
- result[:ingredient] = parslet_output[:ingredient].to_s.lstrip.rstrip #TODO cheating
121
+ result[:ingredient] = parslet[:ingredient].to_s.lstrip.rstrip #TODO cheating
106
122
 
107
123
  result
108
124
  end
109
125
 
110
126
  private
111
127
 
128
+ def unit_matches
129
+ @unit_matches ||= original_query.scan(UnitVariationMapper.regexp).sort_by(&:length).reverse
130
+ end
131
+
112
132
  def prepositions
113
133
  Ingreedy.dictionaries.current.prepositions
114
134
  end
@@ -117,26 +137,18 @@ module Ingreedy
117
137
  UnitVariationMapper.unit_from_variation(unit_variation)
118
138
  end
119
139
 
120
- def rationalize_total_amount(amount, container_amount)
121
- if container_amount
122
- rationalize_amount(amount) * rationalize_amount(container_amount, 'container_')
123
- else
124
- rationalize_amount(amount)
125
- end
126
- end
127
-
128
- def rationalize_amount(amount, capture_key_prefix = '')
140
+ def rationalize(amount)
129
141
  return unless amount
130
- integer = amount["#{capture_key_prefix}integer_amount".to_sym]
142
+ integer = amount[:integer_amount]
131
143
  integer &&= integer.to_s
132
144
 
133
- float = amount["#{capture_key_prefix}float_amount".to_sym]
145
+ float = amount[:float_amount]
134
146
  float &&= float.to_s
135
147
 
136
- fraction = amount["#{capture_key_prefix}fraction_amount".to_sym]
148
+ fraction = amount[:fraction_amount]
137
149
  fraction &&= fraction.to_s
138
150
 
139
- word = amount["#{capture_key_prefix}word_integer_amount".to_sym]
151
+ word = amount[:word_integer_amount]
140
152
  word &&= word.to_s
141
153
 
142
154
  Rationalizer.rationalize(
@@ -146,6 +158,5 @@ module Ingreedy
146
158
  word: word
147
159
  )
148
160
  end
149
-
150
161
  end
151
162
  end
@@ -1,7 +1,5 @@
1
1
  module Ingreedy
2
-
3
2
  class Rationalizer
4
-
5
3
  def self.rationalize(options)
6
4
  new(options).rationalize
7
5
  end
@@ -17,14 +15,14 @@ module Ingreedy
17
15
  if @word
18
16
  result = rationalize_word
19
17
  elsif @fraction
20
- result = @fraction.to_r
18
+ result = rationalize_fraction
21
19
  if @integer
22
20
  result += @integer.to_i
23
21
  end
24
22
  elsif @integer
25
23
  result = @integer.to_r
26
24
  elsif @float
27
- result = @float.to_r
25
+ result = @float.gsub(',', '.').to_r
28
26
  end
29
27
 
30
28
  result
@@ -32,10 +30,17 @@ module Ingreedy
32
30
 
33
31
  private
34
32
 
35
- def rationalize_word
36
- Ingreedy.dictionaries.current.numbers[@word.downcase]
37
- end
33
+ def rationalize_fraction
34
+ vulgar_fractions.each { |char, amount| @fraction.gsub!(char, amount.to_s) }
35
+ @fraction.to_r
36
+ end
38
37
 
39
- end
38
+ def vulgar_fractions
39
+ Ingreedy.dictionaries.current.vulgar_fractions
40
+ end
40
41
 
42
+ def rationalize_word
43
+ Ingreedy.dictionaries.current.numbers[@word.downcase]
44
+ end
45
+ end
41
46
  end
@@ -1,6 +1,11 @@
1
1
  module Ingreedy
2
2
  class UnitVariationMapper
3
3
 
4
+ def self.regexp
5
+ regexp = all_variations.map { |v| Regexp.escape(v) }.join('|')
6
+ regexp = Regexp.new(regexp, Regexp::IGNORECASE)
7
+ end
8
+
4
9
  def self.all_variations
5
10
  # Return these in order of size, descending
6
11
  # That way, the longer versions will try to be parsed first, then the shorter versions
@@ -1,4 +1,4 @@
1
1
  module Ingreedy
2
- VERSION = '0.0.5'
2
+ VERSION = '0.0.6'
3
3
  end
4
4
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ingreedy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian C. Anderson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-17 00:00:00.000000000 Z
11
+ date: 2015-10-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -127,7 +127,7 @@ dependencies:
127
127
  description: Natural language recipe ingredient parser that supports numeric amount,
128
128
  units, and ingredient
129
129
  email:
130
- - anderson.ian.c@gmail.com
130
+ - ian@iancanderson.com
131
131
  executables: []
132
132
  extensions: []
133
133
  extra_rdoc_files: []
@@ -139,7 +139,6 @@ files:
139
139
  - lib/ingreedy/dictionary_collection.rb
140
140
  - lib/ingreedy/ingreedy_parser.rb
141
141
  - lib/ingreedy/rationalizer.rb
142
- - lib/ingreedy/unit_parser.rb
143
142
  - lib/ingreedy/unit_variation_mapper.rb
144
143
  - lib/ingreedy/version.rb
145
144
  homepage: http://github.com/iancanderson/ingreedy
@@ -1,20 +0,0 @@
1
- module Ingreedy
2
-
3
- class UnitParser < Parslet::Parser
4
- include CaseInsensitiveParser
5
-
6
- rule(:unit) do
7
- unit_variations.map { |var| str(var) | stri(var) }.reduce(:|)
8
- end
9
-
10
- root :unit
11
-
12
- private
13
-
14
- def unit_variations
15
- UnitVariationMapper.all_variations
16
- end
17
-
18
- end
19
-
20
- end