gtpc2mjzC/C++ Language Support User's Guide

IPRSE_parse-Parse a Text String against a Grammar

IPRSE_parse matches an input string against an input grammar and produces a structure containing elements of the grammar with the corresponding elements of the input string. It is intended primarily for parsing TPF commands by real-time segments written in C.

IPRSE_parse returns the parsed parameters and values through a pointer to a struct IPRSE_output, declared in the tpfparse.h header.

Format

#include <tpfparse.h>
int IPRSE_parse(char *string, const char *grammar,
               struct IPRSE_output *result, int options,
               const char *errheader);

string
The input string, which must be a standard C string terminated by a zero byte ('\0') or by an EOM character if the IPRSE_EOM option is specified. If the IPRSE_EOM option is specified, the maximum length of the string is 4095 characters.

grammar
The grammar describing acceptable input strings. The grammar must end in a zero byte ('\0').

result
The tokenized parameter list in the following form:

result.IPRSE_parameter
The parameter name as specified by the grammar

result.IPRSE_value
The value of the parameter as specified by the input string.
Note:
This value is translated to upper case when the IPRSE_MIXED_CASE option is specified and the corresponding grammar parameter ends with a less-than sign (<).

result.IPRSE_next
The pointer to the next entry in the output parameter list.

options
The following options control sending error messages:

IPRSE_PRINT
Print all error messages.

IPRSE_NOPRINT
Suppress all error messages. This is the default if IPRSE_PRINT is not specified.

The following options control allocation of storage for the results:

IPRSE_ALLOC
Obtain storage dynamically for the output structure. Always code this option.

IPRSE_NOALLOC
This is the default if IPRSE_ALLOC is not specified. Do not use IPRSE_NOALLOC except to facilitate migration of old code that uses the IPRSE_bldprstr function to initialize preallocated storage. Using the IPRSE_ALLOC option is both more efficient and less likely to cause errors.

The following options are pertinent to input message blocks:

IPRSE_EOM
If the input string ends with an EOM character (+) instead of an EOS character ('\0'), the IPRSE_parse function replaces the EOM character with an EOS character. The first EOM character in the input string is replaced, there cannot be any '+' characters within the input string if the IPRSE_EOM option is specified. The EOM character must be in the first 4095 characters of the input string.

IPRSE_NOEOM
This is the default if IPRSE_EOM is not specified. The input string must end with an EOS character ('\0').

The following four options control how the IPRSE_parse function parses the input string. All four of these options can also be specified at the beginning of the grammar (see Specifying Parser Options in the Grammar). Options specified in the grammar parameter override options specified in the options parameter:

IPRSE_STRICT
Accept only spaces as token separators, and only dashes (-) as separators between keywords and values in the input string. Use this option when the input parameters can contain commas (,), slashes (/), or equal signs (=).

IPRSE_NOSTRICT
Accept spaces, commas (,) or slashes (/) as token separators, and dashes (-) or equal signs (=) as separators between keywords and values. This is the default if IPRSE_STRICT is not specified.

IPRSE_MIXED_CASE
Accept lowercase or uppercase letters in the input string.

IPRSE_NOMIXED_CASE
Accept only uppercase letters in the input string. This is the default if IPRSE_MIXED_CASE is not specified.

Multiple options can be ORed together; for example, IPRSE_ALLOC | IPRSE_PRINT.

errheader
A string that identifies the program calling the parser. This string is printed out as part of the error message text if the IPRSE_PRINT option is specified.

Normal Return

IPRSE_parse returns the number of parameters that have been parsed and put in the result structure. For example, a return code of 3 would mean that 3 parameters were parsed from an input string that contained 3 parameters.

Note:
The return code must be used to count the nodes when traversing the result.

Error Return

IPRSE_parse detects errors in the input string and in the grammar.

Programming Considerations

Examples

A series of examples follows, the first of which is a complete program for creating and parsing with a grammar. All of the other examples show a grammar, its input string, and the IPRSE_output structure.

The number of parameters found is returned if the string complies with the grammar conventions. See Defining a Grammar for additional information.

The examples represent the results in the IPRSE_output structure through the diagram shown in Figure 4.

Figure 4. IPRSE_output Structure


Example 1: Coding Example for Grammar and Parser

The following example shows a program that:

/*====================================================================*/
/*  This example shows a segment that parses                          */
/*  a message in MI0MI format on data level D0.                       */
/*  This code example includes calls to:                              */
/*    - parse input using a specific grammar (IPRSE_parse)            */
/*    - use the parsed output (process_parm, defined in this segment) */
/*====================================================================*/
 
#include <tpfeq.h>
#include <tpfapi.h>
#include <string.h>
#include <stdlib.h>
#include <tpfparse.h>
 
