P. Maurer's Website, DGL, FHDL, Education, Research

The DGL ActiveX Control


To install the DGL ActiveX control on your system, you need to respond with OK when your browser asks you if its OK to install. If you gave the wrong answer, refresh the page and reply OK this time. If you have fire-wall problems, click here to download a zip file with an installer. Unzip file to a directory and run "setup.exe". Depending on your zip settings, a new directory might be created while unzipping. The installer was created using VS.NET under Windows XP, but should work on Win98 and above. I don't have a Win95 to test. On Win98, the installer keeps asking you to close "applications" that are really just folder displays. Don't be intimidated by this, just keep clicking "Continue." 

To test the installation, (automatic or manual) select the following line, and paste it into the first text box. Then click on the "Generate" button. You should see 10 5-digit binary numbers in the second text box.

main: %10{bn}; bn: %{fived}\r\n; fived: %5d; d: 0,1;

         See below for properties, methods, and events.

Procedures for use

Note that the DGL ActiveX control is at a somewhat lower level than the UNIX version of DGL. Some things, like saving states, that were automatic in the UNIX version, must now be done explicitly. This is because the DGL ActiveX control is a component, not a finished program like the UNIX version. You must use this component to create your own programs. The ActiveX version of DGL is actually enormously more powerful than the UNIX version of DGL, but with increased power comes a bit more work.

The data-generation work of the DGL ActiveX control is actually performed by the CGrammar class,  its aggregates, and their derived classes. The class structure will be made freely available once the documentation is complete. (Who knows when that will be? This is a labor of love, not anything that I get paid for!)

Suppose you have added a control called DGL1 to your Visual Basic project. Let's parse a grammar, save and restore production states, and generate three random strings. The following code is used for this purpose.  (I'm specifying function calls in .NET style.)

    DGL1.StateFileName = "MyGrammar.rand"
    DGL1.RestoreState( )
    RandString1 = DGL1.Select(1)
    RandString2 = DGL1.Select(1)
    RandString3 = DGL1.Select(1)
    DGL1.SaveState( )



These properties are all properties of the current grammar. Changing the grammar will change these properties as well. All properties are run time only.

long GrammarHandle - Pointer to the current CGrammar object, cast to a long. Read Only.

String FlagCharacter - The flag character of the current grammar. % is the default character

String StartSymbol - The start symbol of the current grammar. "main" is the default.

String StateFileName - The state file where the grammar state is saved. There is no default.

short Seed1 - Random number seed, part 1, 16-bit integer. Used by drand48 standard C function

short Seed2 - Random number seed, part 2, 16-bit integer.

short Seed3 - Random number seed, part 3, 16-bit integer.

long RepetitionCount - The repetition count of the current grammar. In this version of DGL, the repetition count is the number of times that the start symbol is interpreted each time the Select method is called. This repetition count is used only if the argument of the select method is zero.

Boolean SaveSeed - Indicates whether the random number seed is saved after each invocation of the grammar. 

long ProductionCount - number of productions in the grammar. Read Only.

String GrammarName - Name of the current grammar, the NULL string is the default.

Boolean IgnoreTimeStamp - Use the seed file even if the hash code is wrong.

long Hash1 - first 32-bits of the hash code

long Hash2 - second 32-bits of the hash code



Standard Data Generation

long ParseString(String Value,String FileName)

The Value string contains a DGL grammar in ASCII format. The FileName string contains a file name that will be used in error messages. This function permits the host program to perform I/O operations. The File named in the FileName parameter is not opened. This string is used for informational purposes only. The ErrorMessage event will be fired to report errors. A zero return indicates the presence of compile errors. Upon success, the grammar is retained within the component in parsed form.

long ParseFile(String FileName)

The FileName string is treated as the name of a file. The file is opened and is treated as an ASCII file containing a DGL grammar. The ErrorMessage event will be fired to report errors. A zero return indicates the presence of compile errors. Upon success, the grammar is retained within the component in parsed form.

String Select(long RepetitionCount)

Performs a data selection operation. The RepetitionCount parameter is used to determine the number of choices made from the start symbol. If RepetitionCount is specified as zero, the RepetitionCount property value is used instead. The generated data is returned as the value of the method.

long SaveState(void)

Writes the random number seed and the state of all saved production to the save file. This method uses the StateFileName property. This method must be called explicitly when you are finished using the grammar. The save operation is NEVER performed automatically.

