Skip to content

Commit

Permalink
Merge pull request #10 from cookpad/horiso/add-continuous-language-op…
Browse files Browse the repository at this point in the history
…tion

Add continuous language option
  • Loading branch information
sota-horiuchi authored Mar 26, 2024
2 parents bd99203 + 75e1643 commit e7326c9
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 7 deletions.
1 change: 1 addition & 0 deletions lib/ingreedy.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
path = File.expand_path(File.join(File.dirname(__FILE__), "ingreedy"))

require File.join(path, "case_insensitive_parser")
require File.join(path, "continuous_language_locale")
require File.join(path, "ingreedy_parser")
require File.join(path, "dictionary_collection")

Expand Down
11 changes: 10 additions & 1 deletion lib/ingreedy/amount_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
module Ingreedy
class AmountParser < Parslet::Parser
include CaseInsensitiveParser
include ContinuousLanguageLocale

rule(:whitespace) do
match("\s")
if use_whitespace?(current_locale)
match("\s")
else
match("\s").maybe
end
end

rule(:integer) do
Expand Down Expand Up @@ -58,6 +63,10 @@ class AmountParser < Parslet::Parser

private

def current_locale
Ingreedy.dictionaries.current.locale
end

def word_digits
Ingreedy.dictionaries.current.numbers.keys
end
Expand Down
9 changes: 9 additions & 0 deletions lib/ingreedy/continuous_language_locale.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Ingreedy
module ContinuousLanguageLocale
CONTINUOUS_LANGUAGES_LOCALES = %i(ja th zh-TW)

def use_whitespace?(locale)
!CONTINUOUS_LANGUAGES_LOCALES.include?(locale)
end
end
end
5 changes: 3 additions & 2 deletions lib/ingreedy/dictionary.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
module Ingreedy
class Dictionary
attr_reader :units, :numbers, :prepositions, :range_separators
attr_reader :units, :numbers, :prepositions, :range_separators, :locale
attr_reader :imprecise_amounts

def initialize(units:, numbers: {}, prepositions: [], range_separators: %w{- ~}, imprecise_amounts: [])
def initialize(units:, numbers: {}, prepositions: [], range_separators: %w{- ~}, imprecise_amounts: [], locale: nil)
@units = units
@numbers = sort_by_length(numbers)
@prepositions = prepositions
@range_separators = range_separators
@imprecise_amounts = imprecise_amounts
@locale = locale
end

# https://en.wikipedia.org/wiki/Number_Forms
Expand Down
4 changes: 2 additions & 2 deletions lib/ingreedy/dictionary_collection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def initialize
end

def []=(locale, attributes)
@collection[locale] = Dictionary.new(**attributes)
@collection[locale] = Dictionary.new(**attributes, locale: locale)
end

def current
Expand Down Expand Up @@ -38,7 +38,7 @@ def i18n_gem_locales
end

def fetch_dictionary(locale)
@collection[locale] ||= Dictionary.new **load_yaml(locale)
@collection[locale] ||= Dictionary.new(**load_yaml(locale), locale: locale)
rescue Errno::ENOENT
end

Expand Down
13 changes: 11 additions & 2 deletions lib/ingreedy/root_parser.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Ingreedy
class RootParser < Parslet::Parser
include CaseInsensitiveParser
include ContinuousLanguageLocale

rule(:range) do
AmountParser.new.as(:amount) >>
Expand All @@ -19,7 +20,11 @@ class RootParser < Parslet::Parser
end

rule(:whitespace) do
match("\s")
if use_whitespace?(current_locale)
match("\s")
else
match("\s").maybe
end
end

rule(:container_amount) do
Expand Down Expand Up @@ -87,7 +92,7 @@ class RootParser < Parslet::Parser

rule(:reverse_format) do
# e.g. flour 200g
((whitespace >> quantity).absent? >> any).repeat.as(:ingredient) >>
((whitespace >> quantity >> any.absent?).absent? >> any).repeat.as(:ingredient) >>
whitespace >>
quantity
end
Expand Down Expand Up @@ -119,6 +124,10 @@ def parse
private

attr_reader :original_query

def current_locale
Ingreedy.dictionaries.current.locale
end

def imprecise_amounts
Ingreedy.dictionaries.current.imprecise_amounts
Expand Down
23 changes: 23 additions & 0 deletions spec/ingreedy/continuouse_language_locale_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'ingreedy/continuous_language_locale'

RSpec.describe Ingreedy::ContinuousLanguageLocale do
include Ingreedy::ContinuousLanguageLocale

describe '#use_whitespace?' do
context 'when the locale is a continuous language' do
it 'returns false' do
expect(use_whitespace?(:ja)).to be_falsey
expect(use_whitespace?(:th)).to be_falsey
expect(use_whitespace?(:'zh-TW')).to be_falsey
end
end

context 'when the locale is not a continuous language' do
it 'returns true' do
expect(use_whitespace?(:en)).to be_truthy
expect(use_whitespace?(:fr)).to be_truthy
expect(use_whitespace?(:'zh-CN')).to be_truthy
end
end
end
end
78 changes: 78 additions & 0 deletions spec/ingreedy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,84 @@
end
end

describe Ingreedy, "continuous language" do
context "Japanese" do
before do
Ingreedy.dictionaries[:ja] = {
units: { gram: ["g"], other: ["個"] },
numbers: { "一" => 1 },
}
Ingreedy.locale = :ja
end

after do
Ingreedy.locale = nil
end

it "parses correctly" do
result = Ingreedy.parse "200g砂糖"

expect(result.amount).to eq(200)
expect(result.unit).to eq(:gram)
expect(result.ingredient).to eq("砂糖")
end

it "parses correctly with reverse format" do
result = Ingreedy.parse "砂糖200g"

expect(result.amount).to eq(200)
expect(result.unit).to eq(:gram)
expect(result.ingredient).to eq("砂糖")
end

it "parses correctly with numbers" do
result = Ingreedy.parse "卵一個"

expect(result.amount).to eq(1)
expect(result.unit).to eq(:other)
expect(result.ingredient).to eq("卵")
end
end

context "Taiwanese" do
before do
Ingreedy.dictionaries[:"zh-TW"] = {
units: { gram: ["g"], other: ["个"] },
numbers: { "一" => 1 },
}
Ingreedy.locale = :"zh-TW"
end

after do
Ingreedy.locale = nil
end

it "parses correctly" do
result = Ingreedy.parse "200g砂糖"

expect(result.amount).to eq(200)
expect(result.unit).to eq(:gram)
expect(result.ingredient).to eq("砂糖")
end

it "parses correctly with reverse format" do
result = Ingreedy.parse "砂糖200g"

expect(result.amount).to eq(200)
expect(result.unit).to eq(:gram)
expect(result.ingredient).to eq("砂糖")
end

it "parses correctly with numbers" do
result = Ingreedy.parse "一个鸡蛋"

expect(result.amount).to eq(1)
expect(result.unit).to eq(:other)
expect(result.ingredient).to eq("鸡蛋")
end
end
end

describe Ingreedy, "error handling" do
it "wraps Parslet exceptions in a custom exception" do
expect do
Expand Down

0 comments on commit e7326c9

Please sign in to comment.