gtpc2mjz | C/C++ Language Support User's Guide |
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);
The following options control allocation of storage for the results:
The following options are pertinent to input message blocks:
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:
Multiple options can be ORed together; for example, IPRSE_ALLOC | IPRSE_PRINT.
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.
IPRSE_parse detects errors in the input string and in the grammar.
The IPRSE_parse function issues the following messages. The cccc represents the errheader parameter that is printed after the message header; it shows which function or program was calling IPRSE_parse when the error occurred. All messages will be sent via the wtopc function without chaining.
If the system can determine the last parameter in error, the message indicates the last parameter in error by adding the PARAMETER IN ERROR IS text and the parameter value.
If the system can determine the last valid parameter, the message indicates the last valid parameter by adding text that states LAST VALID PARAMETER IS and the parameter value. If a keyword was found to be in error, text will be added that states ERROR IN KEYWORD and the keyword.
Programming Considerations
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.