/*--------------------------------------------------------------------*/
/*  Define the grammar for the command handled by this     */
/*  segment.                                                          */
/*--------------------------------------------------------------------*/
 
#define XMP_GRAMMAR "{ Positional "                               \
                    "| d+++ a.a [(xx)*] "                    \
                    "| (NO)SELFdef [Key-w List-cc.cc] "      \
                    "}"
 
/*--------------------------------------------------------------------*/
/*  Declare an interface to functions that will process the parsed    */
/*  command parameters.                                    */
/*--------------------------------------------------------------------*/
 
enum   parm1_type { POSITIONAL_NOT_SPECIFIED, POSITIONAL_SPECIFIED };
enum   parm5_type { SELFDEF_NOT_SPECIFIED, SELFDEF_NO, SELFDEF_YES };
 
struct xmp_interface
{
    enum parm1_type   parm1_value;      /*  "Positional"              */
    int               parm2_value;      /*  "d+++"                    */
    char             *parm3_first;      /*  first "a"                 */
    char             *parm3_second;     /*  second "a"                */
    char             *parm4_string;     /*  "(xx)*"                   */
    enum parm5_type   parm5_value;      /*  "(NO)SELFdef"             */
    char              parm6_value;      /*  "Key-w"                   */
    char             *parm7_first;      /*  first "cc"                */
    char             *parm7_second;     /*  second "cc"               */
};
 
#define XMP_DEFAULTS { POSITIONAL_NOT_SPECIFIED, -1, NULL, NULL, NULL, \
                       SELFDEF_NOT_SPECIFIED, '\0', NULL, NULL }
 
/*--------------------------------------------------------------------*/
/*  Declare internal function called by this segment.                 */
/*--------------------------------------------------------------------*/
 
static void process_parm(struct xmp_interface *xi , char *p, char *v);
 
 
/**********************************************************************/
/*  Function ____ completes the parsing of the "Zxxxx" functional     */
/*  message contained in the core block on data level D0.             */
/**********************************************************************/
 
void ____(void)
{
 
/*--------------------------------------------------------------------*/
/*  Define variables for accessing the command text in the */
/*  core block on D0.                                                 */
/*--------------------------------------------------------------------*/
 
    struct mi0mi         *block_ptr;  /*  pointer to core block       */
    char                 *input_ptr;  /*  pointer to message text     */
    char                 *eom_ptr;    /*  pointer to _EOM character   */
                                      /*  (to be replaced by '\0')    */
 
/*--------------------------------------------------------------------*/
/*  Define variables for the parser results.                          */
/*--------------------------------------------------------------------*/
 
    struct IPRSE_output   parse_results;
    int                   num_parms;  /* For saving the IPRSE_parse   */
                                      /* return code.                 */
 
/*--------------------------------------------------------------------*/
/*  Define a moving pointer for traversing the parse results, a wtopc */
/*  header for the help message, and an interface variable for the    */
/*  parsed parameter values.                                          */
/*--------------------------------------------------------------------*/
 
    struct IPRSE_output  *pr_ptr;
    struct wtopc_header   msg_header;
    struct xmp_interface  parm_values = XMP_DEFAULTS;
 
 
/*--------------------------------------------------------------------*/
/*  Access the command block on level D0, point to the     */
/*  beginning of the parameters by skipping over "Zxxxx", and replace */
/*  _EOM with '\0'.                                                   */
/*--------------------------------------------------------------------*/
 
    block_ptr = ecbptr()->ce1cr0;
    input_ptr = block_ptr->mi0acc + strlen("Zxxxx");
    eom_ptr = (char *)&block_ptr->mi0ln0 + block_ptr->mi0cct - 1;
    *eom_ptr = '\0';
 
/*--------------------------------------------------------------------*/
/*  Call the parser.                                                  */
/*--------------------------------------------------------------------*/
 
    num_parms = IPRSE_parse(input_ptr, XMP_GRAMMAR, &parse_results,
        IPRSE_ALLOC | IPRSE_PRINT, "TEST");
 
/*--------------------------------------------------------------------*/
/*  Check if the command meets the grammar's requirements. */
/*--------------------------------------------------------------------*/
 
    if (num_parms > 0)  /*  The parse was successful; num_parms       */
                        /*  parameters from the command    */
                        /*  matched parameters specified in the       */
                        /*  grammar (XMP_GRAMMAR).                    */
    {
        pr_ptr = &parse_results;     /*  point to the first result     */
        do
        {
            process_parm(&parm_values, pr_ptr->IPRSE_parameter,
                pr_ptr->IPRSE_value);
            pr_ptr = pr_ptr->IPRSE_next;
        } while (--num_parms);
 
        /* call additional functions to further process the input */
    }
    else
        if (num_parms == IPRSE_HELP)
        {
            wtopc_insert_header(&msg_header, "TEST", 99, 'I',
                WTOPC_SYS_TIME);
            wtopc("EXAMPLE HELP MESSAGE", 0, WTOPC_NO_CHAIN,
                &msg_header);
        }
        else ;  /*  IPRSE_parse has already written an error message. */
 
    exit(0);    /*  Command processing is completed.       */
}
 
 
/**********************************************************************/
/*  Function process_parm sets the appropriate interface variable     */
/*  field to the value corresponding to the matched parameter.        */
/**********************************************************************/
 
