Babbly

Babbly is a programming language designed for easily generating texts. The language is used in most of my Twitterbots.

Structures

Disjunctions

Babbly allows for easily specifying several options for slot declarations, e.g. the following example would generate "hello world!", "hello universe!" and "hello earth!".

main = hello <place>!
place = world|universe|earth

Weighted disjunctions

If you want certain options to have higher probability of being used in generation than others, you can easily specify this, e.g. in this example, "hello world!" will be generated 80% of the time.

main = hello <place>!
place = {
    8: world
    1: universe,
    1: world
}

Importing files

Importing word lists

A common design pattern when making such generative grammars is specifying word lists. As such, one can make a .words file where all words are new line separated, and import this. It can then be used just like any other declared generator.

firstname.words:

An
Bob
Charlie
Dave

main.decl

import firstname.words

main = hello my name is <firstname>!

Importing declaration files

One can also import other .decl files to import all these declarations.

import proverb_generator.decls

main = My <relative> always used to say: "<proverb>"!
relative = granddad|grandmother|father|mother

From Java

When you run Babbly from Java, you can also pass the generate function a parameter controlling its initial generator declarations. This way, you can pass arbitrary static strings, other Babbly generators or even more complex Java string generator functions as a named declaration to the file. This is useful e.g. for responding to messages or incorporating certain input words.

Regex-like syntax

Babbly also allows several RegEx-inspired shorthands.

Repetition

Placing {n,m} after any part, repeats the last part n to m times. The example below would generate "hello", "heello", "heeello", "heeeello" and "heeeeello". Alternatively, brackets can be used to repeat more than just a letter.

main = He{1,5}llo

Optionals

Putting a number between 0 and 1 between curly brackets will optionally generate the previous part. E.g., in the example below, "Hello there friend" is generated in 70% of the time, "Hello friend" 30% of the time.

main = Hello (there){.7} friend.

Stored declarations

Often, you want your generated text to refer to the same generated thing multiple times. To achieve this, you can store these using a colon followed by a name, e.g. <declarationname:name>. This name can be just also just be blank.

name = An|Bob|Charlie|Dave
main = <name:protagonist> went to visit <name:>. <name:> said: "You look great, <name:protagonist>."

Functions

Babbly supports some basic functions, and allows you to easily create new any (optional) string conversion functions in Java. Functions are specified within a declaration reference and follow a period. These can also easily be chained.

animal = cat|dog|goose
main = <animal.title.plural> are amazing!

Cascades: backing up generators

Since a function could be defined that not always returns a value, or certain declarations are missing from the context, cascades can be declare to specify back-up options. They are specified using a /.

In the example below, it will generate a fact if the Java function can generate one. If this does not return something valid, it will try find the number of legs of the generated animal. If this also fails (e.g. due to nog having information about the number of legs), it will just say that their animal is awesome.

animal = cat|dog|goose
main = My favorite fact is: (<animal.related_fact>) / (<animal.plural> have <animal.number_of_legs> legs!) / (My <animal> is awesome!)

Examples

Given all these constructs, you can easily create some complex text generators where you have full control over its probabilities.

import firstname.words

food = pasta|pizza|sushi
main = {
  3: <firstname> loves <food>!
  1: <firstname> (quite|reasonably|fairly) likes eating <food>. Oo{1,3}h, I really hope they'll join!
  1: <firstname:protagonist> is not (quite){.5} fond of <food:>. <firstname:protagonist> will thus not go to the <food:> (restaurant|place).
}

Other examples can be found by going to the sources of some of my Twitterbots.

Related publication

Back to projects