calyx 0.10.4 → 0.11.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
  SHA1:
3
- metadata.gz: 78e2075bb19864a35f97504f1d2afc2e09b186ab
4
- data.tar.gz: 1e474a6d3bac3d62d5a8b25c5ad75ec724a95a44
3
+ metadata.gz: 3a89c9fc6b0ecc0e8779331da13072f11d810eab
4
+ data.tar.gz: 8a74d06ae8feb2e547426fbf893a3d2922010f29
5
5
  SHA512:
6
- metadata.gz: 8d4facec94b4ffd5c29bfb53d4f8cd6b0de4939d9937ed0853a15420246deeee0fb543ae210e6462b4b707f1c82bd9c462b54b427a8637bf35b7536bb3a4b842
7
- data.tar.gz: fd89979f568bd4ec3bd3655dfcacddf405841766ed7bef6a32a8d2d7a0ce501aa3bbc4fa85e67a0455106701f50787c071afbd6f4a6eb02d091f46c9a67a2be7
6
+ metadata.gz: c178d2441191f82aa308ae5d8599bb904a68128daa636435830b6ec58443cfa3ea1dd9a8e534b206442d658542f4aae8a5d906b9cd0677e22db7e983116529f9
7
+ data.tar.gz: 8ba8bb5db4ed05e66d9c1fb19986282607d6cbd10fac4de6ed70a18be5ae08b39367fd3931fd8c485b6bfc7687aae7610817547a6668b6de94a078fb843b240e
data/README.md CHANGED
@@ -181,6 +181,8 @@ class Fruit < Calyx::Grammar
181
181
  end
182
182
  ```
183
183
 
184
+ ## String Modifiers
185
+
184
186
  Dot-notation is supported in template expressions, allowing you to call any available method on the `String` object returned from a rule. Formatting methods can be chained arbitrarily and will execute in the same way as they would in native Ruby code.
185
187
 
186
188
  ```ruby
@@ -193,7 +195,77 @@ end
193
195
  # => "Why, hello there."
194
196
  ```
195
197
 
196
- In order to use more intricate natural language processing capabilities, you can embed additional methods onto the `String` class yourself, as well as use methods from existing Gems that monkeypatch `String`.
198
+ You can also extend the grammar with custom modifiers that provide useful formatting functions.
199
+
200
+ ### Filters
201
+
202
+ Filters accept an input string and return the transformed output:
203
+
204
+ ```ruby
205
+ class Greeting < Calyx::Grammar
206
+ filter :shoutycaps do |input|
207
+ input.upcase
208
+ end
209
+ start '{hello.shoutycaps} there.', 'Why, {hello} there.'
210
+ rule :hello, 'hello'
211
+ end
212
+
213
+ # => "HELLO there."
214
+ # => "Why, HELLO there."
215
+ ```
216
+
217
+ ### Mappings
218
+
219
+ The mapping shortcut allows you to specify a map of regex patterns pointing to their resulting substitution strings:
220
+
221
+ ```ruby
222
+ class GreenBottle < Calyx::Grammar
223
+ mapping :pluralize, /(.+)/ => '\\1s'
224
+ start 'One green {bottle}.', 'Two green {bottle.pluralize}.'
225
+ rule :bottle, 'bottle'
226
+ end
227
+
228
+ # => "One green bottle."
229
+ # => "Two green bottles."
230
+ ```
231
+
232
+ ### Modifier Mixins
233
+
234
+ In order to use more intricate natural language processing capabilities, you can add modifier methods to a module and extend the grammar with it:
235
+
236
+ ```ruby
237
+ module FullStop
238
+ def full_stop
239
+ self << '.'
240
+ end
241
+ end
242
+
243
+ class Hello < Calyx::Grammar
244
+ modifier FullStop
245
+ start '{hello.capitalize.full_stop}'
246
+ rule :hello, 'hello'
247
+ end
248
+
249
+ # => "Hello."
250
+ ```
251
+
252
+ To share custom modifiers across multiple grammars, you can include the module in `Calyx::Modifiers`. This will make the methods available to all subsequent instances:
253
+
254
+ ```ruby
255
+ module FullStop
256
+ def full_stop
257
+ self << '.'
258
+ end
259
+ end
260
+
261
+ class Calyx::Modifiers
262
+ include FullStop
263
+ end
264
+ ```
265
+
266
+ ### Monkeypatching String
267
+
268
+ Alternatively, you can combine methods from existing Gems that monkeypatch `String`:
197
269
 
198
270
  ```ruby
199
271
  require 'indefinite_article'
@@ -305,7 +377,12 @@ Rough plan for stabilising the API and features for a `1.0` release.
305
377
 
306
378
  ## Credits
307
379
 
