#if !defined  HAVE_STRINGSUBST_H__
#define       HAVE_STRINGSUBST_H__

#include "fxttypes.h"  // ulong


class string_subst
// String substitution engine.
// An axiom (start string) and replacement rules must be supplied.
{
public:
    // example values generate rabbit sequence:
    ulong nsym_;    // # of symbols
    // == 2
    char *symbol_;   // alphabet
    // == { '0', '1' };
    char **symrule_; // symrule_[i] string to replace i-th symbol with
    // == { "0", "1",  "1", "10" };  for  0 |-> 1,  1 |-> 10

    ulong xlate_[256];  // translate char --> rule
    //  'a' --> symrule[ xlate['a'] ]

    ulong cmax_; // max string length
    char  *cc_;  // string to hold result
    ulong ctc_;  // count chars of result actually produced


private:
    void setup(int cmax, int nsym, char*const* symrule);

public:
    string_subst(int cmax, int nsym, char*const* symrule)
    {
        setup(cmax, nsym, symrule);
    }

    ~string_subst()
    {
        delete [] symbol_;
        delete [] symrule_;
        delete [] cc_;
    }

    char* string()  { return cc_; }

    void print_rules(const char *start=0);

    int verify(const char *start="");

    void do_subst(ulong n, const char *rule)
    {
        if ( 0==n )  // add symbols to string:
        {
            for (ulong i=0;  ctc_<cmax_;  ++i)
            {
                char c = rule[i];
                if ( 0==c )  break;
                cc_[ctc_] = c;
                ++ctc_;
            }
        }
        else  // recurse:
        {
            for (ulong i=0;  0!=rule[i];  ++i)
            {
                ulong r = (ulong)rule[i];
                ulong x = xlate_[r];
                do_subst(n-1, symrule_[x]);  // recursion
            }
        }
    }

    ulong subst(ulong maxn, const char *start)
    // maxn:=number of generations,  start:=axiom
    {
        ctc_ = 0;
        do_subst(maxn, start);
        cc_[ctc_] = 0;  // terminate string
        return  ctc_;
    }

};
// -------------------------


#endif  // !defined HAVE_STRINGSUBST_H__
