calyx 0.12.1 → 0.13.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: 5ef3b96315fd2ed6eb9352e21a11a4fe650c06cb
4
- data.tar.gz: d5c9cb27ee6626cdae2fe30ceef5c6bdb369e260
3
+ metadata.gz: b083064b7b93a5747ec7833b4e3ca46394f8f45b
4
+ data.tar.gz: d87854cd9b134257987fef4febfae492a7665d3d
5
5
  SHA512:
6
- metadata.gz: 97709bec536e1f1ea619ec7f882184b4e4ec45c32b29371cd1c2ba30a88bbbcb0c637cce3d52ac5ebc6c37d642c8c51ff9fb47785a8c9775ffee0490d91bcdcd
7
- data.tar.gz: 927d4e0ee0380e58299b97f6cffaae351575fbd15fa99e446c48c7a16dff9b90055625460862a533a02476748809aeb9840ce2b872549d0917f19b618b7ccc46
6
+ metadata.gz: 267238c9ed8dedc16de8096c53fc362d16f77a25f60ac5f0eb475c304740a44a1530fa236a9cb30f2175da7e39b20729555376b9c18af5118ea83f01711e86ef
7
+ data.tar.gz: 1dabb4bc4cd57d42e2887039ced705b9e10c6347e22714414103a737e52c4096ac378db9a6320a6902ab5036691d341a68c13b781bdc8a10062c0ddfd2ef31e4
data/.travis.yml CHANGED
@@ -2,9 +2,9 @@ language: ruby
2
2
  rvm:
3
3
  - 2.1
4
4
  - 2.2
5
- - 2.3.0
6
- - rbx-2
5
+ - 2.3.1
6
+ - 2.4.0-preview1
7
+ - ruby-head
7
8
  - jruby-9
8
- - jruby-head
9
9
  before_install: gem install bundler -v 1.10.6
10
10
  script: bundle exec rspec
data/README.md CHANGED
@@ -397,7 +397,7 @@ end
397
397
 
398
398
  Rule expansions can be ‘memoized’ so that multiple references to the same rule return the same value. This is useful for picking a noun from a list and reusing it in multiple places within a text.
399
399
 
400
- The `@` symbol is used to mark memoized rules. This evaluates the rule and stores it in memory the first time it’s referenced. All subsequent references to the memoized rule use the same stored value.
400
+ The `@` sigil is used to mark memoized rules. This evaluates the rule and stores it in memory the first time it’s referenced. All subsequent references to the memoized rule use the same stored value.
401
401
 
402
402
  ```ruby
403
403
  # Without memoization
@@ -425,6 +425,24 @@ end
425
425
 
426
426
  Note that the memoization symbol can only be used on the right hand side of a production rule.
427
427
 
428
+ ### Unique Rules
429
+
430
+ Rule expansions can be marked as ‘unique’, meaning that multiple references to the same rule always return a different value. This is useful for situations where the same result appearing twice would appear awkward and messy.
431
+
432
+ Unique rules are marked by the `$` sigil.
433
+
434
+ ```ruby
435
+ grammar = Calyx::Grammar.new do
436
+ start "{$medal}, {$medal}, {$medal}"
437
+ medal 'Gold', 'Silver', 'Bronze'
438
+ end
439
+
440
+ grammar.generate
441
+ # => Silver, Bronze, Gold
442
+ ```
443
+
444
+ **Note: this is a new and experimental feature and the API may change as kinks are ironed out from testing and exploration.**
445
+
428
446
  ### Dynamically Constructing Rules
429
447
 
430
448
  Template expansions can be dynamically constructed at runtime by passing a context map of rules to the `#generate` method:
@@ -17,6 +17,8 @@ module Calyx
17
17
  elsif choice.is_a?(Symbol)
18
18
  if choice[0] == Memo::SIGIL
19
19
  Memo.new(choice, registry)
20
+ elsif choice[0] == Unique::SIGIL
21
+ Unique.new(choice, registry)
20
22
  else
21
23
  NonTerminal.new(choice, registry)
22
24
  end
@@ -3,7 +3,7 @@ module Calyx
3
3
  # A type of production rule representing a string combining both template
4
4
  # substitutions and raw content.
5
5
  class Concat
6
- EXPRESSION = /(\{[A-Za-z0-9_@\.]+\})/.freeze
6
+ EXPRESSION = /(\{[A-Za-z0-9_@$\.]+\})/.freeze
7
7
  START_TOKEN = '{'.freeze
