RiGrammar


Description

A probabilistic context-free grammar with literary extensions for text-generation

Examples
rg = new RiGrammar(stringOrObject);
result = rg.expand();
RiTa grammars are valid JSON or YAML formatted strings (or objects), as follows

{
  "<start>": [ "<rule1>", "<rule2>", "<rule3>" ],

  "<rule2>": [ "terminal1", "terminal2", "<rule1>" ],
  ...
}
OR (in YAML, where quotes are generally not needed)

<start>: [ <rule1>, <rule2>, <rule3> ]

<rule2>: [ terminal1, terminal2, <rule1> ]
...
OR (again, in YAML)

<start>:
  - <rule1>
  - <multiline>

<rule1>:
  - terminal string 1
  - terminal string 2

<multiline>: >
  This is
  a long string
  that wraps three lines
...
  • YAML is a human-friendly superset of JSON, which is often more convenient to use if you're writing your grammar as a String. If you're working in JavaScript, you can alternatively just pass a JavaScript/JSON object instead. And if you're not sure whether your grammar is valid YAML or JSON, you can check it at yamllint.com or jsonlint.com.
     
  • Commonly used methods:

    • expand() begins at the <start> state and generates a string of terminals from the grammar.

    • expandFrom(String) begins with the argument in String (which can consist of both non-terminals and terminals), and expands from there.


      Notice that expand() is simply a convenient version of expandFrom("<start>");.

  • A RiGrammar object will assign (by default) equal weights to all choices in a rule. One can adjust the weights by adding 'multipliers' as follows: (in the rule below, 'terminal1' will be chosen twice as often as the 2 other choices.

    <rule2>: terminal1 [2] | terminal2 | <rule1>
    
  • The RiGrammar object supports callbacks, from your grammar, back into your code. To generate a callback, add the method call in your grammar, surrounded by back-ticks, as follows:

    <rule2>:
      - The cat ran after the `randomNoun()`
      - The cat ran after the `pluralize('cat')`
      - The <noun> ran after the `pluralize(<noun>)`
    

    Then call expand(callee), where callee is the (optional) object on which to execute the method. If no object is supplied (e.g., in JavaScript) then the function is called in the current scope.

    Any number of arguments may be passed in a callback, but for each call, there must be a corresponding method in the object that gets the callback , e.g.,

    function pluralize(theString) {
       ...
    }
    
    Note: this mechanism is not yet implemented in NodeJS (see Issue #71)...

  • Syntax
    // Initialize an empty RiGrammar object.
    
    rg = new RiGrammar();
    
    
    // Or specify a grammar as a YAML/JSON string.
    
    rg = RiGrammar("<start>: [ <rule>, terminal ] ...");
    
    
    // Or specify a grammar in a YAML/JSON object.
    
    rg = RiGrammar(myJsObject);
    
    
    // Or load a YAML/JSON grammar from a file
    
    rg = new RiGrammar();
    rg.loadFrom("grammar.yaml");
    
    
    // Or load a YAML/JSON grammar from a URL
    
    rg = new RiGrammar();
    rg.loadFrom("http://www.theserver.org/path/grammar.json");
    
    
    Parameters
      String or Object the YAML or JSON grammar
    Platform Java / Javascript