long RestoreState(void)

Restores the random number seed and the state of all saved production. This method uses the StateFileName property. This method must be called explicitly before using the grammar. The restore operation is NEVER performed automatically.

Production Manipulation

long Reset(void)

Restore all productions to their initial state. This affects all productions with an initial state, such as sequences, counters, and chains.

long ResetProduction(String ProductionName)

Restore a specific production to its initial state.

long SetProbability(String ProductionName, long TableIndex, long ProbabilityValue)

Change the probability of a table entry in a Dynamic production.

void AddString(String NewString)
long AddTable(String ProductionName)
void ClearTable(void)

These functions are used to provide a table for an External production. The DGL ActiveX control maintains an internal list of strings which is initially empty. The AddString method adds a string to this internal list, while the ClearTable method deletes all strings from the internal list. The AddTable method makes a copy of the internal string list, and converts it into a table of strings suitable for use as the right-hand side of a production. This table replaces the current table of the named production, if such an assignment is possible. The AddTable method does not clear the internal list of strings.

long SaveProduction(long ProductionIndex)
long UnsaveProduction(long ProductionIndex)
Boolean IsSaved(long ProductionIndex)

These functions are used to change the saved state of a specific production. The SaveProduction method causes the internal state of the named production to be saved whenever the SaveState method is called. The UnsaveProduction causes the state of the named product not to be saved. The current saved status of a production can be tested using the IsSaved method.

Macro Processing

A DGL grammar can be used as a set of recursive macros. The following methods facilitate this usage.

String InterpretString(String InputString)

The InterpretString method is similar to the Select method, except the start symbol of the grammar is not used as the starting point. Instead, the specified string is used as the starting point. Note that the Select method actually creates the string "%{main}" and calls the InterpretString function to generate the desired data. The InterpretString function will replace all non-terminals in the InputString, and will return the result as the value of the method.

long InterpretFile(String InputFileName,String OutputFileName)

The InterpretFile method works in much the same fashion as the InterpretString method, except the operation is performed file-to-file. The InterpretFile method is capable of handling an unlimited amount of data, while the InterpretString method is limited by internal storage.

long InterpretHeader(String FileName)

The InterpretHeader method is identical to the InterpretFile method, but no output is produced. It is expected that the file will consist of a set of assignments to variables.

Remote Grammar Handling

Remote Grammar handling is done using the following functions, and the property GrammarHandle. To obtain a pointer to the CGrammar object representing the current grammar, access the value of GrammarHandle. Use the SetGrammar method to pass a grammar (by pointer) to a component. When passing a grammar from one component to another, use the ReleaseGrammar method to make the first component "forget" about the grammar. The method DestroyHandle is used to destroy a grammar handle that no longer belongs to any component, due to the use of the ReleaseGrammar method. Note that using the SetGrammar method will cause the new component to "own" the grammar. One must not call the DestroyHandle method on a grammar handle for a grammar that is owned by a component. One should be careful not to end up with two or more components owing the same grammar, because this will cause the grammar to be double-deleted when the program terminates. (This usually causes program failure.) The DestroyCurrentGrammar method causes the component to destroy its current internal grammar. DestroyCurrentGrammar is essentially the same as the NewGrammar method described in the next section.

long DestroyHandle(long GrammarPointer)

void DestroyCurrentGrammar(void)

void ReleaseGrammar(void)

void SetGrammar(long GrammarPointer)

Creating Grammars Dynamically

DGL Grammars can be created dynamically, one production at a time. The first step in doing this is usually to call the NewGrammar method, but this is not necessary. If the NewGrammar method is not called, then any new productions are added to the current grammar, if any.

long NewGrammar(String GrammarName)

GrammarName is actually comments, not used for anything at this time.

Once a new grammar has been created, it can be converted to ASCII and/or saved using the following methods. The GetAscii method allows the host program to perform its own I/O, while the SaveAscii method causes the file to be written by the component.

String GetAscii(void)

long SaveAscii(String FileName)

In addition to creating new productions, it is possible to delete existing productions. The following method can be used to delete any production, including those that came into existence as a result of a ParseString or ParseFile method call.

long DeleteProduction(String ProductionName)