static void process_parm(struct xmp_interface *xi , char *p, char *v)
{
 
/*--------------------------------------------------------------------*/
/*  Define the value that strcmp returns when the two strings passed  */
/*  to it are equal.                                                  */
/*--------------------------------------------------------------------*/
 
#define STRCMP_EQUAL 0
 
/*--------------------------------------------------------------------*/
/*  Define a local variable to point to the dot in a list.            */
/*--------------------------------------------------------------------*/
 
    char *dot_ptr;
 
 
/*--------------------------------------------------------------------*/
/*  Determine which parameter was matched and set up the appropriate  */
/*  interface field(s) with the matching values.                      */
/*--------------------------------------------------------------------*/
 
    if (strcmp(p, "Positional") == STRCMP_EQUAL)
    {
        xi->parm1_value = POSITIONAL_SPECIFIED;
    }
 
    else if (strcmp(p, "d+++") == STRCMP_EQUAL)
    {
        xi->parm2_value = atoi(v);
    }
 
    else if (strcmp(p, "a.a") == STRCMP_EQUAL)
    {
        dot_ptr = strchr(v, '.');   /*  Point to the dot separating   */
                                    /*  the two list sub-parameters.  */
        *dot_ptr = '\0';            /*  Divide the list parameter     */
                                    /*  into two sub-strings.         */
        xi->parm3_first = v;
        xi->parm3_second = dot_ptr + 1;
    }
 
    else if (strcmp(p, "xx") == STRCMP_EQUAL)
    {
        xi->parm4_string = v;
    }
 
    else if (strcmp(p, "(NO)SELFdef") == STRCMP_EQUAL)
    {
        xi->parm5_value =
            *v == 'Y' ? SELFDEF_YES : SELFDEF_NO;
    }
 
    else if (strcmp(p, "Key-w") == STRCMP_EQUAL)
    {
        xi->parm6_value = *v;
    }
 
    else if (strcmp(p, "List-cc.cc") == STRCMP_EQUAL)
    {
        dot_ptr = strchr(v, '.');
        *dot_ptr = '\0';
        xi->parm7_first = v;
        xi->parm7_second = dot_ptr + 1;
    }
 
    return;
}

If the grammar is:

"{ Postional | d+++ a.a [(xx)*]
| (NO)SELFdef [Key-w List-cc.cc]}"

And the input string:

NOSELF K-A L-DD.AA

Therefore, the string meets the grammar requirements. IPRSE_parse returns a return code of 3 because it parsed 3 parameters on the input string. The results in the arrays are shown as follows (result 0 is the first parameter parsed, and so on):

Example 2

 char *grammar = "cccc PRoc-ccxx [IS-d ]";
 char *string  = "DDDD PRO-AB23";

The string meets the grammar requirements. IPRSE_parse returns a return code of 2 because it parsed 2 parameters from the input string. The results in the arrays are shown as follows (result 0 is the first parameter parsed, and so on):

Example 3

 char *grammar = "cccc PR {Deac | Reac}";
 char *string  = "DDDD PR DEA ";

The string meets the grammar requirements. IPRSE_parse returns a return code of 3 because it parsed 3 parameters from the input string. The results in the arrays are shown as follows (result 0 is the first parameter parsed, and so on):

Example 4

 char *grammar = "cccc (wwww)* ";
 char *string  = "DDDD AAAB.CC*  ";

The string meets the grammar requirements. IPRSE_parse returns a return code of 2 because it parsed 2 parameters from the input string. The results in the arrays are shown as follows (result 0 is the first parameter parsed, and so on):

Example 5

 char *grammar = "(NO)RETURNcode";
 char *string  = "NORETURN";

The string meets the grammar requirements. IPRSE_parse returns a return code of 1 because it parsed 2 parameters from the input string. The results in the arrays are shown as follows (result 0 is the first parameter parsed, and so on):

Related Information

Macros BPKDC and BPPSC in TPF General Macros.