Crate glc

source ·
Expand description

glc

This crate’s aim is to generate random expressions based on a context-free grammar.

The acronym stands for “gramática livre de contexto” (context-free grammar).

How to Use

use glc::{Grammar, t_or_rule, nt_seq_rule};

let grammar = Grammar(
    // starting symbol
    "S".into(),

    // vector of rules
    vec![
        // a rule that generates a sequence of non-terminals: "A B"
        nt_seq_rule!("S" => "A", "B"),
        nt_seq_rule!("B" => "A", "B", "N"),
        nt_seq_rule!("B" => "E"),
        t_or_rule!("E" => ""),

        // a rule that is an "or" of terminals: any letter from a-z
        t_or_rule!(
            "A" => "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
                   "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
                   "w", "x", "y", "z"
        ),
        t_or_rule!("N" => "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"),
    ],
);

// generate a random string with this grammar
println!("{}", grammar.gen());

A simplified version of the macro above is available:

// You may need to tune this parameter depending on how large is your grammar,
// since the `grammar` macro is recursive.
#![recursion_limit = "256"]
use glc::grammar;

let _grammar = grammar!{
    // The first non-terminal seen (head of the 1st rule) will be
    // the starting symbol (in this case: `S`).
    S => A B;
    B => A B N;
    B => E;
    E => "";
    // Or transform a non-terminal in one among many terminals
    A => "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
         "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v",
         "w", "x", "y", "z";
    N => "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"
};

For a real-life example take a look at mexe.

Macros

  • Generate a grammar using the following syntax:
  • Represents a rule that replaces one non-terminal by a sequence of non-terminals. Invoke it like this:
  • Parse a rule.
  • Represents a disjunctive rule: a non-terminal that can be replaced by one of the listed terminal symbols. An invocation of this macro looks like this:

Structs

  • A derivation starts with the starting non-terminal symbol of the grammar and progresses by iteratively replacing non-terminals by some sequence of symbols, according to the grammar rules.
  • An expression constituted of a sequence of terminal symbols. These expressions can be obtained by making a complete Derivation with the Grammar. A Derivation that has only terminal symbols can be converted into an expression.
  • Represents a context-free grammar. Contains a NonTerminal which represents the starting symbol and a list of Rules.
  • A non-terminal symbol is a symbol that must be replaced further before the final expression is complete.
  • A disjunction of Sequences.
  • Represents a grammar rule. Contains a NonTerminal which represents the rule’s head, and a RuleBody.
  • A sequence of Symbols.
  • A terminal symbol is a symbol that is not further replaceable. It can appear in the final expression generated.

Enums

  • The body of a rule. The body can be just a Sequence (of symbols) or an Or. The latter is equivalent to a set of rules with the same head, each with a sequence as the body.
  • A Symbol can be a Terminal (a symbol that can appear in the final expression generated by the grammar) or a NonTerminal (a symbol that must be replaced further).