calyx 0.10.4 → 0.11.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
  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