308
- - [Mark Rickerby](https://github.com/maetl) (author and maintainer)
380
+ ### Author & Maintainer
381
+
382
+ - [Mark Rickerby](https://github.com/maetl)
383
+
384
+ ### Contributors
385
+
309
386
  - [Tariq Ali](https://github.com/tra38)
310
387
 
311
388
  ## License
data/lib/calyx.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require 'calyx/version'
2
2
  require 'calyx/grammar'
3
3
  require 'calyx/errors'
4
- require 'calyx/file_converter'
4
+ require 'calyx/format'
5
5
  require 'calyx/registry'
6
- require 'calyx/modifier'
6
+ require 'calyx/modifiers'
7
7
  require 'calyx/production/memo'
8
8
  require 'calyx/production/choices'
9
9
  require 'calyx/production/concat'
data/lib/calyx/errors.rb CHANGED
@@ -1,3 +1,11 @@
1
1
  module Calyx
2
- class RuleNotFound < NoMethodError; end
2
+ module Errors
3
+ class RuleNotFound < StandardError; end
4
+
5
+ class DuplicateRule < StandardError
6
+ def initialize(key)
7
+ super("Rule already declared in grammar: #{key}")
8
+ end
9
+ end
10
+ end
3
11
  end
@@ -0,0 +1,37 @@
1
+ module Calyx
2
+ module Format
3
+ def self.load(filename)
4
+ file = File.read(filename)
5
+ extension = File.extname(filename)
6
+ if extension == ".yml"
7
+ self.load_yml(file)
8
+ elsif extension == ".json"
9
+ self.load_json(file)
10
+ else
11
+ raise "Cannot convert #{extension} files."
12
+ end
13
+ end
14
+
15
+ def self.load_yml(file)
16
+ require 'yaml'
17
+ yaml = YAML.load(file)
18
+ self.build_grammar(yaml)
19
+ end
20
+
21
+ def self.load_json(file)
22
+ require 'json'
23
+ json = JSON.parse(file)
24
+ self.build_grammar(json)
25
+ end
26
+
27
+ private
28
+
29
+ def self.build_grammar(rules)
30
+ Calyx::Grammar.new do
31
+ rules.each do |label, productions|
32
+ rule(label, *productions)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
data/lib/calyx/grammar.rb CHANGED
@@ -5,6 +5,10 @@ module Calyx
5
5
  @registry ||= Registry.new
6
6
  end
7
7
 
8
+ def load(filename)
9
+ Format.load(filename)
10
+ end
11
+
8
12
  def modifier(name)
9
13
  registry.modifier(name)
10
14
  end
@@ -1,5 +1,5 @@
1
1
  module Calyx
2
- class Modifier
2
+ class Modifiers
3
3
  def extend_with(name)
4
4
  extend name
5
5
  end
@@ -1,11 +1,11 @@
1
1
  module Calyx
2
2
  class Registry
3
- attr_reader :rules, :transforms
3
+ attr_reader :rules, :transforms, :modifiers
4
4
 
5
5
  def initialize
6
6
  @rules = {}
7
7
  @transforms = {}
8
- @modifier = Modifier.new
8
+ @modifiers = Modifiers.new
9
9
  end
10
10
 
11
11
  def method_missing(name, *arguments)
@@ -13,7 +13,7 @@ module Calyx
13
13
  end
14
14
 
15
15
  def modifier(name)
16
- @modifier.extend_with(name)
16
+ modifiers.extend_with(name)
17
17
  end
18
18
 
19
19
  def mapping(name, pairs)
@@ -40,7 +40,7 @@ module Calyx
40
40
  if transforms.key?(name)
41
41
  transforms[name].call(value)
42
42
  else
43
- @modifier.transform(name, value)
43
+ modifiers.transform(name, value)
44
44
  end
45
45
  end
46
46
 
@@ -57,7 +57,7 @@ module Calyx
57
57
 
58
58
  rules_map.each do |key, value|
59
59
  if rules.key?(key.to_sym)
60
- raise "Rule already declared in grammar: #{key}"
60
+ raise Error::DuplicateRule.new(key)
61
61
  end
62
62
 
63
63
  context[key.to_sym] = if value.is_a?(Array)
@@ -72,7 +72,7 @@ module Calyx
72
72
  if expansion.respond_to?(:evaluate)
73
73
  [start_symbol, expansion.evaluate]
74
74
  else
75
- raise RuleNotFound.new(start_symbol)
75
+ raise Errors::RuleNotFound.new(start_symbol)
76
76
  end
77
77
  end
78
78
 
@@ -93,7 +93,9 @@ module Calyx
93
93
  end
94
94
 
95
95
  def construct_rule(productions)
96
- if productions.first.is_a?(Enumerable)
96
+ if productions.first.is_a?(Hash)
97
+ Production::WeightedChoices.parse(productions.first.to_a, self)
98
+ elsif productions.first.is_a?(Enumerable)
97
99
  Production::WeightedChoices.parse(productions, self)
98
100
  else
99
101
  Production::Choices.parse(productions, self)
data/lib/calyx/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Calyx
2
- VERSION = '0.10.4'.freeze
2
+ VERSION = '0.11.0'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: calyx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.4
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Rickerby
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-06-01 00:00:00.000000000 Z
11
+ date: 2016-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,9 +69,9 @@ files:
69
69
  - examples/tiny_woodland.rb
70
70
  - lib/calyx.rb
71
71
  - lib/calyx/errors.rb
72
- - lib/calyx/file_converter.rb
72
+ - lib/calyx/format.rb
73
73
  - lib/calyx/grammar.rb
74
- - lib/calyx/modifier.rb
74
+ - lib/calyx/modifiers.rb
75
75
  - lib/calyx/production/choices.rb
76
76
  - lib/calyx/production/concat.rb
77
77
  - lib/calyx/production/expression.rb
@@ -1,40 +0,0 @@
1
- require 'yaml'
2
- require 'json'
3
-
4
- module Calyx
5
- class Grammar
6
- class << self
7
- def load(filename)
8
- file = File.read(filename)
9
- extension = File.extname(filename)
10
- if extension == ".yml"
11
- load_yml(file)
12
- elsif extension == ".json"
13
- load_json(file)
14
- else
15
- raise "Cannot convert #{extension} files."
16
- end
17
- end
18
-
19
- def load_yml(file)
20
- yaml = YAML.load(file)
21
- build_grammar(yaml)
22
- end
23
-
24
- def load_json(file)
25
- json = JSON.parse(file)
26
- build_grammar(json)
27
- end
28
-
29
- private
30
-
31
- def build_grammar(rules)
32
- Calyx::Grammar.new do
33
- rules.each do |label, productions|
34
- rule(label, *productions)
35
- end
36
- end
37
- end
38
- end
39
- end
40
- end