8
8
  END_TOKEN = '}'.freeze
9
9
  DEREF_TOKEN = '.'.freeze
@@ -22,6 +22,8 @@ module Calyx
22
22
  head, *tail = atom.slice(1, atom.length-2).split(DEREF_TOKEN)
23
23
  if head[0] == Memo::SIGIL
24
24
  rule = Memo.new(head, registry)
25
+ elsif head[0] == Unique::SIGIL
26
+ rule = Unique.new(head, registry)
25
27
  else
26
28
  rule = NonTerminal.new(head, registry)
27
29
  end
@@ -0,0 +1,32 @@
1
+ module Calyx
2
+ module Production
3
+ # A type of production rule representing a unique substitution which only
4
+ # returns values that have not previously been selected. The probability
5
+ # that a given rule will be selected increases as more selections are made
6
+ # and the list grows smaller.
7
+ #
8
+ # TODO: handle wraparound
9
+ class Unique
10
+ SIGIL = '$'.freeze
11
+
12
+ # Construct a unique rule, given the symbol to lookup and the registry
13
+ # to look it up in.
14
+ #
15
+ # @param [Symbol] symbol
16
+ # @param [Calyx::Registry] registry
17
+ def initialize(symbol, registry)
18
+ @symbol = symbol.slice(1, symbol.length-1).to_sym
19
+ @registry = registry
20
+ end
21
+
22
+ # Evaluate the unique rule, using the registry to handle the expansion
23
+ # and keep track of previous selections.
24
+ #
25
+ # @param [Random] random
26
+ # @return [Array]
27
+ def evaluate(random)
28
+ [@symbol, @registry.unique_expansion(@symbol)]
29
+ end
30
+ end
31
+ end
32
+ end
@@ -81,6 +81,26 @@ module Calyx
81
81
  memos[symbol] ||= expand(symbol).evaluate(@random)
82
82
  end
83
83
 
84
+ # Expands a unique rule symbol by evaluating it and checking that it hasn't
85
+ # previously been selected.
86
+ #
87
+ # @param [Symbol] symbol
88
+ def unique_expansion(symbol)
89
+ pending = true
90
+ uniques[symbol] = [] if uniques[symbol].nil?
91
+
92
+ while pending
93
+ result = expand(symbol).evaluate(@random)
94
+
95
+ unless uniques[symbol].include?(result)
96
+ uniques[symbol] << result
97
+ pending = false
98
+ end
99
+ end
100
+
101
+ result
102
+ end
103
+
84
104
  # Merges the given registry instance with the target registry.
85
105
  #
86
106
  # This is only needed at compile time, so that child classes can easily
@@ -91,8 +111,6 @@ module Calyx
91
111
  @rules = rules.merge(registry.rules)
92
112
  end
93
113
 
94
-
95
-
96
114
  # Evaluates the grammar defined in this registry, combining it with rules
97
115
  # from the passed in context.
98
116
  #
@@ -128,12 +146,13 @@ module Calyx
128
146
 
129
147
  private
130
148
 
131
- attr_reader :random, :memos, :context
149
+ attr_reader :random, :memos, :context, :uniques
132
150
 
133
151
  def reset_evaluation_context(random)
134
152
  @random = random
135
153
  @context = {}
136
154
  @memos = {}
155
+ @uniques = {}
137
156
  end
138
157
 
139
158
  def construct_mapping(pairs)
data/lib/calyx/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Calyx
2
- VERSION = '0.12.1'.freeze
2
+ VERSION = '0.13.0'.freeze
3
3
  end
data/lib/calyx.rb CHANGED
@@ -5,6 +5,7 @@ require 'calyx/format'
5
5
  require 'calyx/registry'
6
6
  require 'calyx/modifiers'
7
7
  require 'calyx/production/memo'
8
+ require 'calyx/production/unique'
8
9
  require 'calyx/production/choices'
9
10
  require 'calyx/production/concat'
10
11
  require 'calyx/production/expression'
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.12.1
4
+ version: 0.13.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-10-03 00:00:00.000000000 Z
11
+ date: 2017-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -82,6 +82,7 @@ files:
82
82
  - lib/calyx/production/memo.rb
83
83
  - lib/calyx/production/non_terminal.rb
84
84
  - lib/calyx/production/terminal.rb
85
+ - lib/calyx/production/unique.rb
85
86
  - lib/calyx/production/weighted_choices.rb
86
87
  - lib/calyx/registry.rb
87
88
  - lib/calyx/version.rb