Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
main.c
Go to the documentation of this file.
1 /* *************************************************************************************
2  Copyright (c) 2021, Lowell D. Thomas
3  All rights reserved.
4 
5  This file is part of APG Version 7.0.
6  APG Version 7.0 may be used under the terms of the BSD 2-Clause License.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 * *************************************************************************************/
79 #include "../../utilities/utilities.h"
80 #include "./float.h"
81 
82 static char* s_cpDescription =
83  "Illustrate the simple basics of constructing a parser from pre-generated grammar files.";
84 
85 static char* s_cppCases[] = {
86  "Display application information.",
87  "Parse an input string and display the parser state.",
88  "Define rule call back functions to display phrase information during the parser's traversal of the parse tree.",
89  "Illustrate reporting a fatal parsing error.",
90 };
91 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
92 
93 static int iHelp(void){
94  long int i = 0;
96  printf("description: %s\n", s_cpDescription);
97  printf(" usage: ex-basic arg\n");
98  printf(" arg = n, 1 <= n <= 4\n");
99  printf(" execute case number n\n");
100  printf(" arg = anthing else\n");
101  printf(" print this help screen\n");
102  printf("\n");
103  for(; i < s_iCaseCount; i++){
104  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
105  }
106  return EXIT_SUCCESS;
107 }
108 
109 static int iApp() {
110  // print the current working directory
112  printf("\n");
113 
114  // display the current APG sizes and macros
115  vUtilApgInfo();
116  return EXIT_SUCCESS;
117 }
118 
119 static int iParseFile() {
120  int iReturn = EXIT_SUCCESS;
121  static void* vpMem = NULL;
122  static void* vpParser = NULL;
123  parser_state sState;
124  parser_config sInput;
125  apg_phrase sPhrase;
126  apg_phrase* spPhrase;
127  achar acaBuffer[128];
128  aint uiBufSize = 128;
129  exception e;
130  XCTOR(e);
131  if(e.try){
132  // try block
133 
134  // construct the parser from the pre-generated grammar files
135  vpParser = vpParserCtor(&e, vpFloatInit);
136 
137  // convert the input string to APG alphabet characters (in general not necessarily same size as char)
138  char* cpInput = "-12.3456e+10";
139  sPhrase.acpPhrase = acaBuffer;
140  sPhrase.uiLength = uiBufSize;
141  spPhrase = spStrToPhrase(cpInput, &sPhrase);
142  if(!spPhrase){
143  XTHROW(&e, "alphabet buffer size to small for input string");
144  }
145 
146 
147  // configure the parser
148  memset((void*)&sInput, 0, sizeof(sInput));
149  sInput.acpInput = spPhrase->acpPhrase;
150  sInput.uiInputLength = spPhrase->uiLength;
151  sInput.uiStartRule = 0;
152 
153  // parse the input string
154  vParserParse(vpParser, &sInput, &sState);
155 
156  // display the state
157  vUtilPrintParserState(&sState);
158  }else{
159  // catch block - display the exception location and message
161  iReturn = EXIT_FAILURE;
162  }
163  vMemDtor(vpMem);
164  return iReturn;
165 }
166 
167 // buffer and buffer size for converting alphabet character phrases to strings
168 static char s_acBuffer[1024];
169 static aint s_uiBufferSize = 1024;
170 
171 // data structure for passing user information to the call back functions
172 typedef struct{
173  exception* spException;
174 } my_data;
175 
176 static void vFloat(callback_data* spData) {
177  if (spData->uiParserState == ID_ACTIVE) {
178  printf("float: going down\n");
179  }else if (spData->uiParserState == ID_MATCH) {
180  // convert the phrase to a string
181  my_data* spMyData = (my_data*)spData->vpUserData;
182  apg_phrase sPhrase;
183  sPhrase.acpPhrase = spData->acpString + spData->uiParserOffset;
184  sPhrase.uiLength = spData->uiParserPhraseLength;
185  if(sPhrase.uiLength >= s_uiBufferSize){
186  XTHROW(spMyData->spException, "string conversion buffer too small");
187  }
188  char* cpStr = cpPhraseToStr(&sPhrase, s_acBuffer);
189  printf("float: going up\n");
190  printf(" phrase: %s\n", cpStr);
191  }
192 }
193 
194 static void vSign(callback_data* spData) {
195  if (spData->uiParserState == ID_ACTIVE) {
196  printf("sign: going down\n");
197  }else if (spData->uiParserState == ID_MATCH) {
198  // convert the phrase to a string
199  my_data* spMyData = (my_data*)spData->vpUserData;
200  apg_phrase sPhrase;
201  sPhrase.acpPhrase = spData->acpString + spData->uiParserOffset;
202  sPhrase.uiLength = spData->uiParserPhraseLength;
203  if(sPhrase.uiLength >= s_uiBufferSize){
204  XTHROW(spMyData->spException, "string conversion buffer too small");
205  }
206  char* cpStr = cpPhraseToStr(&sPhrase, s_acBuffer);
207  printf("sign: going up\n");
208  printf(" phrase: %s\n", cpStr);
209  }
210 }
211 
212 static void vDecimal(callback_data* spData) {
213  if (spData->uiParserState == ID_ACTIVE) {
214  printf("decimal: going down\n");
215  }else if (spData->uiParserState == ID_MATCH) {
216  // convert the phrase to a string
217  my_data* spMyData = (my_data*)spData->vpUserData;
218  apg_phrase sPhrase;
219  sPhrase.acpPhrase = spData->acpString + spData->uiParserOffset;
220  sPhrase.uiLength = spData->uiParserPhraseLength;
221  if(sPhrase.uiLength >= s_uiBufferSize){
222  XTHROW(spMyData->spException, "string conversion buffer too small");
223  }
224  char* cpStr = cpPhraseToStr(&sPhrase, s_acBuffer);
225  printf("decimal: going up\n");
226  printf(" phrase: %s\n", cpStr);
227  }
228 }
229 
230 static void vExponent(callback_data* spData) {
231  if (spData->uiParserState == ID_ACTIVE) {
232  printf("exponent: going down\n");
233  }else if (spData->uiParserState == ID_MATCH) {
234  // convert the phrase to a string
235  my_data* spMyData = (my_data*)spData->vpUserData;
236  apg_phrase sPhrase;
237  sPhrase.acpPhrase = spData->acpString + spData->uiParserOffset;
238  sPhrase.uiLength = spData->uiParserPhraseLength;
239  if(sPhrase.uiLength >= s_uiBufferSize){
240  XTHROW(spMyData->spException, "string conversion buffer too small");
241  }
242  char* cpStr = cpPhraseToStr(&sPhrase, s_acBuffer);
243  printf("exponent: going up\n");
244  printf(" phrase: %s\n", cpStr);
245  }
246 }
247 
248 static void vBadExponent(callback_data* spData) {
249  if (spData->uiParserState == ID_ACTIVE) {
250  printf("exponent: going down\n");
251  }else if (spData->uiParserState == ID_MATCH) {
252  // convert the phrase to a string
253  my_data* spMyData = (my_data*)spData->vpUserData;
254  XTHROW(spMyData->spException, "demonstration of reporting a fatal error from a call back function");
255  }
256 }
257 
258 static int iParseString() {
259  int iReturn = EXIT_SUCCESS;
260  static void* vpMem = NULL;
261  static void* vpParser = NULL;
262  parser_state sState;
263  parser_config sInput;
264  apg_phrase sPhrase;
265  apg_phrase* spPhrase;
266  achar acaBuffer[128];
267  aint uiBufSize = 128;
268  exception e;
269  my_data sMyData = {&e};
270  XCTOR(e);
271  if(e.try){
272  // try block
273 
274  // construct the parser from the pre-generated grammar files
275  vpParser = vpParserCtor(&e, vpFloatInit);
276 
277  // convert the input string to APG alphabet characters (in general not necessarily same size as char)
278  char* cpInput = "-12.3456e+10";
279  sPhrase.acpPhrase = acaBuffer;
280  sPhrase.uiLength = uiBufSize;
281  spPhrase = spStrToPhrase(cpInput, &sPhrase);
282  if(!spPhrase){
283  XTHROW(&e, "alphabet buffer size to small for input string");
284  }
285 
286  // set the callback functions
287  // the rule identifiers are defined in float.h by the generator
288  vParserSetRuleCallback(vpParser, FLOAT_FLOAT, vFloat);
289  vParserSetRuleCallback(vpParser, FLOAT_SIGN, vSign);
290  vParserSetRuleCallback(vpParser, FLOAT_DECIMAL, vDecimal);
291  vParserSetRuleCallback(vpParser, FLOAT_EXPONENT, vExponent);
292 
293  // configure the parser
294  memset((void*)&sInput, 0, sizeof(sInput));
295  sInput.acpInput = spPhrase->acpPhrase;
296  sInput.uiInputLength = spPhrase->uiLength;
297  sInput.uiStartRule = 0;
298  sInput.vpUserData = (void*)&sMyData;
299 
300  // parse the input string
301  vParserParse(vpParser, &sInput, &sState);
302 
303  // display the state
304  printf("\n");
305  vUtilPrintParserState(&sState);
306  }else{
307  // catch block - display the exception location and message
309  iReturn = EXIT_FAILURE;
310  }
311  vMemDtor(vpMem);
312  return iReturn;
313 }
314 
315 static int iParseError() {
316  int iReturn = EXIT_SUCCESS;
317  static void* vpMem = NULL;
318  static void* vpParser = NULL;
319  parser_state sState;
320  parser_config sInput;
321  apg_phrase sPhrase;
322  apg_phrase* spPhrase;
323  achar acaBuffer[128];
324  aint uiBufSize = 128;
325  exception e;
326  my_data sMyData = {&e};
327  XCTOR(e);
328  if(e.try){
329  // try block
330 
331  // construct the parser from the pre-generated grammar files
332  vpParser = vpParserCtor(&e, vpFloatInit);
333 
334  // convert the input string to APG alphabet characters (in general not necessarily same size as char)
335  char* cpInput = "-12.3456e+10";
336  sPhrase.acpPhrase = acaBuffer;
337  sPhrase.uiLength = uiBufSize;
338  spPhrase = spStrToPhrase(cpInput, &sPhrase);
339  if(!spPhrase){
340  XTHROW(&e, "alphabet buffer size to small for input string");
341  }
342 
343  // set the callback functions
344  // the rule identifiers are defined in float.h by the generator
345  vParserSetRuleCallback(vpParser, FLOAT_FLOAT, vFloat);
346  vParserSetRuleCallback(vpParser, FLOAT_SIGN, vSign);
347  vParserSetRuleCallback(vpParser, FLOAT_DECIMAL, vDecimal);
348  vParserSetRuleCallback(vpParser, FLOAT_EXPONENT, vBadExponent);
349 
350  // configure the parser
351  memset((void*)&sInput, 0, sizeof(sInput));
352  sInput.acpInput = spPhrase->acpPhrase;
353  sInput.uiInputLength = spPhrase->uiLength;
354  sInput.uiStartRule = 0;
355  sInput.vpUserData = (void*)&sMyData;
356 
357  // parse the input string
358  vParserParse(vpParser, &sInput, &sState);
359 
360  // display the state
361  printf("\n");
362  vUtilPrintParserState(&sState);
363  }else{
364  // catch block - display the exception location and message
366  iReturn = EXIT_FAILURE;
367  }
368  vMemDtor(vpMem);
369  return iReturn;
370 }
371 
382 int main(int argc, char **argv) {
383  long int iCase = 0;
384  if(argc > 1){
385  iCase = atol(argv[1]);
386  }
387  if(iCase == 0 || (iCase > s_iCaseCount)){
388  return iHelp();
389  }
390  switch(iCase){
391  case 1:
392  return iApp();
393  case 2:
394  return iParseFile();
395  case 3:
396  return iParseString();
397  case 4:
398  return iParseError();
399  }
400 }
401 
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
vpParserCtor
void * vpParserCtor(exception *spException, void *vpParserInit)
The parser's constructor for file initialization data.
Definition: parser.c:67
vMemDtor
void vMemDtor(void *vpCtx)
Destroys a Memory component. Frees all memory allocated.
Definition: memory.c:141
exception::try
abool try
True for the try block, false for the catch block.
Definition: exception.h:49
callback_data::uiParserOffset
aint uiParserOffset
[read only] Offset from acpString to the first character to match
Definition: parser.h:160
float.h
callback_data::acpString
const achar * acpString
[read only] Pointer to the input sub-string,
Definition: parser.h:156
callback_data::uiParserState
aint uiParserState
[read only] ID_ACTIVE if the parser is going down the tree. ID_MATCH or ID_NOMATCH if coming up the t...
Definition: parser.h:158
FLOAT_EXPONENT
#define FLOAT_EXPONENT
Definition: float.h:43
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
vParserSetRuleCallback
void vParserSetRuleCallback(void *vpCtx, aint uiRuleId, parser_callback pfnCallback)
Set a call back function for a specific rule.
Definition: parser.c:386
cpPhraseToStr
char * cpPhraseToStr(apg_phrase *spPhrase, char *cpStr)
Convert a phrase of achar characters to a null-terminated ASCII string.
Definition: tools.c:264
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
callback_data::uiParserPhraseLength
aint uiParserPhraseLength
[read only] The parser's matched phrase length if uiParserState is ID_MATCH or ID_NOMATCH....
Definition: parser.h:161
parser_config
Defines the input string and other configuration parameters for the parser,.
Definition: parser.h:198
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
parser_state
The parser's final state.
Definition: parser.h:183
FLOAT_SIGN
#define FLOAT_SIGN
Definition: float.h:47
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
apg_phrase
Defines a pointer to an achar array plus its length. That is, a phrase as is often used by APG.
Definition: lib.h:60
ID_ACTIVE
#define ID_ACTIVE
indicates active parser state, parser has just entered the node and is moving down the parse tree
Definition: parser.h:72
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
callback_data
The data struct passed to each callback function.
Definition: parser.h:134
callback_data::vpUserData
void * vpUserData
[input/output] User-defined data passed to to the parser in parser_config.
Definition: parser.h:136
apg_phrase::uiLength
aint uiLength
The number of characters in the array.
Definition: lib.h:62
my_data
Definition: main.c:150
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
spStrToPhrase
apg_phrase * spStrToPhrase(const char *cpStr, apg_phrase *spPhrase)
Convert an ASCII, null-terminated string to an achar phrase.
Definition: tools.c:237
vpFloatInit
void * vpFloatInit
Definition: float.c:151
my_data::spException
exception * spException
Definition: main.c:151
FLOAT_FLOAT
#define FLOAT_FLOAT
Definition: float.h:44
FLOAT_DECIMAL
#define FLOAT_DECIMAL
Definition: float.h:39
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
vUtilPrintParserState
void vUtilPrintParserState(parser_state *spState)
Display the parser state in human-readable format to stdout.
Definition: utilities.c:727
apg_phrase::acpPhrase
const achar * acpPhrase
Pointer to an array of type achar APG alphabet characters.
Definition: lib.h:61
vParserParse
void vParserParse(void *vpCtx, parser_config *spConfig, parser_state *spState)
Parse an input string of alphabet characters.
Definition: parser.c:268
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.