calyx 0.20.0 → 0.21.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +33 -0
- data/.travis.yml +1 -1
- data/lib/calyx.rb +1 -0
- data/lib/calyx/grammar.rb +12 -0
- data/lib/calyx/mapping.rb +15 -0
- data/lib/calyx/modifiers.rb +10 -0
- data/lib/calyx/production/weighted_choices.rb +7 -0
- data/lib/calyx/registry.rb +2 -12
- data/lib/calyx/rule.rb +14 -4
- data/lib/calyx/version.rb +1 -1
- metadata +5 -69
- data/docs/404.html +0 -7
- data/docs/CNAME +0 -1
- data/docs/_config.yml +0 -27
- data/docs/_data/breadcrumbs.yml +0 -9
- data/docs/_data/docs.yml +0 -35
- data/docs/_data/examples.yml +0 -9
- data/docs/_includes/breadcrumbs.html +0 -36
- data/docs/_includes/contents.html +0 -12
- data/docs/_includes/icon-github.html +0 -4
- data/docs/_includes/icon-rubygems.html +0 -9
- data/docs/_includes/navbar.html +0 -24
- data/docs/_includes/pagebar.html +0 -12
- data/docs/_layouts/default.html +0 -13
- data/docs/_layouts/docs.html +0 -14
- data/docs/_layouts/home.html +0 -13
- data/docs/_layouts/page.html +0 -20
- data/docs/_posts/2017-09-14-welcome-to-jekyll.markdown +0 -25
- data/docs/_posts/2017-09-21-0.17.0-released.md +0 -10
- data/docs/_styles/card.scss +0 -7
- data/docs/_styles/colors.scss +0 -18
- data/docs/_styles/content.scss +0 -57
- data/docs/_styles/cta.scss +0 -25
- data/docs/_styles/grid.scss +0 -22
- data/docs/_styles/media.scss +0 -50
- data/docs/_styles/menu.scss +0 -54
- data/docs/_styles/modifiers.scss +0 -3
- data/docs/_styles/navbar.scss +0 -161
- data/docs/_styles/pagebar.scss +0 -32
- data/docs/_styles/reset.scss +0 -92
- data/docs/_styles/scale.scss +0 -23
- data/docs/_styles/spread.scss +0 -55
- data/docs/_styles/styleguide.scss +0 -52
- data/docs/_styles/syntax.scss +0 -84
- data/docs/_styles/typography.scss +0 -49
- data/docs/_styles/yard.scss +0 -36
- data/docs/api.html +0 -9662
- data/docs/assets/calyx-docs.css +0 -792
- data/docs/assets/calyx-flower-outline.svg +0 -202
- data/docs/assets/calyx-flower-reverse.svg +0 -202
- data/docs/assets/calyx-flower.svg +0 -202
- data/docs/assets/logo-small.png +0 -0
- data/docs/assets/logos/calyx-flower-1.svg +0 -22
- data/docs/assets/logos/calyx-flower-2.svg +0 -21
- data/docs/content/documentation.html +0 -20
- data/docs/content/examples.html +0 -12
- data/docs/content/examples/any-gradient.md +0 -32
- data/docs/content/examples/faker.md +0 -16
- data/docs/content/examples/tiny-woodland-bot.md +0 -24
- data/docs/content/guides/context.md +0 -45
- data/docs/content/guides/expressions.md +0 -175
- data/docs/content/guides/features.md +0 -50
- data/docs/content/guides/formats.md +0 -37
- data/docs/content/guides/installation.md +0 -51
- data/docs/content/guides/random.md +0 -100
- data/docs/content/guides/results.md +0 -62
- data/docs/content/index.html +0 -44
- data/docs/content/introduction.md +0 -23
- data/docs/content/introduction/concepts.md +0 -82
- data/docs/content/introduction/contributing.md +0 -43
- data/docs/content/introduction/tutorial.md +0 -129
- data/docs/content/styleguide.html +0 -71
- data/docs/docs.scss +0 -94
- data/docs/index.html +0 -12
- data/docs/package-lock.json +0 -1536
- data/docs/package.json +0 -16
@@ -1,51 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Installation
|
3
|
-
layout: docs
|
4
|
-
permalink: /guides/installation
|
5
|
-
---
|
6
|
-
|
7
|
-
## System requirements
|
8
|
-
|
9
|
-
The following prerequisites are needed to install Calyx:
|
10
|
-
|
11
|
-
- macOS, Windows, GNU/Linux or Unix
|
12
|
-
- Ruby 2.3 or above (MRI 2.3+, JRuby 9+, Rubinius 3+)
|
13
|
-
- RubyGems
|
14
|
-
|
15
|
-
Calyx has no external Gem dependencies.
|
16
|
-
|
17
|
-
## For command line use
|
18
|
-
|
19
|
-
Install the Calyx gem using the [RubyGems](https://rubygems.org) package manager:
|
20
|
-
|
21
|
-
```
|
22
|
-
gem install calyx
|
23
|
-
```
|
24
|
-
|
25
|
-
## For applications
|
26
|
-
|
27
|
-
Add the `calyx` dependency to your app’s `Gemfile`:
|
28
|
-
|
29
|
-
```ruby
|
30
|
-
gem 'calyx'
|
31
|
-
```
|
32
|
-
|
33
|
-
Run [Bundler](https://bundler.io/) to install it:
|
34
|
-
|
35
|
-
```
|
36
|
-
bundle install
|
37
|
-
```
|
38
|
-
|
39
|
-
## For local development
|
40
|
-
|
41
|
-
To contribute code back to Calyx or fork it in a new direction, clone the repo from GitHub:
|
42
|
-
|
43
|
-
```
|
44
|
-
git clone git@github.com:maetl/calyx
|
45
|
-
```
|
46
|
-
|
47
|
-
You can also download the latest build of the project as a ZIP archive:
|
48
|
-
|
49
|
-
```
|
50
|
-
wget https://github.com/maetl/calyx/archive/master.zip
|
51
|
-
```
|
@@ -1,100 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Random Sampling
|
4
|
-
permalink: /guides/random/
|
5
|
-
---
|
6
|
-
|
7
|
-
# Random Sampling
|
8
|
-
|
9
|
-
By default, the outcomes of generated rules are selected with Ruby’s built-in pseudorandom number generator (as seen in methods like `Kernel.rand` and `Array.sample`). To seed the random number generator, pass in an integer seed value as the first argument to the constructor:
|
10
|
-
|
11
|
-
```ruby
|
12
|
-
grammar = Calyx::Grammar.new(seed: 12345) do
|
13
|
-
# rules...
|
14
|
-
end
|
15
|
-
```
|
16
|
-
|
17
|
-
Alternatively, you can pass a preconfigured instance of Ruby’s stdlib `Random` class:
|
18
|
-
|
19
|
-
```ruby
|
20
|
-
random = Random.new(12345)
|
21
|
-
|
22
|
-
grammar = Calyx::Grammar.new(rng: random) do
|
23
|
-
# rules...
|
24
|
-
end
|
25
|
-
```
|
26
|
-
|
27
|
-
When a random seed isn’t supplied, `Time.new.to_i` is used as the default seed, which makes each run of the generator relatively unique.
|
28
|
-
|
29
|
-
## Weighted Choices
|
30
|
-
|
31
|
-
Choices can be weighted so that some rules have a greater probability of expanding than others.
|
32
|
-
|
33
|
-
Weights are defined by passing a hash instead of a list of rules where the keys are strings or symbols representing the grammar rules and the values are weights.
|
34
|
-
|
35
|
-
Weights can be represented as floats, integers or ranges.
|
36
|
-
|
37
|
-
- Floats must be in the interval 0..1 and the given weights for a production must sum to 1.
|
38
|
-
- Ranges must be contiguous and cover the entire interval from 1 to the maximum value of the largest range.
|
39
|
-
- Integers (Fixnums) will produce a distribution based on the sum of all given numbers, with each number being a fraction of that sum.
|
40
|
-
|
41
|
-
The following definitions produce an equivalent weighting of choices:
|
42
|
-
|
43
|
-
```ruby
|
44
|
-
Calyx::Grammar.new do
|
45
|
-
start 'heads' => 1, 'tails' => 1
|
46
|
-
end
|
47
|
-
|
48
|
-
Calyx::Grammar.new do
|
49
|
-
start 'heads' => 0.5, 'tails' => 0.5
|
50
|
-
end
|
51
|
-
|
52
|
-
Calyx::Grammar.new do
|
53
|
-
start 'heads' => 1..5, 'tails' => 6..10
|
54
|
-
end
|
55
|
-
|
56
|
-
Calyx::Grammar.new do
|
57
|
-
start 'heads' => 50, 'tails' => 50
|
58
|
-
end
|
59
|
-
```
|
60
|
-
|
61
|
-
There’s a lot of interesting things you can do with this. For example, you can model the triangular distribution produced by rolling 2d6:
|
62
|
-
|
63
|
-
```ruby
|
64
|
-
Calyx::Grammar.new do
|
65
|
-
start(
|
66
|
-
'2' => 1,
|
67
|
-
'3' => 2,
|
68
|
-
'4' => 3,
|
69
|
-
'5' => 4,
|
70
|
-
'6' => 5,
|
71
|
-
'7' => 6,
|
72
|
-
'8' => 5,
|
73
|
-
'9' => 4,
|
74
|
-
'10' => 3,
|
75
|
-
'11' => 2,
|
76
|
-
'12' => 1
|
77
|
-
)
|
78
|
-
end
|
79
|
-
```
|
80
|
-
|
81
|
-
Or reproduce Gary Gygax’s famous generation table from the original [Dungeon Master’s Guide](https://en.wikipedia.org/wiki/Dungeon_Master%27s_Guide#Advanced_Dungeons_.26_Dragons) (page 171):
|
82
|
-
|
83
|
-
```ruby
|
84
|
-
Calyx::Grammar.new do
|
85
|
-
start(
|
86
|
-
:empty => 0.6,
|
87
|
-
:monster => 0.1,
|
88
|
-
:monster_treasure => 0.15,
|
89
|
-
:special => 0.05,
|
90
|
-
:trick_trap => 0.05,
|
91
|
-
:treasure => 0.05
|
92
|
-
)
|
93
|
-
empty 'Empty'
|
94
|
-
monster 'Monster Only'
|
95
|
-
monster_treasure 'Monster and Treasure'
|
96
|
-
special 'Special'
|
97
|
-
trick_trap 'Trick/Trap.'
|
98
|
-
treasure 'Treasure'
|
99
|
-
end
|
100
|
-
```
|
@@ -1,62 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: default
|
3
|
-
title: Results
|
4
|
-
permalink: /guides/results/
|
5
|
-
---
|
6
|
-
|
7
|
-
# Generating Results
|
8
|
-
|
9
|
-
## Result objects
|
10
|
-
|
11
|
-
Results are generated by calling `#generate` on the grammar instance. Results are immutable objects representing the unique randomized output from evaluating the grammar.
|
12
|
-
|
13
|
-
```ruby
|
14
|
-
grammar = Calyx::Grammar.new do
|
15
|
-
start "Where is the green sheep?"
|
16
|
-
end
|
17
|
-
|
18
|
-
result = grammar.generate
|
19
|
-
# => Calyx::Result
|
20
|
-
```
|
21
|
-
|
22
|
-
The core accessor methods on the result are:
|
23
|
-
|
24
|
-
- `#text`
|
25
|
-
- `#tree`
|
26
|
-
|
27
|
-
Results can only be deterministically generated by seeding the random number generator.
|
28
|
-
|
29
|
-
## Accessing the flattened text string
|
30
|
-
|
31
|
-
The `#text` method of the result provides access to the flattened text string generated by the grammar.
|
32
|
-
|
33
|
-
```ruby
|
34
|
-
result = grammar.generate
|
35
|
-
|
36
|
-
result.text
|
37
|
-
# => "Where is the green sheep?"
|
38
|
-
```
|
39
|
-
|
40
|
-
`#text` is aliased to the `#to_s` method so result objects can be concatenated and interpolated within other strings directly.
|
41
|
-
|
42
|
-
```ruby
|
43
|
-
result = grammar.generate
|
44
|
-
|
45
|
-
templated = "Q: #{result}"
|
46
|
-
# => "Q: Where is the green sheep?"
|
47
|
-
```
|
48
|
-
|
49
|
-
## Accessing the generated tree
|
50
|
-
|
51
|
-
The `#tree` method of the result provides access to the raw generated tree structure without being flattened into a string.
|
52
|
-
|
53
|
-
The tree is encoded as an array of nested arrays, with the leading symbols labeling the choices and rules selected, and the trailing terminal leaves encoding string values.
|
54
|
-
|
55
|
-
This is related to the concept of [s-expressions](https://en.wikipedia.org/wiki/S-expression). It’s a fairly speculative feature at this stage, but it leads to some interesting possibilities.
|
56
|
-
|
57
|
-
```ruby
|
58
|
-
result = grammar.generate
|
59
|
-
|
60
|
-
result.tree
|
61
|
-
# => [:start, [:choice, [:concat, [[:atom, "Where is the green sheep?"]]]]]
|
62
|
-
```
|
data/docs/content/index.html
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Calyx
|
3
|
-
layout: home
|
4
|
-
permanlink: /
|
5
|
-
---
|
6
|
-
|
7
|
-
{% include navbar.html %}
|
8
|
-
|
9
|
-
<div class="spread spread-hero">
|
10
|
-
<figure class="identity">
|
11
|
-
<img src="/assets/logos/calyx-flower-2.svg" width="80%" height="80%">
|
12
|
-
</figure>
|
13
|
-
<div class="lede">
|
14
|
-
<h2>Create writing machines with generative grammars</h2>
|
15
|
-
|
16
|
-
<ul class="cta-list">
|
17
|
-
<li><a class="cta-button" href="#">Download</a></li>
|
18
|
-
<li><a class="cta-button" href="#">Learn more</a></li>
|
19
|
-
</ul>
|
20
|
-
</div>
|
21
|
-
</div>
|
22
|
-
|
23
|
-
<div class="spread spread-intro">
|
24
|
-
<p>Calyx is a simple and powerful tool for creating writing machines using the Ruby programming language.</p>
|
25
|
-
</div>
|
26
|
-
|
27
|
-
<div class="content">
|
28
|
-
<h1>Calyx</h1>
|
29
|
-
<p>Calyx provides a simple and powerful generative grammar format for creating writing machines using the Ruby programming language.</p>
|
30
|
-
<p>Although the primary use case is procedurally generating text, Calyx grammars can be used to make anything where the output format is a string.</p>
|
31
|
-
<p>Calyx provides a simple Ruby API for creating writing machines of all shapes and sizes using generative grammars.</p>
|
32
|
-
<ul>
|
33
|
-
<li><a href="https://github.com/maetl/calyx">Source code on GitHub</a></li>
|
34
|
-
<li><a href="https://rubygems.org/gems/calyx">Package on Rubygems</a></li>
|
35
|
-
</ul>
|
36
|
-
</div>
|
37
|
-
|
38
|
-
<div class="features">
|
39
|
-
<p>An intuitive syntax for constructing text generators in native Ruby or JSON.</p>
|
40
|
-
|
41
|
-
<p>Randomly select desired output from multiple choices.</p>
|
42
|
-
|
43
|
-
<p>Use weighted probabilities to shape the odds of choices occurring.</p>
|
44
|
-
</div>
|
@@ -1,23 +0,0 @@
|
|
1
|
-
---
|
2
|
-
layout: docs
|
3
|
-
title: Introduction
|
4
|
-
permalink: /introduction/
|
5
|
-
---
|
6
|
-
|
7
|
-
## What is Calyx?
|
8
|
-
|
9
|
-
Calyx is a simple and powerful software library for creating writing machines using the Ruby programming language. It provides tools for producing randomized sequences of text using a syntax inspired by generative grammars.
|
10
|
-
|
11
|
-
Its primary affordances are for creating bots and weird combinatorial prose and poetry but you can use it to generate anything that has a textual or tree-based representation, including SVG graphics, narrative graphs and fake data schemas.
|
12
|
-
|
13
|
-
## Why grammars?
|
14
|
-
|
15
|
-
There are many useful and interesting methods for generative writing. The grammar-based approach is popular, widely studied and practiced, and easy to get started with.
|
16
|
-
|
17
|
-
Grammars offer direct authorial control over the fragments that combine to produce an output text. This involves more effort and structure than other more random approaches, but leads to carefully crafted and expressive results which still have a capacity to surprise, delight, and confound—as any good text generation method should.
|
18
|
-
|
19
|
-
## Getting Started
|
20
|
-
|
21
|
-
Get started with a [simple tutorial](/introduction/tutorial/) or learn more about the [underlying concepts](/introduction/concepts/). If you’re new to Ruby and generative art in general, the [documentation for beginners](/introduction/beginners/) is a good place to start.
|
22
|
-
|
23
|
-
Use the [guides](/docs/guides/) to learn how to use the various features and capabilities of the library. For more direct and structured information, the [reference](/docs/reference/) contains a full breakdown of everything that Calyx supports.
|
@@ -1,82 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Key Concepts
|
3
|
-
layout: docs
|
4
|
-
permalink: /introduction/concepts/
|
5
|
-
---
|
6
|
-
|
7
|
-
## What are grammars?
|
8
|
-
|
9
|
-
A grammar is a set of interconnected rules that describe the syntax of a language. The grammar rules describe how to form strings in that language based on an alphabet.
|
10
|
-
|
11
|
-
## A dash of theory
|
12
|
-
|
13
|
-
Traditionally, generative grammars are often described as recognizers. Given a particular string as input, the grammar defines whether or not that string is recognized.
|
14
|
-
|
15
|
-
For example, let’s imagine what a pseudocode grammar representing whole numbers greater than zero might look like.
|
16
|
-
|
17
|
-
```
|
18
|
-
start := leading_digit *digit
|
19
|
-
leading_digit := 1..9
|
20
|
-
digit := 0..9
|
21
|
-
```
|
22
|
-
|
23
|
-
If we could turn this pseudocode grammar into a recognizer function and run it on a range of possible strings, we’d see the following results.
|
24
|
-
|
25
|
-
```ruby
|
26
|
-
grammar.parse("1") # => true
|
27
|
-
grammar.parse("2") # => true
|
28
|
-
grammar.parse("99") # => true
|
29
|
-
grammar.parse("111") # => true
|
30
|
-
grammar.parse("134534") # => true
|
31
|
-
grammar.parse("0") # => false
|
32
|
-
grammar.parse("055") # => false
|
33
|
-
grammar.parse("abc") # => false
|
34
|
-
grammar.parse("1.5") # => false
|
35
|
-
```
|
36
|
-
|
37
|
-
How does it work?
|
38
|
-
|
39
|
-
The grammar here is made up of ‘production rules’, which in turn are made up of named symbols called ‘nonterminals’ and literal patterns called ‘terminals’ which match a range of possible strings.
|
40
|
-
|
41
|
-
In this case, `start`, `leading_digit` and `digit` are nonterminals whereas `1..9` and `0..9` are terminals. By convention, `*` means ‘zero or more’, which specifies that the production can match repeating characters over and over until an unmatched character is found (formally, this is known as the [Kleene star](https://en.wikipedia.org/wiki/Kleene_star)).
|
42
|
-
|
43
|
-
To recognize a string with the grammar, we start with a left hand side nonterminal (by convention, this is known as the start symbol, often named `start`) and substitute it with its right hand side production. We then do the same for the next set of nonterminals we find in the production, until we bottom out at a set of terminals matching the literal string.
|
44
|
-
|
45
|
-
If we walk through
|
46
|
-
|
47
|
-
```
|
48
|
-
grammar.parse("1")
|
49
|
-
```
|
50
|
-
|
51
|
-
1. Replace `start` with `leading_digit` then `*digit`
|
52
|
-
2. `leading_digit` is a terminal `1..9`, so check that the first character matches
|
53
|
-
3. `*digit`
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
If you’re familiar with regular expressions, you’ll notice that this grammar seems to do exactly the same thing as the following regular expression.
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
/^[1-9][0-9]*$/
|
61
|
-
```
|
62
|
-
|
63
|
-
Remarkably, this isn’t a coincidence or example of TMTOWTDI. It turns out that there’s a deep symmetry between grammars and regular expressions. Every regular grammar can be transformed into an equivalent regular expression and vice versa.
|
64
|
-
|
65
|
-
```
|
66
|
-
Number := Zero | Integer | Decimal | Real
|
67
|
-
Integer := LeadingDigit *Digit
|
68
|
-
LeadingDigit := [1-9]
|
69
|
-
Digit := [0-9]
|
70
|
-
Decimal := Integer "." *Digit
|
71
|
-
Real := Integer "/" Integer
|
72
|
-
Zero := "0"
|
73
|
-
```
|
74
|
-
|
75
|
-
The following sequences are recognised as valid by the number grammar:
|
76
|
-
|
77
|
-
- `1`
|
78
|
-
- `23.424`
|
79
|
-
- `30000`
|
80
|
-
- `1/7`
|
81
|
-
|
82
|
-
Template expansion grammars
|
@@ -1,43 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Contributing to Calyx
|
3
|
-
layout: docs
|
4
|
-
permalink: /introduction/contributing/
|
5
|
-
---
|
6
|
-
|
7
|
-
# Contributing to Calyx
|
8
|
-
|
9
|
-
Calyx is an open source project and contributions are welcome.
|
10
|
-
|
11
|
-
## General Contributions
|
12
|
-
|
13
|
-
The best way to contribute is to use the Gem. Install it on a local project and try things out. Does it work? Does it do what you expect? Is there anything missing?
|
14
|
-
|
15
|
-
It’s really helpful to contribute to discussion on open issues, reporting bugs or suggest new features. Any feedback and criticism is received with gratitude.
|
16
|
-
|
17
|
-
## Code Contributions
|
18
|
-
|
19
|
-
Changes that fix bugs and improve test coverage will generally be merged on-the-spot. Larger changes that introduce new features should harmonise with the vision, goals and style of the project. If in doubt, just ask in advance.
|
20
|
-
|
21
|
-
### Submitting Changes
|
22
|
-
|
23
|
-
Changes to the source code and documentation should be submitted as a pull request on GitHub, corresponding to the following process:
|
24
|
-
|
25
|
-
- Fork the repo and make a new branch for your changes
|
26
|
-
- Submit your branch as a pull request against the master branch
|
27
|
-
|
28
|
-
If any aspects of your changes need further explanation, use the pull request description to provide further detail and context (including code samples as necessary).
|
29
|
-
|
30
|
-
Please don’t bump the version as part of your pull request (this happens separately).
|
31
|
-
|
32
|
-
### Pull Request Checklist
|
33
|
-
|
34
|
-
- Extraneous and trivial small commits should be squashed into larger descriptive commits
|
35
|
-
- Commits should include concise and clear messages using standard formatting conventions
|
36
|
-
- The test suite must be passing
|
37
|
-
- Newly introduced code branches should be covered by tests
|
38
|
-
-- Introduce new tests if existing tests don’t support your changes
|
39
|
-
- Changes to method signatures and class organisation should be annotated by doc comments
|
40
|
-
|
41
|
-
## Code of Conduct
|
42
|
-
|
43
|
-
Please note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.
|
@@ -1,129 +0,0 @@
|
|
1
|
-
---
|
2
|
-
title: Tutorial
|
3
|
-
layout: docs
|
4
|
-
permalink: /introduction/tutorial
|
5
|
-
---
|
6
|
-
|
7
|
-
## Objective
|
8
|
-
|
9
|
-
This tutorial introduces Calyx with a basic ‘hello world’ example. Following these steps will help you get Calyx up and running and provide you with a code skeleton to start adding more interesting and creative things.
|
10
|
-
|
11
|
-
## Initial setup
|
12
|
-
|
13
|
-
Before getting started, you’ll need to install Calyx from RubyGems and have it available in your local dev environment:
|
14
|
-
|
15
|
-
```
|
16
|
-
gem install calyx
|
17
|
-
```
|
18
|
-
|
19
|
-
If you’re not sure how to do this yet, there’s more information about setting up your Ruby environment in the [resources for beginners](/introduction/beginners/). The [installation guide](/docs/guide/installation/) contains further details about prerequisites and how to download and install the Gem.
|
20
|
-
|
21
|
-
## Getting started
|
22
|
-
|
23
|
-
Create a file named `hello.rb` and add the following contents:
|
24
|
-
|
25
|
-
```ruby
|
26
|
-
require "calyx"
|
27
|
-
|
28
|
-
hello = Calyx::Grammar.new do
|
29
|
-
start "Hello world!"
|
30
|
-
end
|
31
|
-
```
|
32
|
-
|
33
|
-
The first line imports the Calyx library and the lines following use the `Calyx::Grammar` class to define the rules for the generated text, in this case just ‘Hello world!’.
|
34
|
-
|
35
|
-
To generate the text result, call the `#generate` method on the grammar object. Add this to the bottom of the `hello.rb` file:
|
36
|
-
|
37
|
-
```ruby
|
38
|
-
puts hello.generate
|
39
|
-
```
|
40
|
-
|
41
|
-
Run it on the command line by typing `ruby hello.rb`. You should see the following result:
|
42
|
-
|
43
|
-
```
|
44
|
-
Hello world!
|
45
|
-
```
|
46
|
-
|
47
|
-
## Adding random choices
|
48
|
-
|
49
|
-
Obviously, this hardcoded sentence isn’t very interesting by itself. To add variety to the text, rules can be defined with multiple choices to pick from:
|
50
|
-
|
51
|
-
```ruby
|
52
|
-
hello = Calyx::Grammar.new do
|
53
|
-
start 'Hello world!', 'Hi world!', 'Hey world!'
|
54
|
-
end
|
55
|
-
```
|
56
|
-
|
57
|
-
Each time `#generate` runs, Calyx evaluates the grammar and randomly selects a single choice from the list of possible choices. So if we run the grammar three times, we might see three different results:
|
58
|
-
|
59
|
-
```ruby
|
60
|
-
hello.generate
|
61
|
-
# => Hi world!
|
62
|
-
|
63
|
-
hello.generate
|
64
|
-
# => Hello world!
|
65
|
-
|
66
|
-
hello.generate
|
67
|
-
# => Yo world!
|
68
|
-
```
|
69
|
-
|
70
|
-
## Nesting rules inside rules
|
71
|
-
|
72
|
-
When you embed the name of a rule in curly brackets inside a text fragment, Calyx will expand the embedded rule and replace it with generated output each time the grammar runs.
|
73
|
-
|
74
|
-
The following example nests the `greeting` rule within the `start` rule:
|
75
|
-
|
76
|
-
```ruby
|
77
|
-
hello = Calyx::Grammar.new do
|
78
|
-
start '{greeting} world!'
|
79
|
-
greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
80
|
-
end
|
81
|
-
```
|
82
|
-
|
83
|
-
This generates the exact same text as before, but listing the greeting words on their own is more flexible and eliminates the need to write each variation of the phrase out in full.
|
84
|
-
|
85
|
-
This process of starting with a larger fragment of text and breaking it up into smaller phrases and single words is something you’ll do a lot when writing larger and more detailed grammars.
|
86
|
-
|
87
|
-
## Using nesting to shape the text
|
88
|
-
|
89
|
-
Rules can be arbitrarily nested and connected to generate larger and more complex texts. The way the rules branch out is going to define the shape and ‘flavor’ of the text.
|
90
|
-
|
91
|
-
For example, to create more exaggerated variations of the phrase, we can branch out to pick from a list of happy adjectives or a list of sad adjectives:
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
hello = Calyx::Grammar.new do
|
95
|
-
start '{greeting} {world_phrase}.'
|
96
|
-
greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
97
|
-
world_phrase '{happy_adj} world', '{sad_adj} world', 'world'
|
98
|
-
happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
|
99
|
-
sad_adj 'cruel', 'miserable'
|
100
|
-
end
|
101
|
-
```
|
102
|
-
|
103
|
-
Nesting and branching can be manipulated to balance consistency with novelty. The exact same text fragments can be combined in a variety of ways to produce strikingly different resulting texts.
|
104
|
-
|
105
|
-
The following grammar branches out at the top level, with `happy_phrase` and `sad_phrase` being generated from completely separate trees that don’t overlap:
|
106
|
-
|
107
|
-
```ruby
|
108
|
-
hello = Calyx::Grammar.new do
|
109
|
-
start '{happy_phrase} world.', '{sad_phrase} world.'
|
110
|
-
happy_phrase '{happy_greeting} {happy_adj}'
|
111
|
-
happy_greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
112
|
-
happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
|
113
|
-
sad_phrase '{sad_greeting} {sad_adj}'
|
114
|
-
sad_greeting 'Goodbye', 'So long', 'Farewell'
|
115
|
-
sad_adj 'cruel', 'miserable'
|
116
|
-
end
|
117
|
-
```
|
118
|
-
|
119
|
-
Whereas this variation of the grammar uses the same content but generates everything from a single branch, resulting in a word salad with happy and sad fragments mashed together:
|
120
|
-
|
121
|
-
```ruby
|
122
|
-
hello = Calyx::Grammar.new do
|
123
|
-
start '{greeting} {adj} world.'
|
124
|
-
greeting 'Hello', 'Hi', 'Hey', 'Yo', 'Goodbye', 'So long', 'Farewell'
|
125
|
-
adj 'wonderful', 'amazing', 'bright', 'beautiful', 'cruel', 'miserable'
|
126
|
-
end
|
127
|
-
```
|
128
|
-
|
129
|
-
That’s really all you need to know to get started.
|