calyx 0.11.0 → 0.11.1
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 +4 -4
- data/README.md +75 -31
- data/examples/faker.rb +7 -0
- data/examples/faker.yml +42 -0
- data/lib/calyx/errors.rb +51 -4
- data/lib/calyx/format.rb +22 -7
- data/lib/calyx/grammar.rb +73 -2
- data/lib/calyx/modifiers.rb +11 -4
- data/lib/calyx/production/choices.rb +13 -0
- data/lib/calyx/production/concat.rb +17 -0
- data/lib/calyx/production/expression.rb +11 -0
- data/lib/calyx/production/memo.rb +10 -0
- data/lib/calyx/production/non_terminal.rb +10 -0
- data/lib/calyx/production/terminal.rb +7 -0
- data/lib/calyx/production/weighted_choices.rb +19 -1
- data/lib/calyx/registry.rb +50 -3
- data/lib/calyx/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75811b39e9ca016645eb82dea083ff50612f8e2b
|
4
|
+
data.tar.gz: af905efd81c6b0e679e2ed333f571fdad65ee8a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97a47ba2a0dcf0d658641ba1f67b3237731132ca0500c92053b86f54a60b2eba7f3181daef54c43f94d40c725915c39a2ae2898d6a639a0399f3910a4d01116f
|
7
|
+
data.tar.gz: 57341f9c8428917d56b33dedd219dd904bca3252b9f2a7d240bcab1a050f8209f7b61ab26d9402b69f029be53d7ffcfcd29b8342777e2de62733e408607af872
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ gem 'calyx'
|
|
21
21
|
|
22
22
|
## Usage
|
23
23
|
|
24
|
-
Require the library and inherit from `Calyx::Grammar` to construct a set of rules to generate a text.
|
24
|
+
Require the library and inherit from `Calyx::Grammar` to construct a set of rules to generate a text.
|
25
25
|
|
26
26
|
```ruby
|
27
27
|
require 'calyx'
|
@@ -39,12 +39,12 @@ hello.generate
|
|
39
39
|
# > "Hello world."
|
40
40
|
```
|
41
41
|
|
42
|
-
Obviously, this hardcoded sentence isn’t very interesting by itself. Possible variations can be added to the text
|
42
|
+
Obviously, this hardcoded sentence isn’t very interesting by itself. Possible variations can be added to the text by adding additional rules which provide a named set of text strings. The rule delimiter syntax (`{}`) can be used to substitute the generated content of other rules.
|
43
43
|
|
44
44
|
```ruby
|
45
45
|
class HelloWorld < Calyx::Grammar
|
46
46
|
start '{greeting} world.'
|
47
|
-
|
47
|
+
greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
48
48
|
end
|
49
49
|
```
|
50
50
|
|
@@ -63,6 +63,17 @@ hello.generate
|
|
63
63
|
# > "Yo world."
|
64
64
|
```
|
65
65
|
|
66
|
+
By convention, the `start` rule specifies the default starting point for generating the final text. You can start from any other named rule by passing it explicitly to the generate method.
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
class HelloWorld < Calyx::Grammar
|
70
|
+
hello 'Hello world.'
|
71
|
+
end
|
72
|
+
|
73
|
+
hello = HelloWorld.new
|
74
|
+
hello.generate(:hello)
|
75
|
+
```
|
76
|
+
|
66
77
|
### Block Constructors
|
67
78
|
|
68
79
|
As an alternative to subclassing, you can also construct rules unique to an instance by passing a block when initializing the class:
|
@@ -70,12 +81,44 @@ As an alternative to subclassing, you can also construct rules unique to an inst
|
|
70
81
|
```ruby
|
71
82
|
hello = Calyx::Grammar.new do
|
72
83
|
start '{greeting} world.'
|
73
|
-
|
84
|
+
greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
74
85
|
end
|
75
86
|
|
76
87
|
hello.generate
|
77
88
|
```
|
78
89
|
|
90
|
+
### External File Formats
|
91
|
+
|
92
|
+
In addition to defining grammars in pure Ruby, you can load them from external JSON and YAML files:
|
93
|
+
|
94
|
+
```ruby
|
95
|
+
hello = Calyx::Grammar.load('hello.yml')
|
96
|
+
hello.generate
|
97
|
+
```
|
98
|
+
|
99
|
+
The format requires a flat map with keys representing the left-hand side named symbols and the values representing the right hand side substitution rules.
|
100
|
+
|
101
|
+
In JSON:
|
102
|
+
|
103
|
+
```json
|
104
|
+
{
|
105
|
+
"start": "{greeting} world.",
|
106
|
+
"greeting": ["Hello", "Hi", "Hey", "Yo"]
|
107
|
+
}
|
108
|
+
```
|
109
|
+
|
110
|
+
In YAML:
|
111
|
+
|
112
|
+
```yaml
|
113
|
+
---
|
114
|
+
start: "{greeting} world."
|
115
|
+
greeting:
|
116
|
+
- Hello
|
117
|
+
- Hi
|
118
|
+
- Hey
|
119
|
+
- Yo
|
120
|
+
```
|
121
|
+
|
79
122
|
### Nesting and Substitution
|
80
123
|
|
81
124
|
Rules are recursive. They can be arbitrarily nested and connected to generate larger and more complex texts.
|
@@ -83,10 +126,10 @@ Rules are recursive. They can be arbitrarily nested and connected to generate la
|
|
83
126
|
```ruby
|
84
127
|
class HelloWorld < Calyx::Grammar
|
85
128
|
start '{greeting} {world_phrase}.'
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
129
|
+
greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
130
|
+
world_phrase '{happy_adj} world', '{sad_adj} world', 'world'
|
131
|
+
happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
|
132
|
+
sad_adj 'cruel', 'miserable'
|
90
133
|
end
|
91
134
|
```
|
92
135
|
|
@@ -96,18 +139,18 @@ Nesting and hierarchy can be manipulated to balance consistency with novelty. Th
|
|
96
139
|
module HelloWorld
|
97
140
|
class Sentiment < Calyx::Grammar
|
98
141
|
start '{happy_phrase}', '{sad_phrase}'
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
142
|
+
happy_phrase '{happy_greeting} {happy_adj} world.'
|
143
|
+
happy_greeting 'Hello', 'Hi', 'Hey', 'Yo'
|
144
|
+
happy_adj 'wonderful', 'amazing', 'bright', 'beautiful'
|
145
|
+
sad_phrase '{sad_greeting} {sad_adj} world.'
|
146
|
+
sad_greeting 'Goodbye', 'So long', 'Farewell'
|
147
|
+
sad_adj 'cruel', 'miserable'
|
105
148
|
end
|
106
149
|
|
107
150
|
class Mixed < Calyx::Grammar
|
108
151
|
start '{greeting} {adj} world.'
|
109
|
-
|
110
|
-
|
152
|
+
greeting 'Hello', 'Hi', 'Hey', 'Yo', 'Goodbye', 'So long', 'Farewell'
|
153
|
+
adj 'wonderful', 'amazing', 'bright', 'beautiful', 'cruel', 'miserable'
|
111
154
|
end
|
112
155
|
end
|
113
156
|
```
|
@@ -147,7 +190,7 @@ class Roll2D6 < Calyx::Grammar
|
|
147
190
|
end
|
148
191
|
```
|
149
192
|
|
150
|
-
Or reproduce Gary Gygax’s famous generation table from the original Dungeon Master’s Guide (page 171):
|
193
|
+
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):
|
151
194
|
|
152
195
|
```ruby
|
153
196
|
class ChamberOrRoomContents < Calyx::Grammar
|
@@ -160,12 +203,12 @@ class ChamberOrRoomContents < Calyx::Grammar
|
|
160
203
|
[:treasure, 0.05]
|
161
204
|
)
|
162
205
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
206
|
+
empty 'Empty'
|
207
|
+
monster 'Monster Only'
|
208
|
+
monster_treasure 'Monster and Treasure'
|
209
|
+
special 'Special'
|
210
|
+
trick_trap 'Trick/Trap.'
|
211
|
+
treasure 'Treasure'
|
169
212
|
end
|
170
213
|
```
|
171
214
|
|
@@ -176,8 +219,8 @@ Basic rule substitution uses single curly brackets as delimiters for template ex
|
|
176
219
|
```ruby
|
177
220
|
class Fruit < Calyx::Grammar
|
178
221
|
start '{colour} {fruit}'
|
179
|
-
|
180
|
-
|
222
|
+
colour 'red', 'green', 'yellow'
|
223
|
+
fruit 'apple', 'pear', 'tomato'
|
181
224
|
end
|
182
225
|
```
|
183
226
|
|
@@ -188,7 +231,7 @@ Dot-notation is supported in template expressions, allowing you to call any avai
|
|
188
231
|
```ruby
|
189
232
|
class Greeting < Calyx::Grammar
|
190
233
|
start '{hello.capitalize} there.', 'Why, {hello} there.'
|
191
|
-
|
234
|
+
hello 'hello'
|
192
235
|
end
|
193
236
|
|
194
237
|
# => "Hello there."
|
@@ -206,8 +249,9 @@ class Greeting < Calyx::Grammar
|
|
206
249
|
filter :shoutycaps do |input|
|
207
250
|
input.upcase
|
208
251
|
end
|
252
|
+
|
209
253
|
start '{hello.shoutycaps} there.', 'Why, {hello} there.'
|
210
|
-
|
254
|
+
hello 'hello'
|
211
255
|
end
|
212
256
|
|
213
257
|
# => "HELLO there."
|
@@ -222,7 +266,7 @@ The mapping shortcut allows you to specify a map of regex patterns pointing to t
|
|
222
266
|
class GreenBottle < Calyx::Grammar
|
223
267
|
mapping :pluralize, /(.+)/ => '\\1s'
|
224
268
|
start 'One green {bottle}.', 'Two green {bottle.pluralize}.'
|
225
|
-
|
269
|
+
bottle 'bottle'
|
226
270
|
end
|
227
271
|
|
228
272
|
# => "One green bottle."
|
@@ -243,7 +287,7 @@ end
|
|
243
287
|
class Hello < Calyx::Grammar
|
244
288
|
modifier FullStop
|
245
289
|
start '{hello.capitalize.full_stop}'
|
246
|
-
|
290
|
+
hello 'hello'
|
247
291
|
end
|
248
292
|
|
249
293
|
# => "Hello."
|
@@ -282,7 +326,7 @@ end
|
|
282
326
|
|
283
327
|
class NounsWithArticles < Calyx::Grammar
|
284
328
|
start '{fruit.with_indefinite_article.capitalize.full_stop}'
|
285
|
-
|
329
|
+
fruit 'apple', 'orange', 'banana', 'pear'
|
286
330
|
end
|
287
331
|
|
288
332
|
# => "An apple."
|
@@ -372,7 +416,7 @@ Rough plan for stabilising the API and features for a `1.0` release.
|
|
372
416
|
| `0.8` | ~~method missing metaclass API~~ |
|
373
417
|
| `0.9` | ~~return grammar tree from `#evaluate`, with flattened string from `#generate` being separate~~ |
|
374
418
|
| `0.10` | ~~inject custom string functions for parameterised rules, transforms and mappings~~ |
|
375
|
-
| `0.11` | support YAML format (and JSON?) |
|
419
|
+
| `0.11` | ~~support YAML format (and JSON?)~~ |
|
376
420
|
| `1.0` | API documentation |
|
377
421
|
|
378
422
|
## Credits
|
data/examples/faker.rb
ADDED
data/examples/faker.yml
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
email: "{username}@{domain}"
|
2
|
+
full_name:
|
3
|
+
- "{first_name} {last_name}"
|
4
|
+
- "{first_name} {first_name.chars.first} {last_name}"
|
5
|
+
username:
|
6
|
+
- "{first_name.downcase}"
|
7
|
+
- "{first_name.downcase}{number}"
|
8
|
+
first_name: [Aaliyah, Aaron, Abagail, Abbey, Abbie, Abbigail, Abby, Abdiel, Abdul, Abdullah, Abe, Abel, Abelardo, Abigail, Abigale, Abigayle, Abner, Abraham, Ada, Adah, Adalberto, Adaline, Adam, Adan, Addie, Addison, Adela, Adelbert, Adele, Adelia, Adeline, Adell, Adella, Adelle, Aditya, Adolf, Adolfo, Adolph, Adolphus, Adonis, Adrain, Adrian, Adriana, Adrianna, Adriel, Adrien, Adrienne, Afton, Aglae, Agnes, Agustin, Agustina, Ahmad, Ahmed, Aida, Aidan, Aiden, Aileen, Aimee, Aisha, Aiyana, Akeem, Al, Alaina, Alan, Alana, Alanis, Alanna, Alayna, Alba, Albert, Alberta, Albertha, Alberto, Albin, Albina, Alda, Alden, Alec, Aleen, Alejandra, Alejandrin, Alek, Alena, Alene, Alessandra, Alessandro, Alessia, Aletha, Alex, Alexa, Alexander, Alexandra, Alexandre, Alexandrea, Alexandria, Alexandrine, Alexandro, Alexane, Alexanne, Alexie, Alexis, Alexys, Alexzander, Alf, Alfonso, Alfonzo, Alford, Alfred, Alfreda, Alfredo, Ali, Alia, Alice, Alicia, Alisa, Alisha, Alison, Alivia, Aliya, Aliyah, Aliza, Alize, Allan, Allen, Allene, Allie, Allison, Ally, Alphonso, Alta, Althea, Alva, Alvah, Alvena, Alvera, Alverta, Alvina, Alvis, Alyce, Alycia, Alysa, Alysha, Alyson, Alysson, Amalia, Amanda, Amani, Amara, Amari, Amaya, Amber, Ambrose, Amelia, Amelie, Amely, America, Americo, Amie, Amina, Amir, Amira, Amiya, Amos, Amparo, Amy, Amya, Ana, Anabel, Anabelle, Anahi, Anais, Anastacio, Anastasia, Anderson, Andre, Andreane, Andreanne, Andres, Andrew, Andy, Angel, Angela, Angelica, Angelina, Angeline, Angelita, Angelo, Angie, Angus, Anibal, Anika, Anissa, Anita, Aniya, Aniyah, Anjali, Anna, Annabel, Annabell, Annabelle, Annalise, Annamae, Annamarie, Anne, Annetta, Annette, Annie, Ansel, Ansley, Anthony, Antoinette, Antone, Antonetta, Antonette, Antonia, Antonietta, Antonina, Antonio, Antwan, Antwon, Anya, April, Ara, Araceli, Aracely, Arch, Archibald, Ardella, Arden, Ardith, Arely, Ari, Ariane, Arianna, Aric, Ariel, Arielle, Arjun, Arlene, Arlie, Arlo, Armand, Armando, Armani, Arnaldo, Arne, Arno, Arnold, Arnoldo, Arnulfo, Aron, Art, Arthur, Arturo, Arvel, Arvid, Arvilla, Aryanna, Asa, Asha, Ashlee, Ashleigh, Ashley, Ashly, Ashlynn, Ashton, Ashtyn, Asia, Assunta, Astrid, Athena, Aubree, Aubrey, Audie, Audra, Audreanne, Audrey, August, Augusta, Augustine, Augustus, Aurelia, Aurelie, Aurelio, Aurore, Austen, Austin, Austyn, Autumn, Ava, Avery, Avis, Axel, Ayana, Ayden, Ayla, Aylin, Baby, Bailee, Bailey, Barbara, Barney, Baron, Barrett, Barry, Bart, Bartholome, Barton, Baylee, Beatrice, Beau, Beaulah, Bell, Bella, Belle, Ben, Benedict, Benjamin, Bennett, Bennie, Benny, Benton, Berenice, Bernadette, Bernadine, Bernard, Bernardo, Berneice, Bernhard, Bernice, Bernie, Berniece, Bernita, Berry, Bert, Berta, Bertha, Bertram, Bertrand, Beryl, Bessie, Beth, Bethany, Bethel, Betsy, Bette, Bettie, Betty, Bettye, Beulah, Beverly, Bianka, Bill, Billie, Billy, Birdie, Blair, Blaise, Blake, Blanca, Blanche, Blaze, Bo, Bobbie, Bobby, Bonita, Bonnie, Boris, Boyd, Brad, Braden, Bradford, Bradley, Bradly, Brady, Braeden, Brain, Brandi, Brando, Brandon, Brandt, Brandy, Brandyn, Brannon, Branson, Brant, Braulio, Braxton, Brayan, Breana, Breanna, Breanne, Brenda, Brendan, Brenden, Brendon, Brenna, Brennan, Brennon, Brent, Bret, Brett, Bria, Brian, Briana, Brianne, Brice, Bridget, Bridgette, Bridie, Brielle, Brigitte, Brionna, Brisa, Britney, Brittany, Brock, Broderick, Brody, Brook, Brooke, Brooklyn, Brooks, Brown, Bruce, Bryana, Bryce, Brycen, Bryon, Buck, Bud, Buddy, Buford, Bulah, Burdette, Burley, Burnice, Buster, Cade, Caden, Caesar, Caitlyn, Cale, Caleb, Caleigh, Cali, Calista, Callie, Camden, Cameron, Camila, Camilla, Camille, Camren, Camron, Camryn, Camylle, Candace, Candelario, Candice, Candida, Candido, Cara, Carey, Carissa, Carlee, Carleton, Carley, Carli, Carlie, Carlo, Carlos, Carlotta, Carmel, Carmela, Carmella, Carmelo, Carmen, Carmine, Carol, Carolanne, Carole, Carolina, Caroline, Carolyn, Carolyne, Carrie, Carroll, Carson, Carter, Cary, Casandra, Casey, Casimer, Casimir, Casper, Cassandra, Cassandre, Cassidy, Cassie, Catalina, Caterina, Catharine, Catherine, Cathrine, Cathryn, Cathy, Cayla, Ceasar, Cecelia, Cecil, Cecile, Cecilia, Cedrick, Celestine, Celestino, Celia, Celine, Cesar, Chad, Chadd, Chadrick, Chaim, Chance, Chandler, Chanel, Chanelle, Charity, Charlene, Charles, Charley, Charlie, Charlotte, Chase, Chasity, Chauncey, Chaya, Chaz, Chelsea, Chelsey, Chelsie, Chesley, Chester, Chet, Cheyanne, Cheyenne, Chloe, Chris, Christ, Christa, Christelle, Christian, Christiana, Christina, Christine, Christop, Christophe, Christopher, Christy, Chyna, Ciara, Cicero, Cielo, Cierra, Cindy, Citlalli, Clair, Claire, Clara, Clarabelle, Clare, Clarissa, Clark, Claud, Claude, Claudia, Claudie, Claudine, Clay, Clemens, Clement, Clementina, Clementine, Clemmie, Cleo, Cleora, Cleta, Cletus, Cleve, Cleveland, Clifford, Clifton, Clint, Clinton, Clotilde, Clovis, Cloyd, Clyde, Coby, Cody, Colby, Cole, Coleman, Colin, Colleen, Collin, Colt, Colten, Colton, Columbus, Concepcion, Conner, Connie, Connor, Conor, Conrad, Constance, Constantin, Consuelo, Cooper, Cora, Coralie, Corbin, Cordelia, Cordell, Cordia, Cordie, Corene, Corine, Cornelius, Cornell, Corrine, Cortez, Cortney, Cory, Coty, Courtney, Coy, Craig, Crawford, Creola, Cristal, Cristian, Cristina, Cristobal, Cristopher, Cruz, Crystal, Crystel, Cullen, Curt, Curtis, Cydney, Cynthia, Cyril, Cyrus, Dagmar, Dahlia, Daija, Daisha, Daisy, Dakota, Dale, Dallas, Dallin, Dalton, Damaris, Dameon, Damian, Damien, Damion, Damon, Dan, Dana, Dandre, Dane, D'angelo, Dangelo, Danial, Daniela, Daniella, Danielle, Danika, Dannie, Danny, Dante, Danyka, Daphne, Daphnee, Daphney, Darby, Daren, Darian, Dariana, Darien, Dario, Darion, Darius, Darlene, Daron, Darrel, Darrell, Darren, Darrick, Darrin, Darrion, Darron, Darryl, Darwin, Daryl, Dashawn, Dasia, Dave, David, Davin, Davion, Davon, Davonte, Dawn, Dawson, Dax, Dayana, Dayna, Dayne, Dayton, Dean, Deangelo, Deanna, Deborah, Declan, Dedric, Dedrick, Dee, Deion, Deja, Dejah, Dejon, Dejuan, Delaney, Delbert, Delfina, Delia, Delilah, Dell, Della, Delmer, Delores, Delpha, Delphia, Delphine, Delta, Demarco, Demarcus, Demario, Demetris, Demetrius, Demond, Dena, Denis, Dennis, Deon, Deondre, Deontae, Deonte, Dereck, Derek, Derick, Deron, Derrick, Deshaun, Deshawn, Desiree, Desmond, Dessie, Destany, Destin, Destinee, Destiney, Destini, Destiny, Devan, Devante, Deven, Devin, Devon, Devonte, Devyn, Dewayne, Dewitt, Dexter, Diamond, Diana, Dianna, Diego, Dillan, Dillon, Dimitri, Dina, Dino, Dion, Dixie, Dock, Dolly, Dolores, Domenic, Domenica, Domenick, Domenico, Domingo, Dominic, Dominique, Don, Donald, Donato, Donavon, Donna, Donnell, Donnie, Donny, Dora, Dorcas, Dorian, Doris, Dorothea, Dorothy, Dorris, Dortha, Dorthy, Doug, Douglas, Dovie, Doyle, Drake, Drew, Duane, Dudley, Dulce, Duncan, Durward, Dustin, Dusty, Dwight, Dylan, Earl, Earlene, Earline, Earnest, Earnestine, Easter, Easton, Ebba, Ebony, Ed, Eda, Edd, Eddie, Eden, Edgar, Edgardo, Edison, Edmond, Edmund, Edna, Eduardo, Edward, Edwardo, Edwin, Edwina, Edyth, Edythe, Effie, Efrain, Efren, Eileen, Einar, Eino, Eladio, Elaina, Elbert, Elda, Eldon, Eldora, Eldred, Eldridge, Eleanora, Eleanore, Eleazar, Electa, Elena, Elenor, Elenora, Eleonore, Elfrieda, Eli, Elian, Eliane, Elias, Eliezer, Elijah, Elinor, Elinore, Elisa, Elisabeth, Elise, Eliseo, Elisha, Elissa, Eliza, Elizabeth, Ella, Ellen, Ellie, Elliot, Elliott, Ellis, Ellsworth, Elmer, Elmira, Elmo, Elmore, Elna, Elnora, Elody, Eloisa, Eloise, Elouise, Eloy, Elroy, Elsa, Else, Elsie, Elta, Elton, Elva, Elvera, Elvie, Elvis, Elwin, Elwyn, Elyse, Elyssa, Elza, Emanuel, Emelia, Emelie, Emely, Emerald, Emerson, Emery, Emie, Emil, Emile, Emilia, Emiliano, Emilie, Emilio, Emily, Emma, Emmalee, Emmanuel, Emmanuelle, Emmet, Emmett, Emmie, Emmitt, Emmy, Emory, Ena, Enid, Enoch, Enola, Enos, Enrico, Enrique, Ephraim, Era, Eriberto, Eric, Erica, Erich, Erick, Ericka, Erik, Erika, Erin, Erling, Erna, Ernest, Ernestina, Ernestine, Ernesto, Ernie, Ervin, Erwin, Eryn, Esmeralda, Esperanza, Esta, Esteban, Estefania, Estel, Estell, Estella, Estelle, Estevan, Esther, Estrella, Etha, Ethan, Ethel, Ethelyn, Ethyl, Ettie, Eudora, Eugene, Eugenia, Eula, Eulah, Eulalia, Euna, Eunice, Eusebio, Eva, Evalyn, Evan, Evangeline, Evans, Eve, Eveline, Evelyn, Everardo, Everett, Everette, Evert, Evie, Ewald, Ewell, Ezekiel, Ezequiel, Ezra, Fabian, Fabiola, Fae, Fannie, Fanny, Fatima, Faustino, Fausto, Favian, Fay, Faye, Federico, Felicia, Felicita, Felicity, Felipa, Felipe, Felix, Felton, Fermin, Fern, Fernando, Ferne, Fidel, Filiberto, Filomena, Finn, Fiona, Flavie, Flavio, Fleta, Fletcher, Flo, Florence, Florencio, Florian, Florida, Florine, Flossie, Floy, Floyd, Ford, Forest, Forrest, Foster, Frances, Francesca, Francesco, Francis, Francisca, Francisco, Franco, Frank, Frankie, Franz, Fred, Freda, Freddie, Freddy, Frederic, Frederick, Frederik, Frederique, Fredrick, Fredy, Freeda, Freeman, Freida, Frida, Frieda, Friedrich, Fritz, Furman, Gabe, Gabriel, Gabriella, Gabrielle, Gaetano, Gage, Gail, Gardner, Garett, Garfield, Garland, Garnet, Garnett, Garret, Garrett, Garrick, Garrison, Garry, Garth, Gaston, Gavin, Gay, Gayle, Gaylord, Gene, General, Genesis, Genevieve, Gennaro, Genoveva, Geo, Geoffrey, George, Georgette, Georgiana, Georgianna, Geovanni, Geovanny, Geovany, Gerald, Geraldine, Gerard, Gerardo, Gerda, Gerhard, Germaine, German, Gerry, Gerson, Gertrude, Gia, Gianni, Gideon, Gilbert, Gilberto, Gilda, Giles, Gillian, Gina, Gino, Giovani, Giovanna, Giovanni, Giovanny, Gisselle, Giuseppe, Gladyce, Gladys, Glen, Glenda, Glenna, Glennie, Gloria, Godfrey, Golda, Golden, Gonzalo, Gordon, Grace, Gracie, Graciela, Grady, Graham, Grant, Granville, Grayce, Grayson, Green, Greg, Gregg, Gregoria, Gregorio, Gregory, Greta, Gretchen, Greyson, Griffin, Grover, Guadalupe, Gudrun, Guido, Guillermo, Guiseppe, Gunnar, Gunner, Gus, Gussie, Gust, Gustave, Guy, Gwen, Gwendolyn, Hadley, Hailee, Hailey, Hailie, Hal, Haleigh, Haley, Halie, Halle, Hallie, Hank, Hanna, Hannah, Hans, Hardy, Harley, Harmon, Harmony, Harold, Harrison, Harry, Harvey, Haskell, Hassan, Hassie, Hattie, Haven, Hayden, Haylee, Hayley, Haylie, Hazel, Hazle, Heath, Heather, Heaven, Heber, Hector, Heidi, Helen, Helena, Helene, Helga, Hellen, Helmer, Heloise, Henderson, Henri, Henriette, Henry, Herbert, Herman, Hermann, Hermina, Herminia, Herminio, Hershel, Herta, Hertha, Hester, Hettie, Hilario, Hilbert, Hilda, Hildegard, Hillard, Hillary, Hilma, Hilton, Hipolito, Hiram, Hobart, Holden, Hollie, Hollis, Holly, Hope, Horace, Horacio, Hortense, Hosea, Houston, Howard, Howell, Hoyt, Hubert, Hudson, Hugh, Hulda, Humberto, Hunter, Hyman, Ian, Ibrahim, Icie, Ida, Idell, Idella, Ignacio, Ignatius, Ike, Ila, Ilene, Iliana, Ima, Imani, Imelda, Immanuel, Imogene, Ines, Irma, Irving, Irwin, Isaac, Isabel, Isabell, Isabella, Isabelle, Isac, Isadore, Isai, Isaiah, Isaias, Isidro, Ismael, Isobel, Isom, Israel, Issac, Itzel, Iva, Ivah, Ivory, Ivy, Izabella, Izaiah, Jabari, Jace, Jacey, Jacinthe, Jacinto, Jack, Jackeline, Jackie, Jacklyn, Jackson, Jacky, Jaclyn, Jacquelyn, Jacques, Jacynthe, Jada, Jade, Jaden, Jadon, Jadyn, Jaeden, Jaida, Jaiden, Jailyn, Jaime, Jairo, Jakayla, Jake, Jakob, Jaleel, Jalen, Jalon, Jalyn, Jamaal, Jamal, Jamar, Jamarcus, Jamel, Jameson, Jamey, Jamie, Jamil, Jamir, Jamison, Jammie, Jan, Jana, Janae, Jane, Janelle, Janessa, Janet, Janice, Janick, Janie, Janis, Janiya, Jannie, Jany, Jaquan, Jaquelin, Jaqueline, Jared, Jaren, Jarod, Jaron, Jarred, Jarrell, Jarret, Jarrett, Jarrod, Jarvis, Jasen, Jasmin, Jason, Jasper, Jaunita, Javier, Javon, Javonte, Jay, Jayce, Jaycee, Jayda, Jayde, Jayden, Jaydon, Jaylan, Jaylen, Jaylin, Jaylon, Jayme, Jayne, Jayson, Jazlyn, Jazmin, Jazmyn, Jazmyne, Jean, Jeanette, Jeanie, Jeanne, Jed, Jedediah, Jedidiah, Jeff, Jefferey, Jeffery, Jeffrey, Jeffry, Jena, Jenifer, Jennie, Jennifer, Jennings, Jennyfer, Jensen, Jerad, Jerald, Jeramie, Jeramy, Jerel, Jeremie, Jeremy, Jermain, Jermaine, Jermey, Jerod, Jerome, Jeromy, Jerrell, Jerrod, Jerrold, Jerry, Jess, Jesse, Jessica, Jessie, Jessika, Jessy, Jessyca, Jesus, Jett, Jettie, Jevon, Jewel, Jewell, Jillian, Jimmie, Jimmy, Jo, Joan, Joana, Joanie, Joanne, Joannie, Joanny, Joany, Joaquin, Jocelyn, Jodie, Jody, Joe, Joel, Joelle, Joesph, Joey, Johan, Johann, Johanna, Johathan, John, Johnathan, Johnathon, Johnnie, Johnny, Johnpaul, Johnson, Jolie, Jon, Jonas, Jonatan, Jonathan, Jonathon, Jordan, Jordane, Jordi, Jordon, Jordy, Jordyn, Jorge, Jose, Josefa, Josefina, Joseph, Josephine, Josh, Joshua, Joshuah, Josiah, Josiane, Josianne, Josie, Josue, Jovan, Jovani, Jovanny, Jovany, Joy, Joyce, Juana, Juanita, Judah, Judd, Jude, Judge, Judson, Judy, Jules, Julia, Julian, Juliana, Julianne, Julie, Julien, Juliet, Julio, Julius, June, Junior, Junius, Justen, Justice, Justina, Justine, Juston, Justus, Justyn, Juvenal, Juwan, Kacey, Kaci, Kacie, Kade, Kaden, Kadin, Kaela, Kaelyn, Kaia, Kailee, Kailey, Kailyn, Kaitlin, Kaitlyn, Kale, Kaleb, Kaleigh, Kaley, Kali, Kallie, Kameron, Kamille, Kamren, Kamron, Kamryn, Kane, Kara, Kareem, Karelle, Karen, Kari, Kariane, Karianne, Karina, Karine, Karl, Karlee, Karley, Karli, Karlie, Karolann, Karson, Kasandra, Kasey, Kassandra, Katarina, Katelin, Katelyn, Katelynn, Katharina, Katherine, Katheryn, Kathleen, Kathlyn, Kathryn, Kathryne, Katlyn, Katlynn, Katrina, Katrine, Kattie, Kavon, Kay, Kaya, Kaycee, Kayden, Kayla, Kaylah, Kaylee, Kayleigh, Kayley, Kayli, Kaylie, Kaylin, Keagan, Keanu, Keara, Keaton, Keegan, Keeley, Keely, Keenan, Keira, Keith, Kellen, Kelley, Kelli, Kellie, Kelly, Kelsi, Kelsie, Kelton, Kelvin, Ken, Kendall, Kendra, Kendrick, Kenna, Kennedi, Kennedy, Kenneth, Kennith, Kenny, Kenton, Kenya, Kenyatta, Kenyon, Keon, Keshaun, Keshawn, Keven, Kevin, Kevon, Keyon, Keyshawn, Khalid, Khalil, Kian, Kiana, Kianna, Kiara, Kiarra, Kiel, Kiera, Kieran, Kiley, Kim, Kimberly, King, Kip, Kira, Kirk, Kirsten, Kirstin, Kitty, Kobe, Koby, Kody, Kolby, Kole, Korbin, Korey, Kory, Kraig, Kris, Krista, Kristian, Kristin, Kristina, Kristofer, Kristoffer, Kristopher, Kristy, Krystal, Krystel, Krystina, Kurt, Kurtis, Kyla, Kyle, Kylee, Kyleigh, Kyler, Kylie, Kyra, Lacey, Lacy, Ladarius, Lafayette, Laila, Laisha, Lamar, Lambert, Lamont, Lance, Landen, Lane, Laney, Larissa, Laron, Larry, Larue, Laura, Laurel, Lauren, Laurence, Lauretta, Lauriane, Laurianne, Laurie, Laurine, Laury, Lauryn, Lavada, Lavern, Laverna, Laverne, Lavina, Lavinia, Lavon, Lavonne, Lawrence, Lawson, Layla, Layne, Lazaro, Lea, Leann, Leanna, Leanne, Leatha, Leda, Lee, Leif, Leila, Leilani, Lela, Lelah, Leland, Lelia, Lempi, Lemuel, Lenna, Lennie, Lenny, Lenora, Lenore, Leo, Leola, Leon, Leonard, Leonardo, Leone, Leonel, Leonie, Leonor, Leonora, Leopold, Leopoldo, Leora, Lera, Lesley, Leslie, Lesly, Lessie, Lester, Leta, Letha, Letitia, Levi, Lew, Lewis, Lexi, Lexie, Lexus, Lia, Liam, Liana, Libbie, Libby, Lila, Lilian, Liliana, Liliane, Lilla, Lillian, Lilliana, Lillie, Lilly, Lily, Lilyan, Lina, Lincoln, Linda, Lindsay, Lindsey, Linnea, Linnie, Linwood, Lionel, Lisa, Lisandro, Lisette, Litzy, Liza, Lizeth, Lizzie, Llewellyn, Lloyd, Logan, Lois, Lola, Lolita, Loma, Lon, London, Lonie, Lonnie, Lonny, Lonzo, Lora, Loraine, Loren, Lorena, Lorenz, Lorenza, Lorenzo, Lori, Lorine, Lorna, Lottie, Lou, Louie, Louisa, Lourdes, Louvenia, Lowell, Loy, Loyal, Loyce, Lucas, Luciano, Lucie, Lucienne, Lucile, Lucinda, Lucio, Lucious, Lucius, Lucy, Ludie, Ludwig, Lue, Luella, Luigi, Luis, Luisa, Lukas, Lula, Lulu, Luna, Lupe, Lura, Lurline, Luther, Luz, Lyda, Lydia, Lyla, Lynn, Lyric, Lysanne, Mabel, Mabelle, Mable, Mac, Macey, Maci, Macie, Mack, Mackenzie, Macy, Madaline, Madalyn, Maddison, Madeline, Madelyn, Madelynn, Madge, Madie, Madilyn, Madisen, Madison, Madisyn, Madonna, Madyson, Mae, Maegan, Maeve, Mafalda, Magali, Magdalen, Magdalena, Maggie, Magnolia, Magnus, Maia, Maida, Maiya, Major, Makayla, Makenna, Makenzie, Malachi, Malcolm, Malika, Malinda, Mallie, Mallory, Malvina, Mandy, Manley, Manuel, Manuela, Mara, Marc, Marcel, Marcelina, Marcelino, Marcella, Marcelle, Marcellus, Marcelo, Marcia, Marco, Marcos, Marcus, Margaret, Margarete, Margarett, Margaretta, Margarette, Margarita, Marge, Margie, Margot, Margret, Marguerite, Maria, Mariah, Mariam, Marian, Mariana, Mariane, Marianna, Marianne, Mariano, Maribel, Marie, Mariela, Marielle, Marietta, Marilie, Marilou, Marilyne, Marina, Mario, Marion, Marisa, Marisol, Maritza, Marjolaine, Marjorie, Marjory, Mark, Markus, Marlee, Marlen, Marlene, Marley, Marlin, Marlon, Marques, Marquis, Marquise, Marshall, Marta, Martin, Martina, Martine, Marty, Marvin, Mary, Maryam, Maryjane, Maryse, Mason, Mateo, Mathew, Mathias, Mathilde, Matilda, Matilde, Matt, Matteo, Mattie, Maud, Maude, Maudie, Maureen, Maurice, Mauricio, Maurine, Maverick, Mavis, Max, Maxie, Maxime, Maximilian, Maximillia, Maximillian, Maximo, Maximus, Maxine, Maxwell, May, Maya, Maybell, Maybelle, Maye, Maymie, Maynard, Mayra, Mazie, Mckayla, Mckenna, Mckenzie, Meagan, Meaghan, Meda, Megane, Meggie, Meghan, Mekhi, Melany, Melba, Melisa, Melissa, Mellie, Melody, Melvin, Melvina, Melyna, Melyssa, Mercedes, Meredith, Merl, Merle, Merlin, Merritt, Mertie, Mervin, Meta, Mia, Micaela, Micah, Michael, Michaela, Michale, Micheal, Michel, Michele, Michelle, Miguel, Mikayla, Mike, Mikel, Milan, Miles, Milford, Miller, Millie, Milo, Milton, Mina, Minerva, Minnie, Miracle, Mireille, Mireya, Misael, Missouri, Misty, Mitchel, Mitchell, Mittie, Modesta, Modesto, Mohamed, Mohammad, Mohammed, Moises, Mollie, Molly, Mona, Monica, Monique, Monroe, Monserrat, Monserrate, Montana, Monte, Monty, Morgan, Moriah, Morris, Mortimer, Morton, Mose, Moses, Moshe, Mossie, Mozell, Mozelle, Muhammad, Muriel, Murl, Murphy, Murray, Mustafa, Mya, Myah, Mylene, Myles, Myra, Myriam, Myrl, Myrna, Myron, Myrtice, Myrtie, Myrtis, Myrtle, Nadia, Nakia, Name, Nannie, Naomi, Naomie, Napoleon, Narciso, Nash, Nasir, Nat, Natalia, Natalie, Natasha, Nathan, Nathanael, Nathanial, Nathaniel, Nathen, Nayeli, Neal, Ned, Nedra, Neha, Neil, Nelda, Nella, Nelle, Nellie, Nels, Nelson, Neoma, Nestor, Nettie, Neva, Newell, Newton, Nia, Nicholas, Nicholaus, Nichole, Nick, Nicklaus, Nickolas, Nico, Nicola, Nicolas, Nicole, Nicolette, Nigel, Nikita, Nikki, Nikko, Niko, Nikolas, Nils, Nina, Noah, Noble, Noe, Noel, Noelia, Noemi, Noemie, Noemy, Nola, Nolan, Nona, Nora, Norbert, Norberto, Norene, Norma, Norris, Norval, Norwood, Nova, Novella, Nya, Nyah, Nyasia, Obie, Oceane, Ocie, Octavia, Oda, Odell, Odessa, Odie, Ofelia, Okey, Ola, Olaf, Ole, Olen, Oleta, Olga, Olin, Oliver, Ollie, Oma, Omari, Omer, Ona, Onie, Opal, Ophelia, Ora, Oral, Oran, Oren, Orie, Orin, Orion, Orland, Orlando, Orlo, Orpha, Orrin, Orval, Orville, Osbaldo, Osborne, Oscar, Osvaldo, Oswald, Oswaldo, Otha, Otho, Otilia, Otis, Ottilie, Ottis, Otto, Ova, Owen, Ozella, Ozzie, Pablo, Paige, Palma, Pamela, Pansy, Paolo, Paris, Parker, Pascale, Pasquale, Pat, Patience, Patricia, Patrick, Patsy, Pattie, Paul, Paula, Pauline, Paxton, Payton, Pearl, Pearlie, Pearline, Pedro, Peggie, Penelope, Percival, Percy, Perry, Pete, Peter, Petra, Peyton, Philip, Phoebe, Phyllis, Pierce, Pierre, Pietro, Pink, Pinkie, Piper, Polly, Porter, Precious, Presley, Preston, Price, Prince, Princess, Priscilla, Providenci, Prudence, Queen, Queenie, Quentin, Quincy, Quinn, Quinten, Quinton, Rachael, Rachel, Rachelle, Rae, Raegan, Rafael, Rafaela, Raheem, Rahsaan, Rahul, Raina, Raleigh, Ralph, Ramiro, Ramon, Ramona, Randal, Randall, Randi, Randy, Ransom, Raoul, Raphael, Raphaelle, Raquel, Rashad, Rashawn, Rasheed, Raul, Raven, Ray, Raymond, Raymundo, Reagan, Reanna, Reba, Rebeca, Rebecca, Rebeka, Rebekah, Reece, Reed, Reese, Regan, Reggie, Reginald, Reid, Reilly, Reina, Reinhold, Remington, Rene, Renee, Ressie, Reta, Retha, Retta, Reuben, Reva, Rex, Rey, Reyes, Reymundo, Reyna, Reynold, Rhea, Rhett, Rhianna, Rhiannon, Rhoda, Ricardo, Richard, Richie, Richmond, Rick, Rickey, Rickie, Ricky, Rico, Rigoberto, Riley, Rita, River, Robb, Robbie, Robert, Roberta, Roberto, Robin, Robyn, Rocio, Rocky, Rod, Roderick, Rodger, Rodolfo, Rodrick, Rodrigo, Roel, Rogelio, Roger, Rogers, Rolando, Rollin, Roma, Romaine, Roman, Ron, Ronaldo, Ronny, Roosevelt, Rory, Rosa, Rosalee, Rosalia, Rosalind, Rosalinda, Rosalyn, Rosamond, Rosanna, Rosario, Roscoe, Rose, Rosella, Roselyn, Rosemarie, Rosemary, Rosendo, Rosetta, Rosie, Rosina, Roslyn, Ross, Rossie, Rowan, Rowena, Rowland, Roxane, Roxanne, Roy, Royal, Royce, Rozella, Ruben, Rubie, Ruby, Rubye, Rudolph, Rudy, Rupert, Russ, Russel, Russell, Rusty, Ruth, Ruthe, Ruthie, Ryan, Ryann, Ryder, Rylan, Rylee, Ryleigh, Ryley, Sabina, Sabrina, Sabryna, Sadie, Sadye, Sage, Saige, Sallie, Sally, Salma, Salvador, Salvatore, Sam, Samanta, Samantha, Samara, Samir, Sammie, Sammy, Samson, Sandra, Sandrine, Sandy, Sanford, Santa, Santiago, Santina, Santino, Santos, Sarah, Sarai, Sarina, Sasha, Saul, Savanah, Savanna, Savannah, Savion, Scarlett, Schuyler, Scot, Scottie, Scotty, Seamus, Sean, Sebastian, Sedrick, Selena, Selina, Selmer, Serena, Serenity, Seth, Shad, Shaina, Shakira, Shana, Shane, Shanel, Shanelle, Shania, Shanie, Shaniya, Shanna, Shannon, Shanny, Shanon, Shany, Sharon, Shaun, Shawn, Shawna, Shaylee, Shayna, Shayne, Shea, Sheila, Sheldon, Shemar, Sheridan, Sherman, Sherwood, Shirley, Shyann, Shyanne, Sibyl, Sid, Sidney, Sienna, Sierra, Sigmund, Sigrid, Sigurd, Silas, Sim, Simeon, Simone, Sincere, Sister, Skye, Skyla, Skylar, Sofia, Soledad, Solon, Sonia, Sonny, Sonya, Sophia, Sophie, Spencer, Stacey, Stacy, Stan, Stanford, Stanley, Stanton, Stefan, Stefanie, Stella, Stephan, Stephania, Stephanie, Stephany, Stephen, Stephon, Sterling, Steve, Stevie, Stewart, Stone, Stuart, Summer, Sunny, Susan, Susana, Susanna, Susie, Suzanne, Sven, Syble, Sydnee, Sydney, Sydni, Sydnie, Sylvan, Sylvester, Sylvia, Tabitha, Tad, Talia, Talon, Tamara, Tamia, Tania, Tanner, Tanya, Tara, Taryn, Tate, Tatum, Tatyana, Taurean, Tavares, Taya, Taylor, Teagan, Ted, Telly, Terence, Teresa, Terrance, Terrell, Terrence, Terrill, Terry, Tess, Tessie, Tevin, Thad, Thaddeus, Thalia, Thea, Thelma, Theo, Theodora, Theodore, Theresa, Therese, Theresia, Theron, Thomas, Thora, Thurman, Tia, Tiana, Tianna, Tiara, Tierra, Tiffany, Tillman, Timmothy, Timmy, Timothy, Tina, Tito, Titus, Tobin, Toby, Tod, Tom, Tomas, Tomasa, Tommie, Toney, Toni, Tony, Torey, Torrance, Torrey, Toy, Trace, Tracey, Tracy, Travis, Travon, Tre, Tremaine, Tremayne, Trent, Trenton, Tressa, Tressie, Treva, Trever, Trevion, Trevor, Trey, Trinity, Trisha, Tristian, Tristin, Triston, Troy, Trudie, Trycia, Trystan, Turner, Twila, Tyler, Tyra, Tyree, Tyreek, Tyrel, Tyrell, Tyrese, Tyrique, Tyshawn, Tyson, Ubaldo, Ulices, Ulises, Una, Unique, Urban, Uriah, Uriel, Ursula, Vada, Valentin, Valentina, Valentine, Valerie, Vallie, Van, Vance, Vanessa, Vaughn, Veda, Velda, Vella, Velma, Velva, Vena, Verda, Verdie, Vergie, Verla, Verlie, Vern, Verna, Verner, Vernice, Vernie, Vernon, Verona, Veronica, Vesta, Vicenta, Vicente, Vickie, Vicky, Victor, Victoria, Vida, Vidal, Vilma, Vince, Vincent, Vincenza, Vincenzo, Vinnie, Viola, Violet, Violette, Virgie, Virgil, Virginia, Virginie, Vita, Vito, Viva, Vivian, Viviane, Vivianne, Vivien, Vivienne, Vladimir, Wade, Waino, Waldo, Walker, Wallace, Walter, Walton, Wanda, Ward, Warren, Watson, Wava, Waylon, Wayne, Webster, Weldon, Wellington, Wendell, Wendy, Werner, Westley, Weston, Whitney, Wilber, Wilbert, Wilburn, Wiley, Wilford, Wilfred, Wilfredo, Wilfrid, Wilhelm, Wilhelmine, Will, Willa, Willard, William, Willie, Willis, Willow, Willy, Wilma, Wilmer, Wilson, Wilton, Winfield, Winifred, Winnifred, Winona, Winston, Woodrow, Wyatt, Wyman, Xander, Xavier, Xzavier, Yadira, Yasmeen, Yasmin, Yasmine, Yazmin, Yesenia, Yessenia, Yolanda, Yoshiko, Yvette, Yvonne, Zachariah, Zachary, Zachery, Zack, Zackary, Zackery, Zakary, Zander, Zane, Zaria, Zechariah, Zelda, Zella, Zelma, Zena, Zetta, Zion, Zita, Zoe, Zoey, Zoie, Zoila, Zola, Zora, Zula]
|
9
|
+
last_name: [Abbott, Abernathy, Abshire, Adams, Altenwerth, Anderson, Ankunding, Armstrong, Auer, Aufderhar, Bahringer, Bailey, Balistreri, Barrows, Bartell, Bartoletti, Barton, Bashirian, Batz, Bauch, Baumbach, Bayer, Beahan, Beatty, Bechtelar, Becker, Bednar, Beer, Beier, Berge, Bergnaum, Bergstrom, Bernhard, Bernier, Bins, Blanda, Blick, Block, Bode, Boehm, Bogan, Bogisich, Borer, Bosco, Botsford, Boyer, Boyle, Bradtke, Brakus, Braun, Breitenberg, Brekke, Brown, Bruen, Buckridge, Carroll, Carter, Cartwright, Casper, Cassin, Champlin, Christiansen, Cole, Collier, Collins, Conn, Connelly, Conroy, Considine, Corkery, Cormier, Corwin, Cremin, Crist, Crona, Cronin, Crooks, Cruickshank, Cummerata, Cummings, Dach, D'Amore, Daniel, Dare, Daugherty, Davis, Deckow, Denesik, Dibbert, Dickens, Dicki, Dickinson, Dietrich, Donnelly, Dooley, Douglas, Doyle, DuBuque, Durgan, Ebert, Effertz, Eichmann, Emard, Emmerich, Erdman, Ernser, Fadel, Fahey, Farrell, Fay, Feeney, Feest, Feil, Ferry, Fisher, Flatley, Frami, Franecki, Friesen, Fritsch, Funk, Gaylord, Gerhold, Gerlach, Gibson, Gislason, Gleason, Gleichner, Glover, Goldner, Goodwin, Gorczany, Gottlieb, Goyette, Grady, Graham, Grant, Green, Greenfelder, Greenholt, Grimes, Gulgowski, Gusikowski, Gutkowski, Gutmann, Haag, Hackett, Hagenes, Hahn, Haley, Halvorson, Hamill, Hammes, Hand, Hane, Hansen, Harber, Harris, Hartmann, Harvey, Hauck, Hayes, Heaney, Heathcote, Hegmann, Heidenreich, Heller, Herman, Hermann, Hermiston, Herzog, Hessel, Hettinger, Hickle, Hilll, Hills, Hilpert, Hintz, Hirthe, Hodkiewicz, Hoeger, Homenick, Hoppe, Howe, Howell, Hudson, Huel, Huels, Hyatt, Jacobi, Jacobs, Jacobson, Jakubowski, Jaskolski, Jast, Jenkins, Jerde, Johns, Johnson, Johnston, Jones, Kassulke, Kautzer, Keebler, Keeling, Kemmer, Kerluke, Kertzmann, Kessler, Kiehn, Kihn, Kilback, King, Kirlin, Klein, Kling, Klocko, Koch, Koelpin, Koepp, Kohler, Konopelski, Koss, Kovacek, Kozey, Krajcik, Kreiger, Kris, Kshlerin, Kub, Kuhic, Kuhlman, Kuhn, Kulas, Kunde, Kunze, Kuphal, Kutch, Kuvalis, Labadie, Lakin, Lang, Langosh, Langworth, Larkin, Larson, Leannon, Lebsack, Ledner, Leffler, Legros, Lehner, Lemke, Lesch, Leuschke, Lind, Lindgren, Littel, Little, Lockman, Lowe, Lubowitz, Lueilwitz, Luettgen, Lynch, Macejkovic, MacGyver, Maggio, Mann, Mante, Marks, Marquardt, Marvin, Mayer, Mayert, McClure, McCullough, McDermott, McGlynn, McKenzie, McLaughlin, Medhurst, Mertz, Metz, Miller, Mills, Mitchell, Moen, Mohr, Monahan, Moore, Morar, Morissette, Mosciski, Mraz, Mueller, Muller, Murazik, Murphy, Murray, Nader, Nicolas, Nienow, Nikolaus, Nitzsche, Nolan, Oberbrunner, O'Connell, O'Conner, O'Hara, O'Keefe, O'Kon, Okuneva, Olson, Ondricka, O'Reilly, Orn, Ortiz, Osinski, Pacocha, Padberg, Pagac, Parisian, Parker, Paucek, Pfannerstill, Pfeffer, Pollich, Pouros, Powlowski, Predovic, Price, Prohaska, Prosacco, Purdy, Quigley, Quitzon, Rath, Ratke, Rau, Raynor, Reichel, Reichert, Reilly, Reinger, Rempel, Renner, Reynolds, Rice, Rippin, Ritchie, Robel, Roberts, Rodriguez, Rogahn, Rohan, Rolfson, Romaguera, Roob, Rosenbaum, Rowe, Ruecker, Runolfsdottir, Runolfsson, Runte, Russel, Rutherford, Ryan, Sanford, Satterfield, Sauer, Sawayn, Schaden, Schaefer, Schamberger, Schiller, Schimmel, Schinner, Schmeler, Schmidt, Schmitt, Schneider, Schoen, Schowalter, Schroeder, Schulist, Schultz, Schumm, Schuppe, Schuster, Senger, Shanahan, Shields, Simonis, Sipes, Skiles, Smith, Smitham, Spencer, Spinka, Sporer, Stamm, Stanton, Stark, Stehr, Steuber, Stiedemann, Stokes, Stoltenberg, Stracke, Streich, Stroman, Strosin, Swaniawski, Swift, Terry, Thiel, Thompson, Tillman, Torp, Torphy, Towne, Toy, Trantow, Tremblay, Treutel, Tromp, Turcotte, Turner, Ullrich, Upton, Vandervort, Veum, Volkman, Von, VonRueden, Waelchi, Walker, Walsh, Walter, Ward, Waters, Watsica, Weber, Wehner, Weimann, Weissnat, Welch, West, White, Wiegand, Wilderman, Wilkinson, Will, Williamson, Willms, Windler, Wintheiser, Wisoky, Wisozk, Witting, Wiza, Wolf, Wolff, Wuckert, Wunsch, Wyman, Yost, Yundt, Zboncak, Zemlak, Ziemann, Zieme, Zulauf]
|
10
|
+
number:
|
11
|
+
- "777"
|
12
|
+
- "69"
|
13
|
+
- "34"
|
14
|
+
- "{number}4"
|
15
|
+
domain:
|
16
|
+
- "{noun}{tld}"
|
17
|
+
- "{noun}{noun}{tld}"
|
18
|
+
noun:
|
19
|
+
- abc
|
20
|
+
- acorn
|
21
|
+
- adze
|
22
|
+
- aphx
|
23
|
+
- bat
|
24
|
+
- ball
|
25
|
+
- beach
|
26
|
+
- bell
|
27
|
+
- cat
|
28
|
+
- chalk
|
29
|
+
- dog
|
30
|
+
- dent
|
31
|
+
- elp
|
32
|
+
tld:
|
33
|
+
- .com
|
34
|
+
- .com.au
|
35
|
+
- .co
|
36
|
+
- .co.nz
|
37
|
+
- .org
|
38
|
+
- .info
|
39
|
+
- .co.uk
|
40
|
+
- .tech
|
41
|
+
- .io
|
42
|
+
- .xyz
|
data/lib/calyx/errors.rb
CHANGED
@@ -1,11 +1,58 @@
|
|
1
1
|
module Calyx
|
2
|
+
# Library-specific error types.
|
2
3
|
module Errors
|
3
|
-
|
4
|
+
# Only rules that exist in the registry can be evaluated. When a
|
5
|
+
# non-existent rule is referenced, this error is raised.
|
6
|
+
#
|
7
|
+
# grammar = Calyx::Grammar.new do
|
8
|
+
# start :blank
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# grammar.evaluate
|
12
|
+
# # => Calyx::Errors::MissingRule: :blank is not registered
|
13
|
+
class MissingRule < RuntimeError;
|
14
|
+
def initialize(msg)
|
15
|
+
super(":#{msg} is not registered")
|
16
|
+
end
|
17
|
+
end
|
4
18
|
|
5
|
-
|
6
|
-
|
7
|
-
|
19
|
+
# Raised when a rule passed in via a context map conflicts with an existing
|
20
|
+
# rule in the grammar.
|
21
|
+
#
|
22
|
+
# grammar = Calyx::Grammar.new do
|
23
|
+
# start :priority
|
24
|
+
# priority "(A)"
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# grammar.evaluate(priority: "(B)")
|
28
|
+
# # => Calyx::Errors::DuplicateRule: :priority is already registered
|
29
|
+
class DuplicateRule < ArgumentError
|
30
|
+
def initialize(msg)
|
31
|
+
super(":#{msg} is already registered")
|
8
32
|
end
|
9
33
|
end
|
34
|
+
|
35
|
+
# Raised when the client attempts to load a grammar with an unsupported file
|
36
|
+
# extension. Only `.json` and `.yml` are valid.
|
37
|
+
#
|
38
|
+
# Calyx::Grammar.load("grammar.toml")
|
39
|
+
# # => Calyx::Errors::UnsupportedFormat: grammar.toml is not a valid JSON or YAML file
|
40
|
+
class UnsupportedFormat < ArgumentError
|
41
|
+
def initialize(msg)
|
42
|
+
super("#{File.basename(msg)} is not a valid JSON or YAML file")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Raised when a rule defined in a grammar is invalid. This will prevent
|
47
|
+
# the grammar from compiling correctly.
|
48
|
+
#
|
49
|
+
# Calyx::Grammar.new do
|
50
|
+
# start '40%' => 0.4, '30%' => 0.3
|
51
|
+
# end
|
52
|
+
#
|
53
|
+
# # => Calyx::Errors::InvalidDefinition: Weights must sum to 1
|
54
|
+
#
|
55
|
+
class InvalidDefinition < ArgumentError
|
56
|
+
end
|
10
57
|
end
|
11
58
|
end
|
data/lib/calyx/format.rb
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
module Calyx
|
2
|
+
# Helper methods for loading and initializing grammars from static files
|
3
|
+
# on disk.
|
2
4
|
module Format
|
5
|
+
# Reads a file and parses its format, based on the given extension.
|
6
|
+
#
|
7
|
+
# Accepts a JSON or YAML file path, identified by its extension (`.json`
|
8
|
+
# or `.yml`).
|
9
|
+
#
|
10
|
+
# @param filename [String]
|
11
|
+
# @return [Calyx::Grammar]
|
3
12
|
def self.load(filename)
|
4
13
|
file = File.read(filename)
|
5
14
|
extension = File.extname(filename)
|
@@ -8,20 +17,26 @@ module Calyx
|
|
8
17
|
elsif extension == ".json"
|
9
18
|
self.load_json(file)
|
10
19
|
else
|
11
|
-
raise
|
20
|
+
raise Errors::UnsupportedFormat.new(filename)
|
12
21
|
end
|
13
22
|
end
|
14
23
|
|
15
|
-
|
24
|
+
# Converts the given string of YAML data to a grammar instance.
|
25
|
+
#
|
26
|
+
# @param data [String]
|
27
|
+
# @return [Calyx::Grammar]
|
28
|
+
def self.load_yml(data)
|
16
29
|
require 'yaml'
|
17
|
-
|
18
|
-
self.build_grammar(yaml)
|
30
|
+
self.build_grammar(YAML.load(data))
|
19
31
|
end
|
20
32
|
|
21
|
-
|
33
|
+
# Converts the given string of JSON data to a grammar instance.
|
34
|
+
#
|
35
|
+
# @param data [String]
|
36
|
+
# @return [Calyx::Grammar]
|
37
|
+
def self.load_json(data)
|
22
38
|
require 'json'
|
23
|
-
|
24
|
-
self.build_grammar(json)
|
39
|
+
self.build_grammar(JSON.parse(data))
|
25
40
|
end
|
26
41
|
|
27
42
|
private
|
data/lib/calyx/grammar.rb
CHANGED
@@ -1,43 +1,104 @@
|
|
1
1
|
module Calyx
|
2
|
+
# The main public interface to Calyx. Grammars represent the concept of a
|
3
|
+
# template grammar defined by a set of production rules that can be chained
|
4
|
+
# and nested from a given starting rule.
|
5
|
+
#
|
6
|
+
# Calyx works like a traditional phrase-structured grammar in reverse. Instead
|
7
|
+
# of recognising strings based on a union of possible matches, it generates
|
8
|
+
# strings by representing the union as a choice and randomly picking one
|
9
|
+
# of the options each time the grammar runs.
|
2
10
|
class Grammar
|
3
11
|
class << self
|
12
|
+
# Access the registry belonging to this grammar class.
|
13
|
+
#
|
14
|
+
# Constructs a new registry if it isn't already available.
|
15
|
+
#
|
16
|
+
# @return [Calyx::Registry]
|
4
17
|
def registry
|
5
18
|
@registry ||= Registry.new
|
6
19
|
end
|
7
20
|
|
21
|
+
# Load a grammar instance from the given file.
|
22
|
+
#
|
23
|
+
# Accepts a JSON or YAML file path, identified by its extension (`.json`
|
24
|
+
# or `.yml`).
|
25
|
+
#
|
26
|
+
# @param filename [String]
|
27
|
+
# @return [Calyx::Grammar]
|
8
28
|
def load(filename)
|
9
29
|
Format.load(filename)
|
10
30
|
end
|
11
31
|
|
12
|
-
|
13
|
-
|
32
|
+
# DSL helper method for registering a modifier module with the grammar.
|
33
|
+
#
|
34
|
+
# @param module_name [Module]
|
35
|
+
def modifier(module_name)
|
36
|
+
registry.modifier(module_name)
|
14
37
|
end
|
15
38
|
|
39
|
+
# DSL helper method for registering a paired mapping regex.
|
40
|
+
#
|
41
|
+
# @param name [Symbol]
|
42
|
+
# @param pairs [Hash<Regex,String>]
|
16
43
|
def mapping(name, pairs)
|
17
44
|
registry.mapping(name, pairs)
|
18
45
|
end
|
19
46
|
|
47
|
+
# DSL helper method for registering the given block as a string filter.
|
48
|
+
#
|
49
|
+
# @param name [Symbol]
|
50
|
+
# @block block with a single string argument returning a modified string.
|
20
51
|
def filter(name, &block)
|
21
52
|
registry.mapping(name, &block)
|
22
53
|
end
|
23
54
|
|
55
|
+
# DSL helper method for registering a new grammar rule.
|
56
|
+
#
|
57
|
+
# Not usually used directly, as the method missing API is less verbose.
|
58
|
+
#
|
59
|
+
# @param name [Symbol]
|
60
|
+
# @param productions [Array]
|
24
61
|
def rule(name, *productions)
|
25
62
|
registry.rule(name, *productions)
|
26
63
|
end
|
27
64
|
|
65
|
+
# Augument the grammar with a method missing hook that treats class
|
66
|
+
# method calls as declarations of a new rule.
|
67
|
+
#
|
68
|
+
# This must be bypassed by calling `#rule` directly if the name of the
|
69
|
+
# desired rule clashes with an existing helper method.
|
70
|
+
#
|
71
|
+
# @param name [Symbol]
|
72
|
+
# @param productions [Array]
|
28
73
|
def method_missing(name, *productions)
|
29
74
|
registry.rule(name, *productions)
|
30
75
|
end
|
31
76
|
|
77
|
+
# Hook for combining the registry of a parent grammar into the child that
|
78
|
+
# inherits from it.
|
79
|
+
#
|
80
|
+
# @param child_registry [Calyx::Registry]
|
32
81
|
def inherit_registry(child_registry)
|
33
82
|
registry.combine(child_registry) unless child_registry.nil?
|
34
83
|
end
|
35
84
|
|
85
|
+
# Hook for combining the rules from a parent grammar into the child that
|
86
|
+
# inherits from it.
|
87
|
+
#
|
88
|
+
# This is automatically called by the Ruby engine.
|
89
|
+
#
|
90
|
+
# @param subclass [Class]
|
36
91
|
def inherited(subclass)
|
37
92
|
subclass.inherit_registry(registry)
|
38
93
|
end
|
39
94
|
end
|
40
95
|
|
96
|
+
# Create a new grammar instance, passing in a random seed if needed.
|
97
|
+
#
|
98
|
+
# Grammar rules can be constructed on the fly when the passed-in block is
|
99
|
+
# evaluated.
|
100
|
+
#
|
101
|
+
# @param seed [Number]
|
41
102
|
def initialize(seed=nil, &block)
|
42
103
|
@seed = seed || Random.new_seed
|
43
104
|
srand(@seed)
|
@@ -50,6 +111,11 @@ module Calyx
|
|
50
111
|
end
|
51
112
|
end
|
52
113
|
|
114
|
+
# Produces a string as an output of the grammar.
|
115
|
+
#
|
116
|
+
# @param start_symbol [Symbol]
|
117
|
+
# @param rules_map [Hash]
|
118
|
+
# @return [String]
|
53
119
|
def generate(*args)
|
54
120
|
start_symbol, rules_map = map_default_args(*args)
|
55
121
|
|
@@ -58,6 +124,11 @@ module Calyx
|
|
58
124
|
end.join(''.freeze)
|
59
125
|
end
|
60
126
|
|
127
|
+
# Produces a syntax tree of nested list nodes as an output of the grammar.
|
128
|
+
#
|
129
|
+
# @param start_symbol [Symbol]
|
130
|
+
# @param rules_map [Hash]
|
131
|
+
# @return [Array]
|
61
132
|
def evaluate(*args)
|
62
133
|
start_symbol, rules_map = map_default_args(*args)
|
63
134
|
|
data/lib/calyx/modifiers.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
module Calyx
|
2
|
+
# Applies modifiers to the output of a rule in a template substitution.
|
2
3
|
class Modifiers
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
# Transforms an output string by delegating to the given output function.
|
5
|
+
#
|
6
|
+
# If a registered modifier method is not found, then delegate to the given
|
7
|
+
# string function.
|
8
|
+
#
|
9
|
+
# If an invalid modifier function is given, returns the raw input string.
|
10
|
+
#
|
11
|
+
# @param name [Symbol]
|
12
|
+
# @param value [String]
|
13
|
+
# @return [String]
|
7
14
|
def transform(name, value)
|
8
15
|
if respond_to?(name)
|
9
16
|
send(name, value)
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module Calyx
|
2
|
+
# A type of production rule representing a list of possible rules, one of
|
3
|
+
# which will chosen each time the grammar runs.
|
2
4
|
module Production
|
3
5
|
class Choices
|
6
|
+
# Parse a list of productions and return a choice node which is the head
|
7
|
+
# of a syntax tree of child nodes.
|
8
|
+
#
|
9
|
+
# @param productions [Array]
|
10
|
+
# @param registry [Calyx::Registry]
|
4
11
|
def self.parse(productions, registry)
|
5
12
|
choices = productions.map do |choice|
|
6
13
|
if choice.is_a?(String)
|
@@ -18,10 +25,16 @@ module Calyx
|
|
18
25
|
self.new(choices)
|
19
26
|
end
|
20
27
|
|
28
|
+
# Initialize a new choice with a list of child nodes.
|
29
|
+
#
|
30
|
+
# @param collection [Array]
|
21
31
|
def initialize(collection)
|
22
32
|
@collection = collection
|
23
33
|
end
|
24
34
|
|
35
|
+
# Evaluate the choice by randomly picking one of its possible options.
|
36
|
+
#
|
37
|
+
# @return [Array]
|
25
38
|
def evaluate
|
26
39
|
[:choice, @collection.sample.evaluate]
|
27
40
|
end
|
@@ -1,11 +1,20 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule representing a string combining both template
|
4
|
+
# substitutions and raw content.
|
3
5
|
class Concat
|
4
6
|
EXPRESSION = /(\{[A-Za-z0-9_@\.]+\})/.freeze
|
5
7
|
START_TOKEN = '{'.freeze
|
6
8
|
END_TOKEN = '}'.freeze
|
7
9
|
DEREF_TOKEN = '.'.freeze
|
8
10
|
|
11
|
+
# Parses an interpolated string into fragments combining terminal strings
|
12
|
+
# and non-terminal rules.
|
13
|
+
#
|
14
|
+
# Returns a concat node which is the head of a tree of child nodes.
|
15
|
+
#
|
16
|
+
# @param production [String]
|
17
|
+
# @param registry [Calyx::Registry]
|
9
18
|
def self.parse(production, registry)
|
10
19
|
expansion = production.split(EXPRESSION).map do |atom|
|
11
20
|
if atom.is_a?(String)
|
@@ -30,10 +39,18 @@ module Calyx
|
|
30
39
|
self.new(expansion)
|
31
40
|
end
|
32
41
|
|
42
|
+
# Initialize the concat node with an expansion of terminal and
|
43
|
+
# non-terminal fragments.
|
44
|
+
#
|
45
|
+
# @param expansion [Array]
|
33
46
|
def initialize(expansion)
|
34
47
|
@expansion = expansion
|
35
48
|
end
|
36
49
|
|
50
|
+
# Evaluate all the child nodes of this node and concatenate them together
|
51
|
+
# into a single result.
|
52
|
+
#
|
53
|
+
# @return [Array]
|
37
54
|
def evaluate
|
38
55
|
concat = @expansion.reduce([]) do |exp, atom|
|
39
56
|
exp << atom.evaluate
|
@@ -1,12 +1,23 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule representing a single template substitution.
|
3
4
|
class Expression
|
5
|
+
# Constructs a node representing a single template substitution.
|
6
|
+
#
|
7
|
+
# @param production [#evaluate]
|
8
|
+
# @param methods [Array]
|
9
|
+
# @param registry [Calyx::Registry]
|
4
10
|
def initialize(production, methods, registry)
|
5
11
|
@production = production
|
6
12
|
@methods = methods.map { |m| m.to_sym }
|
7
13
|
@registry = registry
|
8
14
|
end
|
9
15
|
|
16
|
+
# Evaluate the expression by expanding the non-terminal to produce a
|
17
|
+
# terminal string, then passing it through the given modifier chain and
|
18
|
+
# returning the transformed result.
|
19
|
+
#
|
20
|
+
# @return [Array]
|
10
21
|
def evaluate
|
11
22
|
terminal = @production.evaluate.flatten.reject { |o| o.is_a?(Symbol) }.join(''.freeze)
|
12
23
|
expression = @methods.reduce(terminal) do |value, method|
|
@@ -1,13 +1,23 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule representing a memoized subsitution which
|
4
|
+
# returns the first value selected on all subsequent lookups.
|
3
5
|
class Memo
|
4
6
|
SIGIL = '@'.freeze
|
5
7
|
|
8
|
+
# Construct a memoized rule, given the symbol to lookup and the registry
|
9
|
+
# to look it up in.
|
10
|
+
#
|
11
|
+
# @param symbol [Symbol]
|
12
|
+
# @param registry [Calyx::Registry]
|
6
13
|
def initialize(symbol, registry)
|
7
14
|
@symbol = symbol.slice(1, symbol.length-1).to_sym
|
8
15
|
@registry = registry
|
9
16
|
end
|
10
17
|
|
18
|
+
# Evaluate the memo, using the registry to handle the expansion.
|
19
|
+
#
|
20
|
+
# @return [Array]
|
11
21
|
def evaluate
|
12
22
|
[@symbol, @registry.memoize_expansion(@symbol)]
|
13
23
|
end
|
@@ -1,11 +1,21 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule that represents a non-terminal expansion,
|
4
|
+
# linking one rule to another.
|
3
5
|
class NonTerminal
|
6
|
+
# Construct a non-terminal node, given the symbol to lookup and the
|
7
|
+
# registry to look it up in.
|
8
|
+
#
|
9
|
+
# @param symbol [Symbol]
|
10
|
+
# @param registry [Calyx::Registry]
|
4
11
|
def initialize(symbol, registry)
|
5
12
|
@symbol = symbol.to_sym
|
6
13
|
@registry = registry
|
7
14
|
end
|
8
15
|
|
16
|
+
# Evaluate the non-terminal, using the registry to handle the expansion.
|
17
|
+
#
|
18
|
+
# @return [Array]
|
9
19
|
def evaluate
|
10
20
|
[@symbol, @registry.expand(@symbol).evaluate]
|
11
21
|
end
|
@@ -1,10 +1,17 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule that terminates with a resulting string atom.
|
3
4
|
class Terminal
|
5
|
+
# Construct a terminal node with the given value.
|
6
|
+
#
|
7
|
+
# @param atom [#to_s]
|
4
8
|
def initialize(atom)
|
5
9
|
@atom = atom
|
6
10
|
end
|
7
11
|
|
12
|
+
# Evaluate the terminal by returning its identity directly.
|
13
|
+
#
|
14
|
+
# @return [Array]
|
8
15
|
def evaluate
|
9
16
|
[:atom, @atom]
|
10
17
|
end
|
@@ -1,12 +1,20 @@
|
|
1
1
|
module Calyx
|
2
2
|
module Production
|
3
|
+
# A type of production rule representing a map of possible rules with
|
4
|
+
# associated weights that define the expected probability of a rule
|
5
|
+
# being chosen.
|
3
6
|
class WeightedChoices
|
7
|
+
# Parse a given list or hash of productions into a syntax tree of weighted
|
8
|
+
# choices.
|
9
|
+
#
|
10
|
+
# @param productions [Array<Array>, Hash<#to_s, Float>]
|
11
|
+
# @param registry [Calyx::Registry]
|
4
12
|
def self.parse(productions, registry)
|
5
13
|
weights_sum = productions.reduce(0) do |memo, choice|
|
6
14
|
memo += choice.last
|
7
15
|
end
|
8
16
|
|
9
|
-
raise 'Weights must sum to 1' if weights_sum != 1.0
|
17
|
+
raise Errors::InvalidDefinition, 'Weights must sum to 1' if weights_sum != 1.0
|
10
18
|
|
11
19
|
choices = productions.map do |choice, weight|
|
12
20
|
if choice.is_a?(String)
|
@@ -19,10 +27,20 @@ module Calyx
|
|
19
27
|
self.new(choices)
|
20
28
|
end
|
21
29
|
|
30
|
+
# Initialize a new choice with a list of child nodes.
|
31
|
+
#
|
32
|
+
# @param collection [Array]
|
22
33
|
def initialize(collection)
|
23
34
|
@collection = collection
|
24
35
|
end
|
25
36
|
|
37
|
+
# Evaluate the choice by randomly picking one of its possible options,
|
38
|
+
# balanced according to the given weights.
|
39
|
+
#
|
40
|
+
# The method for selecting weighted probabilities is based on a snippet
|
41
|
+
# of code recommended in the Ruby standard library documentation.
|
42
|
+
#
|
43
|
+
# @return [Array]
|
26
44
|
def evaluate
|
27
45
|
choice = @collection.max_by do |_, weight|
|
28
46
|
rand ** (1.0 / weight)
|
data/lib/calyx/registry.rb
CHANGED
@@ -1,25 +1,42 @@
|
|
1
1
|
module Calyx
|
2
|
+
# Lookup table of all the available rules in the grammar.
|
2
3
|
class Registry
|
3
4
|
attr_reader :rules, :transforms, :modifiers
|
4
5
|
|
6
|
+
# Construct an empty registry.
|
5
7
|
def initialize
|
6
8
|
@rules = {}
|
7
9
|
@transforms = {}
|
8
10
|
@modifiers = Modifiers.new
|
9
11
|
end
|
10
12
|
|
13
|
+
# Hook for defining rules without explicitly calling the `#rule` method.
|
14
|
+
#
|
15
|
+
# @param name [Symbol]
|
16
|
+
# @param productions [Array]
|
11
17
|
def method_missing(name, *arguments)
|
12
18
|
rule(name, *arguments)
|
13
19
|
end
|
14
20
|
|
21
|
+
# Attaches a modifier module to this instance.
|
22
|
+
#
|
23
|
+
# @param module_name [Module]
|
15
24
|
def modifier(name)
|
16
|
-
modifiers.
|
25
|
+
modifiers.extend(name)
|
17
26
|
end
|
18
27
|
|
28
|
+
# Registers a paired mapping regex.
|
29
|
+
#
|
30
|
+
# @param name [Symbol]
|
31
|
+
# @param pairs [Hash<Regex,String>]
|
19
32
|
def mapping(name, pairs)
|
20
33
|
transforms[name.to_sym] = construct_mapping(pairs)
|
21
34
|
end
|
22
35
|
|
36
|
+
# Registers the given block as a string filter.
|
37
|
+
#
|
38
|
+
# @param name [Symbol]
|
39
|
+
# @block block with a single string argument returning a modified string.
|
23
40
|
def filter(name, callable=nil, &block)
|
24
41
|
if block_given?
|
25
42
|
transforms[name.to_sym] = block
|
@@ -28,14 +45,26 @@ module Calyx
|
|
28
45
|
end
|
29
46
|
end
|
30
47
|
|
48
|
+
# Registers a new grammar rule.
|
49
|
+
#
|
50
|
+
# @param name [Symbol]
|
51
|
+
# @param productions [Array]
|
31
52
|
def rule(name, *productions)
|
32
53
|
rules[name.to_sym] = construct_rule(productions)
|
33
54
|
end
|
34
55
|
|
56
|
+
# Expands the given rule symbol to its production.
|
57
|
+
#
|
58
|
+
# @param symbol [Symbol]
|
35
59
|
def expand(symbol)
|
36
60
|
rules[symbol] || context[symbol]
|
37
61
|
end
|
38
62
|
|
63
|
+
# Applies the given modifier function to the given value to transform it.
|
64
|
+
#
|
65
|
+
# @param name [Symbol]
|
66
|
+
# @param value [String]
|
67
|
+
# @return [String]
|
39
68
|
def transform(name, value)
|
40
69
|
if transforms.key?(name)
|
41
70
|
transforms[name].call(value)
|
@@ -44,20 +73,38 @@ module Calyx
|
|
44
73
|
end
|
45
74
|
end
|
46
75
|
|
76
|
+
# Expands a memoized rule symbol by evaluating it and storing the result
|
77
|
+
# for later.
|
78
|
+
#
|
79
|
+
# @param symbol [Symbol]
|
47
80
|
def memoize_expansion(symbol)
|
48
81
|
memos[symbol] ||= expand(symbol).evaluate
|
49
82
|
end
|
50
83
|
|
84
|
+
# Merges the given registry instance with the target registry.
|
85
|
+
#
|
86
|
+
# This is only needed at compile time, so that child classes can easily
|
87
|
+
# inherit the set of rules decared by their parent.
|
88
|
+
#
|
89
|
+
# @param registry [Calyx::Registry]
|
51
90
|
def combine(registry)
|
52
91
|
@rules = rules.merge(registry.rules)
|
53
92
|
end
|
54
93
|
|
94
|
+
# Evaluates the grammar defined in this registry, combining it with rules
|
95
|
+
# from the passed in context.
|
96
|
+
#
|
97
|
+
# Produces a syntax tree of nested list nodes.
|
98
|
+
#
|
99
|
+
# @param start_symbol [Symbol]
|
100
|
+
# @param rules_map [Hash]
|
101
|
+
# @return [Array]
|
55
102
|
def evaluate(start_symbol=:start, rules_map={})
|
56
103
|
reset_evaluation_context
|
57
104
|
|
58
105
|
rules_map.each do |key, value|
|
59
106
|
if rules.key?(key.to_sym)
|
60
|
-
raise
|
107
|
+
raise Errors::DuplicateRule.new(key)
|
61
108
|
end
|
62
109
|
|
63
110
|
context[key.to_sym] = if value.is_a?(Array)
|
@@ -72,7 +119,7 @@ module Calyx
|
|
72
119
|
if expansion.respond_to?(:evaluate)
|
73
120
|
[start_symbol, expansion.evaluate]
|
74
121
|
else
|
75
|
-
raise Errors::
|
122
|
+
raise Errors::MissingRule.new(start_symbol)
|
76
123
|
end
|
77
124
|
end
|
78
125
|
|
data/lib/calyx/version.rb
CHANGED
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.11.
|
4
|
+
version: 0.11.1
|
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
|
11
|
+
date: 2016-07-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,8 @@ files:
|
|
66
66
|
- LICENSE
|
67
67
|
- README.md
|
68
68
|
- calyx.gemspec
|
69
|
+
- examples/faker.rb
|
70
|
+
- examples/faker.yml
|
69
71
|
- examples/tiny_woodland.rb
|
70
72
|
- lib/calyx.rb
|
71
73
|
- lib/calyx/errors.rb
|