The following is a list of the methods that can be used to create productions. The type StringList is actually the same as the type String. The reason it is designated differently here is because the functions will treat the value of the string as a list of strings. Each string must be terminated by a null character, and the list itself must be terminated by two consecutive null characters. This is \0 in C++ and Chr(0) in Visual Basic.

Those StringList variables named "TaggedList" have an additional requirement that the strings must appear in pairs. The first string of the pair will be interpreted as an ASCII-encoded decimal number and will be converted to a binary value. The second string will be interpreted as a string.

Counter and BinaryCounter productions have an operand called "EndValid." If this value is zero, the End argument will be ignored, and the counter will be interpreted as if no End value was specified. Otherwise the End value is used as one would expect.

For binary productions, the Width should be 8, 16, or 32. Any value larger than 32 will be interpreted as 32. Otherwise the specified value will be rounded up to the next highest value from the list 8, 16, and 32.

Productions that can run out of choices have  ContinueSpec and NextName parameters. ContinueSpec must be specified as a value from 0 through 5 inclusive. These values will be interpreted as the Continue specification of the production, with the following meanings: DEFAULT=0, NEXT=1, STOP=2, ABORT=3, CONTINUE=4, RESTART=5. If 3 (NEXT) is specified, then NextName must contain the name of a production, otherwise NextName is ignored. The value 0 (DEFAULT) causes the default action for the particular production to be used.

Seed productions require the specification of a 48-bit random number seed. This value will be used as the initial value of the random number seed. The value must be specified as 3 16-bit signed numbers.

The list of strings specified for the AddExpression method has a special form. The collection of strings must consist of a set of operators and operands specified in prefix form. For example, the expression "A+B" must be specified as three consecutive strings "+", "A", and "B". No parentheses are used in the specification. Thus (A+B)*(C+D) must be specified as the following sequence of strings "*", "+", "A", "B", "+", "C", "D".

long AddAction(String ProductionName, String FileName, String FunctionName)
long AddBinary(String ProductionName, long Width, StringList Alternatives)
long AddBinaryCounter(String ProductionName, long Start, long Increment, long End, long EndValid, long Width, short ContinueSpec, String NextName)
long AddBinaryField(String ProductionName, StringList TaggedList, long Width)
long AddBinaryRange(String ProductionName, long Start, long End, long Width)
long AddChain(String ProductionName, StringList Alternatives, short ContinueSpec, String NextName)
long AddCombination(String ProductionName, StringList Alternatives, long ItemCount, short ContinueSpec, String NextName)
long AddCounter(String ProductionName, long Start, long Increment, long End, long EndValid, long Width, short ContinueSpec, String NextName)
long AddCountUnique(String ProductionName, StringList TaggedList, short ContinueSpec, String NextName)
long AddDouble(String ProductionName, StringList Alternatives)
long AddDynamic(String ProductionName, StringList TaggedList)
long AddExternal(String ProductionName, StringList Alternatives)
long AddExpression(String ProductionName, StringList Alternatives)
long AddFloat(String ProductionName, StringList Alternatives)
long AddHash(String ProductionName, StringList InitialValues)
long AddHead(String ProductionName, StringList Alternatives, short ContinueSpec, String NextName)
long AddPermutation(String ProductionName, StringList Alternatives, short ContinueSpec, String NextName)
long AddRange(String ProductionName, long Start, long End, long Width)
long AddPointer(String ProductionName, StringList Alternatives)
long AddProbability(String ProductionName, StringList TaggedList)
long AddProduction(String ProductionName, StringList Alternatives)
long AddQueue(String ProductionName, StringList InitialValues)
long AddRQueue(String ProductionName, StringList InitialValues)
long AddSeed(String ProductionName, short InitialValuePart1, short InitialValuePart2, short InitialValuePart3)
long AddSequence(String ProductionName, StringList Alternatives, short ContinueSpec, String NextName)
long AddStack(String ProductionName, StringList InitialValues)
long AddStateQueue(String ProductionName)
long AddStateStack(String ProductionName)
long AddStateVariable(String ProductionName)
long AddUnique(String ProductionName, StringList Alternatives, short ContinueSpec, String NextName)
long AddVariable(String ProductionName String InitialValue)


ErrorMessage(String Message, long LineNumber, String FileName)

Fired when a parse error occurs.

Return to Dr. Maurer's Home Page.

Peter M. Maurer (peter_maurer@baylor.edu)