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 * *************************************************************************************/
78 #include "../../apgex/apgex.h"
79 
80 #include "source.h"
81 
82 static const char* cpMakeFileName(char* cpBuffer, const char* cpBase, const char* cpDivider, const char* cpName){
83  strcpy(cpBuffer, cpBase);
84  strcat(cpBuffer, cpDivider);
85  strcat(cpBuffer, cpName);
86  return cpBuffer;
87 }
88 
89 static char* s_cpDescription =
90  "Illustrate the construction and use of the apgex pattern-matching object.";
91 
92 static char* s_cppCases[] = {
93  "Display application information.",
94  "Illustrate the basic use of the default mode, verifying and matching the parts of an email address.",
95  "Illustrate all the details of an email pattern match.",
96  "Illustrate the apgex object's properties before and after a successful match",
97  "Illustrate pattern-matching in global mode.",
98  "Illustrate pattern-matching in sticky mode.",
99  "Illustrate the trace mode, with and without PPPT, ASCII and HTML displays.",
100  "Illustrate patterns with User-Defined Terminals (UDTs).",
101  "Illustrate simple testing for a matched pattern without detailed results.",
102  "Illustrate using the AST for a complex translation of a recursive pattern.",
103  "Illustrate the replacement of matched phrases with simple phrases and compound phrases.",
104  "Illustrate using matched phrases as delimiters to split a phrase into an array of sub-phrases.",
105  "Illustrate defining word and line boundaries to find words and lines.",
106  "Illustrate extracting quoted and unquoted fields from Comma Separated Value (CSV) records.",
107  "Illustrate the use of patterns with wide characters.",
108  "Illustrate back references, universal and parent modes.",
109 };
110 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
111 
112 static int iHelp(void){
113  long int i = 0;
115  printf("description: %s\n", s_cpDescription);
116  printf(" usage: ex-api arg\n");
117  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
118  printf(" execute case number n\n");
119  printf(" arg = anthing else\n");
120  printf(" print this help screen\n");
121  printf("\n");
122  for(; i < s_iCaseCount; i++){
123  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
124  }
125  return EXIT_SUCCESS;
126 }
127 
128 static int iApp() {
129  // print the current working directory
131  printf("\n");
132 
133  // display the current APG sizes and macros
134  vUtilApgInfo();
135  return EXIT_SUCCESS;
136 }
137 
138 static int iPatterns() {
139  int iReturn = EXIT_SUCCESS;
140  static void* vpMem = NULL;
141  static void* vpApgex = NULL;
142  static void* vpApi = NULL;
143  static void* vpParser = NULL;
144  char* cpEmailGrammar =
145  "email-address = %^ local \"@\" domain %$\n"
146  "local = local-word *(\".\" local-word)\n"
147  "domain = 1*(sub-domain \".\") top-domain\n"
148  "local-word = 1*local-char\n"
149  "local-char = alpha / num / special\n"
150  "sub-domain = 1*sub-domain-char\n"
151  "top-domain = 2*6top-domain-char\n"
152  "sub-domain-char = alpha / num / \"-\"\n"
153  "top-domain-char = alpha\n"
154  "alpha = %d65-90 / %d97-122\n"
155  "num = %d48-57\n"
156  "special = %d33 / %d35 / %d36-39 / %d42-43 / %d45 / %d47\n"
157  " / %d61 / %d63 / %d94-96 / %d123-126\n";
158  char* cpEmail = "just.me@my.email.domain.com";
159  char* cpGrammarName = "email.abnf";
160  char caGrammarBuf[PATH_MAX];
161  const char* cpGrammarFile;
162  apgex_result sResult;
163  apg_phrase* spPhrase;
164  exception e;
165  XCTOR(e);
166  if(e.try){
167  // try block
168  vpMem = vpMemCtor(&e);
169  vpApgex = vpApgexCtor(&e);
170  vpApi = vpApiCtor(&e);
171 
172  cpGrammarFile = cpMakeFileName(caGrammarBuf, SOURCE_DIR, "/../input/", cpGrammarName);
173 
174  // display the information header
175  char* cpHeader =
176  "This example case illustrates the three methods of defining the pattern for\n"
177  "verification of an email address.\n";
178  printf("\n%s", cpHeader);
179 
180  // convert the input string to an alphabet character phrase
181  spPhrase = spUtilStrToPhrase(vpMem, cpEmail);
182  printf("\nThe email pattern:\n%s", cpEmailGrammar);
183  printf("\nThe email to match: %s\n", cpEmail);
184 
185  // use the string version of the grammar
186  printf("\nvApgexPattern: use an application-defined string to define the pattern.\n");
187  vApgexPattern(vpApgex, cpEmailGrammar, "");
188  sResult = sApgexExec(vpApgex, spPhrase);
189  vApgexDisplayResult(vpApgex, &sResult, NULL);
190 
191  // use the string version of the grammar
192  printf("\nvApgexPatternFile: use a file to define the pattern.\n");
193  vApgexPatternFile(vpApgex, cpGrammarFile, "");
194  sResult = sApgexExec(vpApgex, spPhrase);
195  vApgexDisplayResult(vpApgex, &sResult, NULL);
196 
197  // use the parser version with its intrinsic grammar
198  printf("\nvApgexPatternParser: use a pre-constructed parser to define the pattern.\n");
199  vApiFile(vpApi, cpGrammarFile, APG_FALSE, APG_FALSE);
200  vpParser = vpApiOutputParser(vpApi);
201  vApgexPatternParser(vpApgex, vpParser, "");
202  sResult = sApgexExec(vpApgex, spPhrase);
203  vApgexDisplayResult(vpApgex, &sResult, NULL);
204 
205  }else{
206  // catch block - display the exception location and message
208  vApgexDisplayPatternErrors(vpApgex, NULL);
209  iReturn = EXIT_FAILURE;
210  }
211 
212  // clean up resources
213  vParserDtor(vpParser);
214  vApiDtor(vpApi);
215  vApgexDtor(vpApgex);
216  vMemDtor(vpMem);
217  return iReturn;
218 }
219 
220 static int iResults() {
221  int iReturn = EXIT_SUCCESS;
222  static void* vpMem = NULL;
223  static void* vpApgex = NULL;
224  static void* vpApi = NULL;
225  char* cpEmail = "just.me@my.email.domain.com";
226  char* cpEmail2 = "This email address is a fake just.me@my.email.domain.com so don't share it with anyone.";
227  char* cpGrammarName = "email.abnf";
228  char caGrammarBuf[PATH_MAX];
229  const char* cpGrammarFile;
230  apgex_result sResult;
231  apg_phrase* spPhrase;
232  exception e;
233  XCTOR(e);
234  if(e.try){
235  // try block
236  vpMem = vpMemCtor(&e);
237  vpApgex = vpApgexCtor(&e);
238  vpApi = vpApiCtor(&e);
239 
240  cpGrammarFile = cpMakeFileName(caGrammarBuf, SOURCE_DIR, "/../input/", cpGrammarName);
241 
242  // display the information header
243  char* cpHeader =
244  "This example case illustrates details of the pattern-matching result.\n"
245  "Three cases show minimal, partial and full rule results.\n";
246  printf("\n%s", cpHeader);
247 
248  // convert the input string to an alphabet character phrase
249  spPhrase = spUtilStrToPhrase(vpMem, cpEmail);
250  vApiInClear(vpApi);
251  printf("\nThe email pattern:\n%s", cpApiInFile(vpApi, cpGrammarFile));
252  printf("\nThe email to match: %s\n", cpEmail);
253 
254  // display minimal result
255  printf("\nMinimal result: By default the result only shows the full pattern match.\n");
256  vApgexPatternFile(vpApgex, cpGrammarFile, "");
257  sResult = sApgexExec(vpApgex, spPhrase);
258  vApgexDisplayResult(vpApgex, &sResult, NULL);
259 
260  // enable select rules
261  printf("\nIntermediate result: Display the sub-phrases for a few select rules.\n");
262  vApgexEnableRules(vpApgex, "local, domain, local-word, sub-domain, top-domain", APG_TRUE);
263  sResult = sApgexExec(vpApgex, spPhrase);
264  vApgexDisplayResult(vpApgex, &sResult, NULL);
265 
266  // enable all rules
267  printf("\nFull result: Display the sub-phrases for all rules.\n");
268  vApgexEnableRules(vpApgex, "--all", APG_TRUE);
269  sResult = sApgexExec(vpApgex, spPhrase);
270  vApgexDisplayResult(vpApgex, &sResult, NULL);
271 
272 
273  // display minimal result with left and right context
274  printf("\n Embedded phrase: Find the pattern in a longer string. Display left and right context\n");
275  printf("The embedded phrase: %s\n", cpEmail2);
276  spPhrase = spUtilStrToPhrase(vpMem, cpEmail2);
277  vApgexPatternFile(vpApgex, cpGrammarFile, "");
278  sResult = sApgexExec(vpApgex, spPhrase);
279  vApgexDisplayResult(vpApgex, &sResult, NULL);
280 
281  }else{
282  // catch block - display the exception location and message
284  vApgexDisplayPatternErrors(vpApgex, NULL);
285  iReturn = EXIT_FAILURE;
286  }
287 
288  // clean up resources
289  vApiDtor(vpApi);
290  vApgexDtor(vpApgex);
291  vMemDtor(vpMem);
292  return iReturn;
293 }
294 
295 static int iProperties() {
296  int iReturn = EXIT_SUCCESS;
297  static void* vpMem = NULL;
298  static void* vpApgex = NULL;
299  static void* vpApi = NULL;
300  char* cpEmailGood = "This, just.me@my.email.domain.com, is an email address.";
301  char* cpEmailBad = "Not an email address.";
302  char* cpGrammarName = "email.abnf";
303  char caGrammarBuf[PATH_MAX];
304  const char* cpGrammarFile;
305  apgex_result sResult;
306  apgex_properties sProperties;
307  apg_phrase* spPhrase;
308  exception e;
309  XCTOR(e);
310  if(e.try){
311  // try block
312  vpMem = vpMemCtor(&e);
313  vpApgex = vpApgexCtor(&e);
314  vpApi = vpApiCtor(&e);
315 
316  cpGrammarFile = cpMakeFileName(caGrammarBuf, SOURCE_DIR, "/../input/", cpGrammarName);
317 
318  // display the information header
319  char* cpHeader =
320  "This example case illustrates the pattern-matching properties.\n"
321  "Properties are illustrated before a pattern match, after a successful match\n"
322  "and after an unsuccessful match.\n";
323  printf("\n%s", cpHeader);
324 
325  // before the match
326  printf("\nProperties before the pattern match:\n");
327  vApgexPatternFile(vpApgex, cpGrammarFile, "gpth");
328  sProperties = sApgexProperties(vpApgex);
329  vApgexDisplayProperties(vpApgex, &sProperties, NULL);
330 
331  // after successful match
332  printf("\nProperties after successful pattern match:\n");
333  vApgexPatternFile(vpApgex, cpGrammarFile, "");
334  spPhrase = spUtilStrToPhrase(vpMem, cpEmailGood);
335  sResult = sApgexExec(vpApgex, spPhrase);
336  sProperties = sApgexProperties(vpApgex);
337  vApgexDisplayProperties(vpApgex, &sProperties, NULL);
338 
339  // after an unsuccessful match
340  printf("\nProperties after an unsuccessful pattern match:\n");
341  vApgexPatternFile(vpApgex, cpGrammarFile, "");
342  spPhrase = spUtilStrToPhrase(vpMem, cpEmailBad);
343  sResult = sApgexExec(vpApgex, spPhrase);
344  sProperties = sApgexProperties(vpApgex);
345  vApgexDisplayProperties(vpApgex, &sProperties, NULL);
346 
347  // just to silence unused warnings
348  sProperties.uiLastIndex = sResult.uiLastIndex;
349 
350  }else{
351  // catch block - display the exception location and message
353  vApgexDisplayPatternErrors(vpApgex, NULL);
354  iReturn = EXIT_FAILURE;
355  }
356 
357  // clean up resources
358  vApiDtor(vpApi);
359  vApgexDtor(vpApgex);
360  vMemDtor(vpMem);
361  return iReturn;
362 }
363 
364 static int iGlobalMode() {
365  int iReturn = EXIT_SUCCESS;
366  static void* vpMem = NULL;
367  static void* vpApgex = NULL;
368  char* cpGrammar = "word = %s\"abc\"\n";
369  char* cpStr = "Learn your abcs by repeating, abc, abc, abc over an over again.";
370  apgex_result sResult;
371  apg_phrase* spPhrase;
372  exception e;
373  XCTOR(e);
374  if(e.try){
375  // try block
376  vpMem = vpMemCtor(&e);
377  vpApgex = vpApgexCtor(&e);
378 
379  // display the information header
380  char* cpHeader =
381  "This example case illustrates pattern-matching in global mode.\n"
382  "Setting the global flag \"g\" facilitates finding all occurrences of a phrase in a sting.\n";
383  printf("\n%s", cpHeader);
384  printf("\nThe Grammar\n");
385  printf("%s\n", cpGrammar);
386  printf("The Input String\n");
387  printf("%s\n", cpStr);
388 
389  // before the match
390  printf("\nFind all occurrences of the grammar phrase in the input string.\n");
391  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
392  vApgexPattern(vpApgex, cpGrammar, "g");
393  sResult = sApgexExec(vpApgex, spPhrase);
394  while(sResult.spResult){
395  vApgexDisplayResult(vpApgex, &sResult, NULL);
396  sResult = sApgexExec(vpApgex, spPhrase);
397  }
398 
399  }else{
400  // catch block - display the exception location and message
402  vApgexDisplayPatternErrors(vpApgex, NULL);
403  iReturn = EXIT_FAILURE;
404  }
405 
406  // clean up resources
407  vApgexDtor(vpApgex);
408  vMemDtor(vpMem);
409  return iReturn;
410 }
411 
412 static int iStickyMode() {
413  int iReturn = EXIT_SUCCESS;
414  static void* vpMem = NULL;
415  static void* vpApgex = NULL;
416  char* cpGrammar = "word = %s\"abc\"\n";
417  char* cpStr = "Learn your abcs by repeating, abcabcabc over an over again.";
418  apgex_result sResult;
419  apg_phrase* spPhrase;
420  exception e;
421  XCTOR(e);
422  if(e.try){
423  // try block
424  vpMem = vpMemCtor(&e);
425  vpApgex = vpApgexCtor(&e);
426 
427  // display the information header
428  char* cpHeader =
429  "This example case illustrates pattern-matching in sticky mode.\n"
430  "Setting the sticky flag \"y\" facilitates finding only occurrences\n"
431  "at a fixed position in the input string. Additionally, it can find consecutive\n"
432  "occurrences as long as there are no characters in between.\n";
433  printf("\n%s", cpHeader);
434  printf("\nThe Grammar\n");
435  printf("%s\n", cpGrammar);
436  printf("The Input String\n");
437  printf("%s\n", cpStr);
438 
439  // beginning of string
440  printf("\nAttempt finding a match at the beginning of the string.\n");
441  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
442  vApgexPattern(vpApgex, cpGrammar, "y");
443  sResult = sApgexExec(vpApgex, spPhrase);
444  vApgexDisplayResult(vpApgex, &sResult, NULL);
445 
446  // at position of first occurrence
447  printf("\nFind a match at a set position.\n");
448  vApgexSetLastIndex(vpApgex, 11);
449  sResult = sApgexExec(vpApgex, spPhrase);
450  vApgexDisplayResult(vpApgex, &sResult, NULL);
451 
452  // consecutive phrases
453  printf("\nFind consecutive phrases.\n");
454  vApgexSetLastIndex(vpApgex, 30);
455  sResult = sApgexExec(vpApgex, spPhrase);
456  while(sResult.spResult){
457  vApgexDisplayResult(vpApgex, &sResult, NULL);
458  sResult = sApgexExec(vpApgex, spPhrase);
459  }
460 
461  }else{
462  // catch block - display the exception location and message
464  vApgexDisplayPatternErrors(vpApgex, NULL);
465  iReturn = EXIT_FAILURE;
466  }
467 
468  // clean up resources
469  vApgexDtor(vpApgex);
470  vMemDtor(vpMem);
471  return iReturn;
472 }
473 
474 static int iTraceMode() {
475  int iReturn = EXIT_SUCCESS;
476  static void* vpMem = NULL;
477  static void* vpApgex = NULL;
478  char* cpGrammar = "word = \"abc\" / \"xyz\"\n";
479  char* cpStr = "---xyz---";
480  const char* cpOutput;
481  char caOutputBuf[PATH_MAX];
482  apg_phrase* spPhrase;
483  exception e;
484  XCTOR(e);
485  if(e.try){
486  // try block
487  vpMem = vpMemCtor(&e);
488  vpApgex = vpApgexCtor(&e);
489 
490  cpOutput = cpMakeFileName(caOutputBuf, SOURCE_DIR, "/../output/", "trace.html");
491 
492  // display the information header
493  char* cpHeader =
494  "This example case illustrates the trace mode.\n"
495  "Setting the trace flag \"t\" will generate a trace of each phrase-matching attempt.\n"
496  "By default, the display will be in ASCII mode and displayed to stdout.\n"
497  "With the PPPT flag \"p\" set the PPPT trace can be compared to the previous without.\n"
498  "Finally, with the \"th\" flags set, the trace will be generated in HTML format.\n";
499  printf("\n%s", cpHeader);
500  printf("\nThe Grammar\n");
501  printf("%s\n", cpGrammar);
502  printf("The Input String\n");
503  printf("%s\n", cpStr);
504 
505  // beginning of string
506  printf("\nTrace of all phrase-matching attempts.\n");
507  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
508  vApgexPattern(vpApgex, cpGrammar, "t");
509  sApgexExec(vpApgex, spPhrase);
510 
511  printf("\nCompare trace with PPPT to previous without PPPT.\n");
512  vApgexPattern(vpApgex, cpGrammar, "tp");
513  sApgexExec(vpApgex, spPhrase);
514 
515  printf("\nDisplay trace in HTML format.\n");
516  printf("Display %s in any browser.\n",cpOutput);
517  vApgexPattern(vpApgex, cpGrammar, "th");
518  void* vpTrace = vpApgexGetTrace(vpApgex);
519  if(!vpTrace){
520  XTHROW(&e, "should have a trace context pointer here");
521  }
522  vTraceSetOutput(vpTrace, cpOutput);
523  sApgexExec(vpApgex, spPhrase);
524 
525  }else{
526  // catch block - display the exception location and message
528  vApgexDisplayPatternErrors(vpApgex, NULL);
529  iReturn = EXIT_FAILURE;
530  }
531 
532  // clean up resources
533  vApgexDtor(vpApgex);
534  vMemDtor(vpMem);
535  return iReturn;
536 }
537 #define HYPHEN 45
538 #define BANG 33
539 #define GT 62
540 #define LT 60
541 static void vCommentUdt(callback_data* spData){
542  if(spData->uiParserState == ID_ACTIVE){
543  const achar* acpChar = spData->acpString + spData->uiParserOffset;
544  const achar* acpEnd = spData->acpString + spData->uiStringLength;
545  achar acPrevChar1 = 0;
546  achar acPrevChar2 = 0;
547  achar acPrevChar3 = 0;
548  achar acChar;
549  aint uiLen = 0;
550  spData->uiCallbackState = ID_NOMATCH;
551  spData->uiCallbackPhraseLength = 0;
552  if((acpChar +3) < acpEnd){
553  if(*acpChar++ != LT){
554  return;
555  }
556  if(*acpChar++ != BANG){
557  return;
558  }
559  if(*acpChar++ != HYPHEN){
560  return;
561  }
562  if(*acpChar++ != HYPHEN){
563  return;
564  }
565  }
566  while(acpChar < acpEnd){
567  if(acPrevChar2 == HYPHEN && acPrevChar3 == HYPHEN){
568  return;
569  }
570  acChar = *acpChar;
571  if(acChar == GT){
572  if(acPrevChar1 == HYPHEN && acPrevChar2 == HYPHEN){
573  // success
574  spData->uiCallbackState = ID_MATCH;
575  spData->uiCallbackPhraseLength = uiLen + 5;
576  return;
577  }
578  }
579  acPrevChar3 = acPrevChar2;
580  acPrevChar2 = acPrevChar1;
581  acPrevChar1 = acChar;
582  acpChar++;
583  uiLen++;
584  }
585  }
586 }
587 
588 
589 static int iUdt() {
590  int iReturn = EXIT_SUCCESS;
591  static void* vpMem = NULL;
592  static void* vpApgex = NULL;
593  char* cpGrammar =
594  "tags = start-tag text end-tag\n"
595  " / empty-tag\n"
596  " / u_comment\n"
597  "start-tag = %d60 name %d62\n"
598  "end-tag = %d60.47 name %d62\n"
599  "empty-tag = %d60 name %d47.62\n"
600  "name = %d97-122 *(%d97-122 / %d48-57)\n"
601  "text = *%d97-122\n";
602  char* cpStr = "<start>text</start> <!-- comment --> <empty/>";
603  apgex_result sResult;
604  apg_phrase* spPhrase;
605  exception e;
606  XCTOR(e);
607  if(e.try){
608  // try block
609  vpMem = vpMemCtor(&e);
610  vpApgex = vpApgexCtor(&e);
611 
612  // display the information header
613  char* cpHeader =
614  "This example case illustrates the patterns with User-Defined Terminals, UDTs.\n"
615  "A simple mockup of XML tags is used with a UDT for the comment tag.\n";
616  printf("\n%s", cpHeader);
617  printf("\nThe Grammar\n");
618  printf("%s\n", cpGrammar);
619  printf("The Input String\n");
620  printf("%s\n", cpStr);
621 
622  // beginning of string
623  printf("\nFind all tags.\n");
624  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
625  vApgexPattern(vpApgex, cpGrammar, "g");
626  vApgexDefineUDT(vpApgex, "u_comment", vCommentUdt);
627  vApgexEnableRules(vpApgex, "start-tag, end-tag, empty-tag, u_comment", APG_TRUE);
628  sResult = sApgexExec(vpApgex, spPhrase);
629  while(sResult.spResult){
630  vApgexDisplayResult(vpApgex, &sResult, NULL);
631  sResult = sApgexExec(vpApgex, spPhrase);
632  }
633 
634  }else{
635  // catch block - display the exception location and message
637  vApgexDisplayPatternErrors(vpApgex, NULL);
638  iReturn = EXIT_FAILURE;
639  }
640 
641  // clean up resources
642  vApgexDtor(vpApgex);
643  vMemDtor(vpMem);
644  return iReturn;
645 }
646 static int iTest() {
647  int iReturn = EXIT_SUCCESS;
648  static void* vpMem = NULL;
649  static void* vpApgex = NULL;
650  char* cpGrammar = "word = %s\"abc\"\n";
651  char* cpStr = "Learn your abcs by repeating, abcabcabc over an over again.";
652  abool bTest;
653  char* cpYes = "yes";
654  char* cpNo = "no";
655  apg_phrase* spPhrase;
656  exception e;
657  XCTOR(e);
658  if(e.try){
659  // try block
660  vpMem = vpMemCtor(&e);
661  vpApgex = vpApgexCtor(&e);
662 
663  // display the information header
664  char* cpHeader =
665  "This example case illustrates testing for a match.\n"
666  "The modes are treated exactly the same as for executing a phrase match.\n"
667  "The difference is that testing only gives a yes or no answer. The matched phrase is not captured.\n";
668  printf("\n%s", cpHeader);
669  printf("\nThe Grammar\n");
670  printf("%s\n", cpGrammar);
671  printf("The Input String\n");
672  printf("%s\n", cpStr);
673  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
674 
675  // default from beginning of string
676  printf("\nTest default mode at the beginning of the string.\n");
677  vApgexPattern(vpApgex, cpGrammar, "");
678  bTest = bApgexTest(vpApgex, spPhrase);
679  printf("test = %s\n", (bTest ? cpYes : cpNo));
680 
681  // global for all successes
682  printf("\nTest global mode for all successes.\n");
683  vApgexPattern(vpApgex, cpGrammar, "g");
684  bTest = bApgexTest(vpApgex, spPhrase);
685  printf("test = %s\n", (bTest ? cpYes : cpNo));
686  while(bTest){
687  bTest = bApgexTest(vpApgex, spPhrase);
688  printf("test = %s\n", (bTest ? cpYes : cpNo));
689  }
690 
691  // beginning of string
692  printf("\nTest sticky mode at the beginning of the string.\n");
693  vApgexPattern(vpApgex, cpGrammar, "y");
694  bTest = bApgexTest(vpApgex, spPhrase);
695  printf("test = %s\n", (bTest ? cpYes : cpNo));
696 
697  // at position of first occurrence
698  printf("\nTest sticky mode at the beginning of a pattern.\n");
699  vApgexSetLastIndex(vpApgex, 11);
700  bTest = bApgexTest(vpApgex, spPhrase);
701  printf("test = %s\n", (bTest ? cpYes : cpNo));
702 
703  // consecutive phrases
704  printf("\nTest sticky mode for consecutive patterns.\n");
705  printf("\nFind consecutive phrases.\n");
706  vApgexSetLastIndex(vpApgex, 30);
707  bTest = bApgexTest(vpApgex, spPhrase);
708  printf("test = %s\n", (bTest ? cpYes : cpNo));
709  while(bTest){
710  bTest = bApgexTest(vpApgex, spPhrase);
711  printf("test = %s\n", (bTest ? cpYes : cpNo));
712  }
713 
714  }else{
715  // catch block - display the exception location and message
717  vApgexDisplayPatternErrors(vpApgex, NULL);
718  iReturn = EXIT_FAILURE;
719  }
720 
721  // clean up resources
722  vApgexDtor(vpApgex);
723  vMemDtor(vpMem);
724  return iReturn;
725 }
726 
727 typedef struct{
729  void* vpVecStack;
730 } ast_translate;
731 static aint uiHtml(ast_data* spData){
732  ast_translate* spTrans = (ast_translate*)spData->vpUserData;
733  void* vpTest;
734 
735  // only print from the root node
736  if(spData->uiState == ID_AST_PRE){
737  vpTest = vpVecFirst(spTrans->vpVecStack);
738  if(!vpTest){
739  printf("HTML translating...\n");
740  }
741  }else if(spData->uiState == ID_AST_POST){
742  vpTest = vpVecFirst(spTrans->vpVecStack);
743  if(!vpTest){
744  printf("\n");
745  }
746  }
747  return ID_AST_OK;
748 }
749 static aint uiOpen(ast_data* spData){
750  if(spData->uiState == ID_AST_POST){
751  ast_translate* spTrans = (ast_translate*)spData->vpUserData;
752 
753  // push the name on a stack so that the closing tag will match the tree depth of the opening tag
754  vpVecPush(spTrans->vpVecStack, &spTrans->sNamePhrase);
755  printf("<");
756  aint ui = 0;
757  for(; ui < spTrans->sNamePhrase.uiLength; ui++){
758  char cChar = (char)spTrans->sNamePhrase.acpPhrase[ui];
759  if(cChar >= 65 && cChar <= 90){
760  cChar += 32;
761  }
762  printf("%c", cChar);
763  }
764  printf(">");
765  }
766  return ID_AST_OK;
767 }
768 static aint uiClose(ast_data* spData){
769  if(spData->uiState == ID_AST_POST){
770  ast_translate* spTrans = (ast_translate*)spData->vpUserData;
771 
772  // get the phrase for this tree depth saved by the open tag
773  apg_phrase* spPhrase = (apg_phrase*)vpVecPop(spTrans->vpVecStack);
774  printf("</");
775  aint ui = 0;
776  for(; ui < spPhrase->uiLength; ui++){
777  char cChar = (char)spPhrase->acpPhrase[ui];
778  if(cChar >= 65 && cChar <= 90){
779  cChar += 32;
780  }
781  printf("%c", cChar);
782  }
783  printf(">");
784  }
785  return ID_AST_OK;
786 }
787 static aint uiName(ast_data* spData){
788  if(spData->uiState == ID_AST_POST){
789  // capture the name phrase
790  ast_translate* spTrans = (ast_translate*)spData->vpUserData;
791  spTrans->sNamePhrase.acpPhrase = spData->acpString + spData->uiPhraseOffset;
792  spTrans->sNamePhrase.uiLength = spData->uiPhraseLength;
793  }
794  return ID_AST_OK;
795 }
796 static int iAst() {
797  int iReturn = EXIT_SUCCESS;
798  static void* vpMem = NULL;
799  static void* vpAst = NULL;
800  static void* vpParser = NULL;
801  static void* vpApgex = NULL;
802  char* cpGrammar =
803  "html = (open html close) / (open close)\n"
804  "open = %d60 name %d62\n"
805  "close = %d60.47 name %d62\n"
806  "name = alpha *alphanum\n"
807  "alpha = %d97-122 / %d65-90\n"
808  "alphanum = alpha / %d48-57\n";
809  char* cpStr = "<h1><P></Q></H2>";
810  apg_phrase* spPhrase;
811  apgex_result sResult;
812  ast_translate sTranslate;
813  exception e;
814  XCTOR(e);
815  if(e.try){
816  // try block
817  vpMem = vpMemCtor(&e);
818  vpApgex = vpApgexCtor(&e);
819 
820  // display the information header
821  char* cpHeader =
822  "This example case illustrates the use of the AST for a complex translation of the matched phrase.\n"
823  "The pattern matches HTML-like tags. The translation will normalize the tag names.\n"
824  "Convert to lower case and match closing names to opening names.\n"
825  "Incidentally, this also illustrates matching of recursive patterns.\n";
826  printf("\n%s", cpHeader);
827  printf("\nThe Grammar\n");
828  printf("%s\n", cpGrammar);
829  printf("The Input String\n");
830  printf("%s\n", cpStr);
831  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
832 
833  // default from beginning of string
834  printf("\nTranslate the matched phrase\n");
835  vApgexPattern(vpApgex, cpGrammar, "");
836  sResult = sApgexExec(vpApgex, spPhrase);
837  if(!sResult.spResult){
838  XTHROW(&e, "pattern match failed");
839  }
840 
841  // get the AST and translate
842  vpParser = vpApgexGetParser(vpApgex);
843  vpAst = vpApgexGetAst(vpApgex);
844  void* vpVecStack = vpVecCtor(vpMem, sizeof(apg_phrase), 512);
845  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "html"), uiHtml);
846  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "open"), uiOpen);
847  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "close"), uiClose);
848  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "name"), uiName);
849  sTranslate.vpVecStack = vpVecStack;
850  vAstTranslate(vpAst, &sTranslate);
851 
852  }else{
853  // catch block - display the exception location and message
855  vApgexDisplayPatternErrors(vpApgex, NULL);
856  iReturn = EXIT_FAILURE;
857  }
858 
859  // clean up resources
860  vApgexDtor(vpApgex);
861  vMemDtor(vpMem);
862  return iReturn;
863 }
864 
865 static apg_phrase sMyReplacement(apgex_result* spResult, apgex_properties* spProperties, void* vpUser){
866  apg_phrase* spReturn = NULL;
867  char* cpYes = "yes";
868  char* cpNo = "no";
869  char caBuf[1024];
870  size_t uiBufSize = 1024;
871  int n = 0;
872  n += snprintf(&caBuf[n], (uiBufSize - n), "\nReplaced matched phrase with custom stuff. ");
873  n += snprintf(&caBuf[n], (uiBufSize - n), "\nI have access to the results (node hits = %"PRIuMAX") and ",
874  (luint)spResult->uiNodeHits);
875  n += snprintf(&caBuf[n], (uiBufSize - n), "the properties (default mode = %s.)\n", (spProperties->bDefaultMode ? cpYes : cpNo));
876  spReturn = spUtilStrToPhrase(vpUser, caBuf);
877  return *spReturn;
878 }
879 static int iReplace() {
880  int iReturn = EXIT_SUCCESS;
881  static void* vpMem = NULL;
882  static void* vpApgex = NULL;
883  char* cpGrammar =
884  "word = abc / xyz\n"
885  "abc = \"abc\"\n"
886  "xyz = \"xyz\"\n";
887  char* cpStr = "-abc-xyz-";
888  char* cpSimple = "555";
889  char* cpEscape = "$$";
890  char* cpLeft = "($`)";
891  char* cpRight = "($')";
892  char* cpSelf = "($&)";
893  char* cpRulea = "($<abc>)";
894  char* cpRulex = "($<xyz>)";
895  apg_phrase* spPhrase;
896  apg_phrase* spReplacement;
897  apg_phrase sReplaced;
898  exception e;
899  XCTOR(e);
900  if(e.try){
901  // try block
902  vpMem = vpMemCtor(&e);
903  vpApgex = vpApgexCtor(&e);
904 
905  // display the information header
906  char* cpHeader =
907  "This example case illustrates the replacement of matched phrases with simple phrases and compound phrases.\n"
908  "Simple replacement simply replaces the matched phrase with a specified phrase.\n"
909  "Compound replacement uses various parts of the result for the replacement phrase.\n";
910  printf("\n%s", cpHeader);
911  printf("\nThe Grammar\n");
912  printf("%s\n", cpGrammar);
913  printf("The Input String\n");
914  printf("%s\n", cpStr);
915  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
916 
917  // simple replacement
918  printf("\nSimple replacement in default mode\n");
919  vApgexPattern(vpApgex, cpGrammar, "");
920  spReplacement = spUtilStrToPhrase(vpMem, cpSimple);
921  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
922  if(!sReplaced.acpPhrase){
923  XTHROW(&e, "replacement failed");
924  }
925  printf("Replace matched phrases with %s\n", cpSimple);
926  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
927 
928  printf("\nSimple replacement in global mode\n");
929  vApgexPattern(vpApgex, cpGrammar, "g");
930  spReplacement = spUtilStrToPhrase(vpMem, cpSimple);
931  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
932  if(!sReplaced.acpPhrase){
933  XTHROW(&e, "replacement failed");
934  }
935  printf("Replace matched phrases with %s\n", cpSimple);
936  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
937 
938  // compound replacements
939  vApgexPattern(vpApgex, cpGrammar, "");
940  vApgexEnableRules(vpApgex, "--all", APG_TRUE);
941  spReplacement = spUtilStrToPhrase(vpMem, cpEscape);
942  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
943  if(!sReplaced.acpPhrase){
944  XTHROW(&e, "replacement failed");
945  }
946  printf("Replace matched phrases with %s - escape character\n", cpEscape);
947  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
948 
949  spReplacement = spUtilStrToPhrase(vpMem, cpLeft);
950  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
951  if(!sReplaced.acpPhrase){
952  XTHROW(&e, "replacement failed");
953  }
954  printf("Replace matched phrases with %s - left context\n", cpLeft);
955  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
956 
957  spReplacement = spUtilStrToPhrase(vpMem, cpSelf);
958  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
959  if(!sReplaced.acpPhrase){
960  XTHROW(&e, "replacement failed");
961  }
962  printf("Replace matched phrases with %s - self, the matched phrase\n", cpSelf);
963  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
964 
965  spReplacement = spUtilStrToPhrase(vpMem, cpRight);
966  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
967  if(!sReplaced.acpPhrase){
968  XTHROW(&e, "replacement failed");
969  }
970  printf("Replace matched phrases with %s - the right context\n", cpRight);
971  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
972 
973  spReplacement = spUtilStrToPhrase(vpMem, cpRulea);
974  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
975  if(!sReplaced.acpPhrase){
976  XTHROW(&e, "replacement failed");
977  }
978  printf("Replace matched phrases with %s - the rule 'abc'\n", cpRulea);
979  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
980 
981  spReplacement = spUtilStrToPhrase(vpMem, cpRulex);
982  sReplaced = sApgexReplace(vpApgex, spPhrase, spReplacement);
983  if(!sReplaced.acpPhrase){
984  XTHROW(&e, "replacement failed");
985  }
986  printf("Replace matched phrases with %s - the rule 'xyz'\n", cpRulex);
987  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
988 
989  sReplaced = sApgexReplaceFunc(vpApgex, spPhrase, sMyReplacement, vpMem);
990  if(!sReplaced.acpPhrase){
991  XTHROW(&e, "replacement failed");
992  }
993  printf("Replace matched phrases with custom replacement function.\n");
994  printf("The matched phrases with replacements:\n%s\n", cpUtilPhraseToStr(vpMem, &sReplaced));
995 
996  }else{
997  // catch block - display the exception location and message
999  vApgexDisplayPatternErrors(vpApgex, NULL);
1000  iReturn = EXIT_FAILURE;
1001  }
1002 
1003  // clean up resources
1004  vApgexDtor(vpApgex);
1005  vMemDtor(vpMem);
1006  return iReturn;
1007 }
1008 
1009 static int iSplit() {
1010  int iReturn = EXIT_SUCCESS;
1011  static void* vpMem = NULL;
1012  static void* vpApgex = NULL;
1013  char* cpPatternSep = "sep = *%d32 \";\" *%d32\n";
1014  char* cpPatternEmpty = "sep = \"\"\n";
1015  char* cpPatternLetters = "letters = 1*%d97-122\n";
1016  char* cpStr;
1017  char caStrBuf[1024];
1018  char* cpSub;
1019  apg_phrase* spPhrase;
1020  apg_phrase* spArray;
1021  aint ui, uiCount;
1022  exception e;
1023  XCTOR(e);
1024  if(e.try){
1025  // try block
1026  vpMem = vpMemCtor(&e);
1027  vpApgex = vpApgexCtor(&e);
1028 
1029  // display the information header
1030  char* cpHeader =
1031  "This example case illustrates the using matched phrases as separators to split a phrase into an array of sub-phrases.\n";
1032  printf("\n%s", cpHeader);
1033 
1034  // split at separator
1035  printf("\nThe Separator Pattern\n");
1036  printf("%s\n", cpPatternSep);
1037  printf("The Input Phrase\n");
1038  cpStr = "one ; two;three";
1039  printf("'%s'\n", cpStr);
1040  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
1041  vApgexPattern(vpApgex, cpPatternSep, "");
1042  spArray = spApgexSplit(vpApgex, spPhrase, 0, &uiCount);
1043  if(!uiCount){
1044  XTHROW(&e, "split failed");
1045  }
1046  printf("\nArray of sub-phrases - split at separators\n");
1047  for(ui = 0; ui < uiCount; ui++){
1048  cpSub = cpPhraseToStr(&spArray[ui], caStrBuf);
1049  printf("index: %d: phrase: %s\n", (int)ui, cpSub);
1050 
1051  }
1052 
1053  printf("\nThe Separator Pattern\n");
1054  printf("%s\n", cpPatternSep);
1055  printf("The Input Phrase - separator is entire string, array is empty\n");
1056  cpStr = " ; ";
1057  printf("'%s'\n", cpStr);
1058  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
1059  vApgexPattern(vpApgex, cpPatternSep, "");
1060  spArray = spApgexSplit(vpApgex, spPhrase, 0, &uiCount);
1061  if(uiCount){
1062  XTHROW(&e, "split failed");
1063  }
1064  printf("\nArray of sub-phrases - separator is entire string, array is empty\n");
1065  printf("none\n");
1066 
1067  printf("\nThe Separator Pattern\n");
1068  printf("%s\n", cpPatternSep);
1069  printf("The Input Phrase\n");
1070  cpStr = "word";
1071  printf("'%s'\n", cpStr);
1072  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
1073  vApgexPattern(vpApgex, cpPatternSep, "");
1074  spArray = spApgexSplit(vpApgex, spPhrase, 0, &uiCount);
1075  if(!uiCount){
1076  XTHROW(&e, "split failed");
1077  }
1078  printf("\nArray of sub-phrases - no separators, array is the whole string\n");
1079  for(ui = 0; ui < uiCount; ui++){
1080  cpSub = cpPhraseToStr(&spArray[ui], caStrBuf);
1081  printf("index: %d: phrase: %s\n", (int)ui, cpSub);
1082 
1083  }
1084 
1085  printf("\nThe Separator Pattern\n");
1086  printf("%s\n", cpPatternEmpty);
1087  printf("The Input Phrase\n");
1088  cpStr = "word";
1089  printf("'%s'\n", cpStr);
1090  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
1091  vApgexPattern(vpApgex, cpPatternEmpty, "");
1092  spArray = spApgexSplit(vpApgex, spPhrase, 0, &uiCount);
1093  if(!uiCount){
1094  XTHROW(&e, "split failed");
1095  }
1096  printf("\nArray of sub-phrases - separate into individual characters\n");
1097  for(ui = 0; ui < uiCount; ui++){
1098  cpSub = cpPhraseToStr(&spArray[ui], caStrBuf);
1099  printf("index: %d: phrase: %s\n", (int)ui, cpSub);
1100 
1101  }
1102 
1103  printf("\nThe Separator Pattern\n");
1104  printf("%s\n", cpPatternLetters);
1105  printf("The Input Phrase\n");
1106  cpStr = "123abc4d56e";
1107  printf("'%s'\n", cpStr);
1108  spPhrase = spUtilStrToPhrase(vpMem, cpStr);
1109  vApgexPattern(vpApgex, cpPatternLetters, "");
1110  spArray = spApgexSplit(vpApgex, spPhrase, 0, &uiCount);
1111  if(!uiCount){
1112  XTHROW(&e, "split failed");
1113  }
1114  printf("\nArray of sub-phrases - letters as separators\n");
1115  for(ui = 0; ui < uiCount; ui++){
1116  cpSub = cpPhraseToStr(&spArray[ui], caStrBuf);
1117  printf("index: %d: phrase: %s\n", (int)ui, cpSub);
1118 
1119  }
1120 
1121  }else{
1122  // catch block - display the exception location and message
1123  vUtilPrintException(&e);
1124  vApgexDisplayPatternErrors(vpApgex, NULL);
1125  iReturn = EXIT_FAILURE;
1126  }
1127 
1128  // clean up resources
1129  vApgexDtor(vpApgex);
1130  vMemDtor(vpMem);
1131  return iReturn;
1132 }
1133 
1134 static int iBoundaries() {
1135  int iReturn = EXIT_SUCCESS;
1136  static void* vpMem = NULL;
1137  static void* vpApgex = NULL;
1138  char* cpWordPattern =
1139  "word-to-find = abw \"cat\" aew\n"
1140  "word-char = %d65-90/%d97-122\n"
1141  "abw = (!!word-char / %^) ; define word beginning\n"
1142  "aew = (!word-char / %$) ; define word end\n";
1143  char* cpLinePattern =
1144  "phrase-to-find = abl \"The \" animal \" in the hat.\" ael\n"
1145  "animal = \"cat\" / \"dog\" / \"bird\" / \"mouse\"\n"
1146  "line-end = %d13.10 / %d10 / %d13\n"
1147  "abl = (&&line-end / %^) ; define line beginning\n"
1148  "ael = (&line-end / %$) ; define line end\n";
1149  char* cpWordStr = "Cat - a Bobcat is a cat but a caterpillar is not a cat.";
1150  char* cpLineStr =
1151  "The cat in the hat.\n"
1152  "The dog in the hat.\r\n"
1153  "The bird in the hat.\r"
1154  "The dog is not in the hat.\n"
1155  "The cat in the hat is black.\n"
1156  "The mouse in the hat.";
1157  apg_phrase* spPhrase;
1158  apgex_result sResult;
1159  exception e;
1160  XCTOR(e);
1161  if(e.try){
1162  // try block
1163  vpMem = vpMemCtor(&e);
1164  vpApgex = vpApgexCtor(&e);
1165 
1166  // display the information header
1167  char* cpHeader =
1168  "This example case illustrates the definition and use of word and line boundaries.\n"
1169  "Unlike most \"regex\" engines, apgex makes no assumptions about what constitutes\n"
1170  "a word or line boundary. Nonetheless it is very easy, using look around and anchors,\n"
1171  "to define word and line boundaries according to the needs of the problem at hand.\n";
1172  printf("\n%s", cpHeader);
1173 
1174  // word boundaries
1175  printf("\nFind Words\n");
1176  printf("%s\n", cpWordPattern);
1177  printf("The Input Phrase\n");
1178  printf("'%s'\n", cpWordStr);
1179  spPhrase = spUtilStrToPhrase(vpMem, cpWordStr);
1180  vApgexPattern(vpApgex, cpWordPattern, "g");
1181  sResult = sApgexExec(vpApgex, spPhrase);
1182  while(sResult.spResult){
1183  vApgexDisplayResult(vpApgex, &sResult, NULL);
1184  sResult = sApgexExec(vpApgex, spPhrase);
1185  }
1186 
1187  // line boundaries
1188  printf("\nFind Lines\n");
1189  printf("%s\n", cpLinePattern);
1190  printf("The Input Phrase\n");
1191  printf("'%s'\n", cpLineStr);
1192  spPhrase = spUtilStrToPhrase(vpMem, cpLineStr);
1193  vApgexPattern(vpApgex, cpLinePattern, "g");
1194  sResult = sApgexExec(vpApgex, spPhrase);
1195  while(sResult.spResult){
1196  vApgexDisplayResult(vpApgex, &sResult, NULL);
1197  sResult = sApgexExec(vpApgex, spPhrase);
1198  }
1199 
1200  }else{
1201  // catch block - display the exception location and message
1202  vUtilPrintException(&e);
1203  vApgexDisplayPatternErrors(vpApgex, NULL);
1204  iReturn = EXIT_FAILURE;
1205  }
1206 
1207  // clean up resources
1208  vApgexDtor(vpApgex);
1209  vMemDtor(vpMem);
1210  return iReturn;
1211 }
1212 
1213 #define DQUOTE 34
1214 static char s_cZero = 0;
1215 static aint uiRecord(ast_data* spData){
1216  if(spData->uiState == ID_AST_POST){
1217  printf("\n");
1218  }
1219  return ID_AST_OK;
1220 }
1221 
1222 static aint uiNonEscaped(ast_data* spData){
1223  if(spData->uiState == ID_AST_POST){
1224  void* vpVec = spData->vpUserData;
1225  const achar* acpChar = spData->acpString + spData->uiPhraseOffset;
1226  const achar* acpEnd = acpChar + spData->uiPhraseLength;
1227  char cChar;
1228  vVecClear(vpVec);
1229  while(acpChar < acpEnd){
1230  cChar = (char)*acpChar++;
1231  vpVecPush(vpVec, &cChar);
1232  }
1233  vpVecPush(vpVec, &s_cZero);
1234  char* cpStr = (char*)vpVecFirst(vpVec);
1235  printf("[%-15s]", cpStr);
1236  }
1237  return ID_AST_OK;
1238 }
1239 
1240 static aint uiEscaped(ast_data* spData){
1241  void* vpVec = spData->vpUserData;
1242  if(spData->uiState == ID_AST_PRE){
1243  vVecClear(vpVec);
1244  }else if(spData->uiState == ID_AST_POST){
1245  vpVecPush(vpVec, &s_cZero);
1246  char* cpStr = (char*)vpVecFirst(vpVec);
1247  printf("[%-15s]", cpStr);
1248  }
1249  return ID_AST_OK;
1250 }
1251 
1252 static aint uiText(ast_data* spData){
1253  if(spData->uiState == ID_AST_POST){
1254  void* vpVec = spData->vpUserData;
1255  const achar* acpChar = spData->acpString + spData->uiPhraseOffset;
1256  char cChar = (char)*acpChar;
1257  vpVecPush(vpVec, &cChar);
1258  }
1259  return ID_AST_OK;
1260 }
1261 
1262 static aint uiDdquote(ast_data* spData){
1263  if(spData->uiState == ID_AST_POST){
1264  void* vpVec = spData->vpUserData;
1265  char cChar = DQUOTE;
1266  vpVecPush(vpVec, &cChar);
1267  }
1268  return ID_AST_OK;
1269 }
1270 
1271 static int iCSV() {
1272  int iReturn = EXIT_SUCCESS;
1273  static void* vpMem = NULL;
1274  static void* vpVec = NULL;
1275  static void* vpAst = NULL;
1276  static void* vpParser = NULL;
1277  static void* vpApgex = NULL;
1278  char* cpCSVPattern =
1279  "; the record and field formats from RFC4180\n"
1280  "; slightly modified for easier phrase capture and replacement\n"
1281  "record = field *(COMMA field) [CRLF]\n"
1282  "field = (escaped / non-escaped)\n"
1283  "escaped = LQUOTE *(text / DDQUOTE) RQUOTE\n"
1284  "text = TEXTDATA / COMMA / CR / LF\n"
1285  "DDQUOTE = 2%x22\n"
1286  "non-escaped = *TEXTDATA\n"
1287  "COMMA = %x2C\n"
1288  "CR = %x0D\n"
1289  "LQUOTE = %x22\n"
1290  "RQUOTE = %x22\n"
1291  "LF = %x0A\n"
1292  "CRLF = CR LF / LF / CR ; modified from RFC4180 to include all forms of line ends\n"
1293  "TEXTDATA = %x20-21 / %x23-2B / %x2D-7E\n";
1294  char* cpFileStr =
1295  "ITEM,DESCRIPTION,VALUE\n"
1296  "Cup,\"coffee,tea,etc\",$10.00\n"
1297  "Camero,Sedan,\"$25,000\"\n"
1298  "Empty Desc.,,\"$0,000\"\n"
1299  "Junker,empty price,\n"
1300  "Aston Martin,\"$316,300\",\"He said, \"\"That's way too much moola, man.\"\"\"\n";
1301  apg_phrase* spPhrase;
1302  char caBuf[1024];
1303  aint uiBufSize = 1024;
1304  aint ui, uj;
1305  const char* cpaStrings[10];
1306  const char* cpStr;
1307  apgex_result sResult;
1308  apgex_rule* spRule;
1309  apg_phrase* spRulePhrase;
1310  exception e;
1311  XCTOR(e);
1312  if(e.try){
1313  // try block
1314  vpMem = vpMemCtor(&e);
1315  vpApgex = vpApgexCtor(&e);
1316 
1317  // display the information header
1318  char* cpHeader =
1319  "This example case illustrates the use of apgex for extracting the values from\n"
1320  "Comma Separated Value (CSV) formatted data. There seems to be no standard format\n"
1321  "but the field format used here is from RFC 4180. For comparison to \"regex\"\n"
1322  "see the solution for the similar Microsoft format described in Jeffrey Friedl's\n"
1323  "book \"Mastering Regular Expressions\", O'Reilly, 2006, pg. 213.\n";
1324  printf("\n%s", cpHeader);
1325 
1326  printf("\nThe Pattern\n");
1327  printf("%s\n", cpCSVPattern);
1328  printf("\nThe CSV File\n");
1329  printf("%s\n", cpFileStr);
1330 
1331  // raw fields
1332  printf("\nDisplay the raw fields in each record.\n");
1333  spPhrase = spUtilStrToPhrase(vpMem, cpFileStr);
1334  vApgexPattern(vpApgex, cpCSVPattern, "g");
1335  vApgexEnableRules(vpApgex, "field", APG_TRUE);
1336  sResult = sApgexExec(vpApgex, spPhrase);
1337  while(sResult.spResult){
1338  spRule = sResult.spRules;
1339  for(ui = 0; ui < spRule->uiPhraseCount; ui++){
1340  spRulePhrase = &spRule->spPhrases[ui].sPhrase;
1341  cpaStrings[ui] = cpUtilPhraseToStr(vpMem, spRulePhrase);
1342  printf("[%-15s]", cpaStrings[ui]);
1343  }
1344  printf("\n");
1345  sResult = sApgexExec(vpApgex, spPhrase);
1346  }
1347 
1348  // useful fields
1349  printf("\nExtract unquoted fields.\n");
1350  printf("Brute Force\n");
1351  spPhrase = spUtilStrToPhrase(vpMem, cpFileStr);
1352  vApgexPattern(vpApgex, cpCSVPattern, "g");
1353  vApgexEnableRules(vpApgex, "--all", APG_FALSE);
1354  vApgexEnableRules(vpApgex, "field", APG_TRUE);
1355  sResult = sApgexExec(vpApgex, spPhrase);
1356  while(sResult.spResult){
1357  spRule = sResult.spRules;
1358  for(ui = 0; ui < spRule->uiPhraseCount; ui++){
1359  spRulePhrase = &spRule->spPhrases[ui].sPhrase;
1360  cpStr = cpUtilPhraseToStr(vpMem, spRulePhrase);
1361  if(cpStr[0] == DQUOTE){
1362  aint uiLen = (aint)strlen(cpStr);
1363  if(uiLen >= uiBufSize){
1364  XTHROW(&e, "buffer size too small for field conversion");
1365  }
1366  aint uiNewLen = 0;
1367  caBuf[uiNewLen] = 0;
1368  if(uiLen > 2){
1369  for(uj = 1; uj < (uiLen - 1); uj++){
1370  if(cpStr[uj] == DQUOTE){
1371  caBuf[uiNewLen++] = DQUOTE;
1372  uj++;
1373  }else{
1374  caBuf[uiNewLen++] = cpStr[uj];
1375  }
1376  }
1377  caBuf[uiNewLen++] = 0;
1378  }
1379  printf("[%-15s]", caBuf);
1380  }else{
1381  printf("[%-15s]", cpStr);
1382  }
1383  vMemFree(vpMem, cpStr);
1384  }
1385  printf("\n");
1386  sResult = sApgexExec(vpApgex, spPhrase);
1387  }
1388 
1389  // AST translation fields
1390  printf("\nExtract unquoted fields.\n");
1391  printf("AST Translation\n");
1392  vpVec = vpVecCtor(vpMem, sizeof(char), 1024);
1393  spPhrase = spUtilStrToPhrase(vpMem, cpFileStr);
1394  vApgexPattern(vpApgex, cpCSVPattern, "g");
1395  vpAst = vpApgexGetAst(vpApgex);
1396  vpParser = vpApgexGetParser(vpApgex);
1397  vApgexEnableRules(vpApgex, "--all", APG_FALSE);
1398  vApgexEnableRules(vpApgex, "record, ddquote, text, non-escaped, escaped", APG_TRUE);
1399  sResult = sApgexExec(vpApgex, spPhrase);
1400  while(sResult.spResult){
1401  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "record"), uiRecord);
1402  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "escaped"), uiEscaped);
1403  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "non-escaped"), uiNonEscaped);
1404  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "text"), uiText);
1405  vAstSetRuleCallback(vpAst, uiParserRuleLookup(vpParser, "ddquote"), uiDdquote);
1406  vAstTranslate(vpAst, vpVec);
1407  sResult = sApgexExec(vpApgex, spPhrase);
1408  }
1409 
1410  }else{
1411  // catch block - display the exception location and message
1412  vUtilPrintException(&e);
1413  vApgexDisplayPatternErrors(vpApgex, NULL);
1414  iReturn = EXIT_FAILURE;
1415  }
1416 
1417  // clean up resources
1418  vApgexDtor(vpApgex);
1419  vMemDtor(vpMem);
1420  return iReturn;
1421 }
1422 
1423 static int iWide() {
1424  int iReturn = EXIT_SUCCESS;
1425  static void* vpMem = NULL;
1426  static void* vpFmt = NULL;
1427  static void* vpApgex = NULL;
1428  char* cpCherokee =
1429  "word = 1*%x13A0-13F4\n";
1430  apg_phrase sPhrase;
1431  apg_phrase* spWord;
1432  const char* cpInput;
1433  char caInputBuf[PATH_MAX];
1434  const char* cpLine;
1435  uint8_t ucaBuf[1024];
1436  aint uiBufSize = 1024;
1437  aint uiSize;
1438  apgex_result sResult;
1439  exception e;
1440  XCTOR(e);
1441  if(e.try){
1442  // try block
1443  vpMem = vpMemCtor(&e);
1444  vpFmt = vpFmtCtor(&e);
1445  vpApgex = vpApgexCtor(&e);
1446 
1447  // display the information header
1448  char* cpHeader =
1449  "This example case illustrates patterns with Unicode UTF-32 characters.\n"
1450  "The pattern will match Cherokee words in 32-bit UTF-32 format.\n";
1451  printf("\n%s", cpHeader);
1452 
1453  // validate the alphabet character width
1454  if(sizeof(achar) != 4){
1455  XTHROW(&e, "recompile with APG_ACHAR=32, sizeof(achar) must = 4");
1456  }
1457 
1458  if(bIsBigEndian()){
1459  cpInput = cpMakeFileName(caInputBuf, SOURCE_DIR, "/../input/", "cherokee.utf32be");
1460  }else{
1461  cpInput = cpMakeFileName(caInputBuf, SOURCE_DIR, "/../input/", "cherokee.utf32le");
1462  }
1463  uiSize = uiBufSize;
1464  vUtilFileRead(vpMem, cpInput, ucaBuf, &uiSize);
1465  if(uiSize > uiBufSize){
1466  XTHROW(&e, "buffer size too small for input file");
1467  }
1468 
1469  // word boundaries
1470  printf("\nThe Cherokee Word Pattern\n");
1471  printf("%s\n", cpCherokee);
1472 
1473  printf("The Input Phrase\n");
1474  cpLine = cpFmtFirstUnicode(vpFmt, (uint32_t*)ucaBuf, (uint64_t)(uiSize / 4), 0, 0);
1475  while(cpLine){
1476  printf("%s", cpLine);
1477  cpLine = cpFmtNext(vpFmt);
1478  }
1479 
1480  printf("\nThe Cherokee Words\n");
1481  vApgexPattern(vpApgex, cpCherokee, "g");
1482  sPhrase.acpPhrase = (achar*)ucaBuf;
1483  sPhrase.uiLength = uiSize / 4;
1484  sResult = sApgexExec(vpApgex, &sPhrase);
1485  while(sResult.spResult){
1486  spWord = &sResult.spResult->sPhrase;
1487  cpLine = cpFmtFirstUnicode(vpFmt, (uint32_t*)spWord->acpPhrase, spWord->uiLength, 0, 0);
1488  while(cpLine){
1489  printf("%s", cpLine);
1490  cpLine = cpFmtNext(vpFmt);
1491  }
1492  sResult = sApgexExec(vpApgex, &sPhrase);
1493  }
1494 
1495  }else{
1496  // catch block - display the exception location and message
1497  vUtilPrintException(&e);
1498  vApgexDisplayPatternErrors(vpApgex, NULL);
1499  iReturn = EXIT_FAILURE;
1500  }
1501 
1502  // clean up resources
1503  vApgexDtor(vpApgex);
1504  vFmtDtor(vpFmt);
1505  vMemDtor(vpMem);
1506  return iReturn;
1507 }
1508 
1509 static int iBackReference() {
1510  int iReturn = EXIT_SUCCESS;
1511  static void* vpMem = NULL;
1512  static void* vpApgex = NULL;
1513  char* cpPatternUI =
1514  "pattern = %^ tag %$\n"
1515  "tag = (open tag close) / (open close)\n"
1516  "name = 1*alpha\n"
1517  "alpha = %d97-122 / %d65-90\n"
1518  "open = %d60 name %d62\n"
1519  "close = %d60.47 \\name %d62\n";
1520  char* cpPatternUS =
1521  "pattern = %^ tag %$\n"
1522  "tag = (open tag close) / (open close)\n"
1523  "name = 1*alpha\n"
1524  "alpha = %d97-122 / %d65-90\n"
1525  "open = %d60 name %d62\n"
1526  "close = %d60.47 \\%s%uname %d62\n";
1527  char* cpPatternPI =
1528  "pattern = %^ tag %$\n"
1529  "tag = (open tag close) / (open close)\n"
1530  "name = 1*alpha\n"
1531  "alpha = %d97-122 / %d65-90\n"
1532  "open = %d60 name %d62\n"
1533  "close = %d60.47 \\%pname %d62\n";
1534  char* cpPatternPS =
1535  "pattern = %^ tag %$\n"
1536  "tag = (open tag close) / (open close)\n"
1537  "name = 1*alpha\n"
1538  "alpha = %d97-122 / %d65-90\n"
1539  "open = %d60 name %d62\n"
1540  "close = %d60.47 \\%p%sname %d62\n";
1541  char* cpTagsUI = "<div><span></SPAN></SPAN>";
1542  char* cpTagsUS = "<div><span></span></span>";
1543  char* cpTagsPI = "<div><span></SPAN></DIV>";
1544  char* cpTagsPS = "<div><span></span></div>";
1545  apg_phrase* spPhraseUI, *spPhraseUS, *spPhrasePI, *spPhrasePS;
1546  abool bResult;
1547  exception e;
1548  XCTOR(e);
1549  if(e.try){
1550  // try block
1551  vpMem = vpMemCtor(&e);
1552  vpApgex = vpApgexCtor(&e);
1553 
1554  // display the information header
1555  char* cpHeader =
1556  "This example case illustrates back references in both \"universal\" and \"parent\" modes.\n"
1557  "The patterns match XML-like tags. The strings have both matching and non-matching node names.\n"
1558  "The opening and closing tags have both case-sensitive and case-insensitive corresponding names.\n"
1559  "Phrase-matching results are shown for all possible combinations, illustrating the differences\n"
1560  "between the different modes and case sensitivities.\n"
1561  "Note that, due to the begin-or-string and end-of-string anchors,\n"
1562  "the patterns require that the entire source phrase must be matched.\n";
1563  printf("\n%s", cpHeader);
1564  spPhraseUI = spUtilStrToPhrase(vpMem, cpTagsUI);
1565  spPhraseUS = spUtilStrToPhrase(vpMem, cpTagsUS);
1566  spPhrasePI = spUtilStrToPhrase(vpMem, cpTagsPI);
1567  spPhrasePS = spUtilStrToPhrase(vpMem, cpTagsPS);
1568 
1569  printf("\nUniversal I: universal mode, case insenstive pattern\n");
1570  printf("%s", cpPatternUI);
1571  printf("\nUniversal S: universal mode, case senstive pattern\n");
1572  printf("%s", cpPatternUS);
1573  printf("\nParent I: parent mode, case insenstive pattern\n");
1574  printf("%s", cpPatternPI);
1575  printf("\nParent S: parent mode, case senstive pattern\n");
1576  printf("%s", cpPatternPS);
1577 
1578  // universal case insensitive
1579  printf("\n%-12s %-26s %-10s\n", "grammar", "source", "result");
1580  vApgexPattern(vpApgex, cpPatternUI, "");
1581  bResult = bApgexTest(vpApgex, spPhraseUI);
1582  printf("%-12s %-26s %-10s\n", "Universal I", cpTagsUI, cpUtilTrueFalse(bResult));
1583  bResult = bApgexTest(vpApgex, spPhraseUS);
1584  printf("%-12s %-26s %-10s\n", "Universal I", cpTagsUS, cpUtilTrueFalse(bResult));
1585  bResult = bApgexTest(vpApgex, spPhrasePI);
1586  printf("%-12s %-26s %-10s\n", "Universal I", cpTagsPI, cpUtilTrueFalse(bResult));
1587  bResult = bApgexTest(vpApgex, spPhrasePS);
1588  printf("%-12s %-26s %-10s\n", "Universal I", cpTagsPS, cpUtilTrueFalse(bResult));
1589  printf("\n");
1590 
1591  // universal case sensitive
1592  vApgexPattern(vpApgex, cpPatternUS, "");
1593  bResult = bApgexTest(vpApgex, spPhraseUI);
1594  printf("%-12s %-26s %-10s\n", "Universal S", cpTagsUI, cpUtilTrueFalse(bResult));
1595  bResult = bApgexTest(vpApgex, spPhraseUS);
1596  printf("%-12s %-26s %-10s\n", "Universal S", cpTagsUS, cpUtilTrueFalse(bResult));
1597  bResult = bApgexTest(vpApgex, spPhrasePI);
1598  printf("%-12s %-26s %-10s\n", "Universal S", cpTagsPI, cpUtilTrueFalse(bResult));
1599  bResult = bApgexTest(vpApgex, spPhrasePS);
1600  printf("%-12s %-26s %-10s\n", "Universal S", cpTagsPS, cpUtilTrueFalse(bResult));
1601  printf("\n");
1602 
1603  // parent case insensitive
1604  vApgexPattern(vpApgex, cpPatternPI, "");
1605  bResult = bApgexTest(vpApgex, spPhraseUI);
1606  printf("%-12s %-26s %-10s\n", "Parent I", cpTagsUI, cpUtilTrueFalse(bResult));
1607  bResult = bApgexTest(vpApgex, spPhraseUS);
1608  printf("%-12s %-26s %-10s\n", "Parent I", cpTagsUS, cpUtilTrueFalse(bResult));
1609  bResult = bApgexTest(vpApgex, spPhrasePI);
1610  printf("%-12s %-26s %-10s\n", "Parent I", cpTagsPI, cpUtilTrueFalse(bResult));
1611  bResult = bApgexTest(vpApgex, spPhrasePS);
1612  printf("%-12s %-26s %-10s\n", "Parent I", cpTagsPS, cpUtilTrueFalse(bResult));
1613  printf("\n");
1614 
1615  // parent case sensitive
1616  vApgexPattern(vpApgex, cpPatternPS, "");
1617  bResult = bApgexTest(vpApgex, spPhraseUS);
1618  printf("%-12s %-26s %-10s\n", "Parent S", cpTagsUI, cpUtilTrueFalse(bResult));
1619  bResult = bApgexTest(vpApgex, spPhraseUS);
1620  printf("%-12s %-26s %-10s\n", "Parent S", cpTagsUS, cpUtilTrueFalse(bResult));
1621  bResult = bApgexTest(vpApgex, spPhrasePI);
1622  printf("%-12s %-26s %-10s\n", "Parent S", cpTagsPI, cpUtilTrueFalse(bResult));
1623  bResult = bApgexTest(vpApgex, spPhrasePS);
1624  printf("%-12s %-26s %-10s\n", "Parent S", cpTagsPS, cpUtilTrueFalse(bResult));
1625  printf("\n");
1626 
1627  }else{
1628  // catch block - display the exception location and message
1629  vUtilPrintException(&e);
1630  vApgexDisplayPatternErrors(vpApgex, NULL);
1631  iReturn = EXIT_FAILURE;
1632  }
1633 
1634  // clean up resources
1635  vApgexDtor(vpApgex);
1636  vMemDtor(vpMem);
1637  return iReturn;
1638 }
1639 
1647 int main(int argc, char **argv) {
1648  long int iCase = 0;
1649  if(argc > 1){
1650  iCase = atol(argv[1]);
1651  }
1652  if((iCase > 0) && (iCase <= s_iCaseCount)){
1653  printf("%s\n", s_cppCases[iCase -1]);
1654  }
1655  switch(iCase){
1656  case 1:
1657  return iApp();
1658  case 2:
1659  return iPatterns();
1660  case 3:
1661  return iResults();
1662  case 4:
1663  return iProperties();
1664  case 5:
1665  return iGlobalMode();
1666  case 6:
1667  return iStickyMode();
1668  case 7:
1669  return iTraceMode();
1670  case 8:
1671  return iUdt();
1672  case 9:
1673  return iTest();
1674  case 10:
1675  return iAst();
1676  case 11:
1677  return iReplace();
1678  case 12:
1679  return iSplit();
1680  case 13:
1681  return iBoundaries();
1682  case 14:
1683  return iCSV();
1684  case 15:
1685  return iWide();
1686  case 16:
1687  return iBackReference();
1688  default:
1689  return iHelp();
1690  }
1691 }
1692 
vTraceSetOutput
void vTraceSetOutput(void *vpCtx, const char *cpFileName)
Definition: trace.c:172
apgex_result::uiNodeHits
aint uiNodeHits
The number of parser node hits.
Definition: apgex.h:83
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
apgex_rule::spPhrases
apgex_phrase * spPhrases
The list of matched phrases. Any given rule or UDT may have multiple matched sub-phrases.
Definition: apgex.h:60
cpUtilPhraseToStr
const char * cpUtilPhraseToStr(void *vpMem, apg_phrase *spPhrase)
Convert an apg_phrase to a null-terminated ASCII string.
Definition: utilities.c:925
vUtilFileRead
void vUtilFileRead(void *vpMem, const char *cpFileName, uint8_t *ucpData, aint *uipLen)
Read a file into the caller's data area.
Definition: utilities.c:252
apgex_rule::uiPhraseCount
aint uiPhraseCount
The number of matched sub-phrases for this rule/UDT.
Definition: apgex.h:61
sApgexReplace
apg_phrase sApgexReplace(void *vpCtx, apg_phrase *spSource, apg_phrase *spReplacement)
Replace the matched phrase with a specified phrase.
Definition: apgex.c:528
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
vApgexPatternFile
void vApgexPatternFile(void *vpCtx, const char *cpFileName, const char *cpFlags)
Reads the SABNF grammar defining the pattern from a file.
Definition: apgex.c:404
ast_data::uiPhraseOffset
aint uiPhraseOffset
Definition: ast.h:72
apgex_properties
Detailed information about the apgex object after vApgexPattern() has been called.
Definition: apgex.h:94
vApiInClear
void vApiInClear(void *vpCtx)
Clears the input and related memory.
Definition: input.c:61
vAstSetRuleCallback
void vAstSetRuleCallback(void *vpCtx, aint uiRuleIndex, ast_callback pfnCallback)
Define a callback function for a single rule on the AST.
Definition: ast.c:243
vApgexDefineUDT
void vApgexDefineUDT(void *vpCtx, const char *cpName, parser_callback pfnUdt)
Define the callback function for a User-Defined Terminal (UDT).
Definition: apgex.c:1222
callback_data::uiParserOffset
aint uiParserOffset
[read only] Offset from acpString to the first character to match
Definition: parser.h:160
sApgexExec
apgex_result sApgexExec(void *vpCtx, apg_phrase *spSource)
Attempt a pattern match on the source array of APG alphabet characters.
Definition: apgex.c:479
callback_data::acpString
const achar * acpString
[read only] Pointer to the input sub-string,
Definition: parser.h:156
ID_AST_POST
#define ID_AST_POST
indicates post-node-traversal AST callback state (up the tree)
Definition: parser.h:92
vpApiCtor
void * vpApiCtor(exception *spEx)
Construct an API component context (object).
Definition: api.c:55
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
ast_translate
Definition: main.c:727
uiParserRuleLookup
aint uiParserRuleLookup(void *vpCtx, const char *cpRuleName)
Find the rule index corresponding to a rule name.
Definition: parser.c:440
ID_AST_OK
#define ID_AST_OK
normal AST callback function return
Definition: parser.h:93
ID_AST_PRE
#define ID_AST_PRE
indicates pre-node-traversal AST callback state (down the tree)
Definition: parser.h:91
ast_data
Input data to the AST callback functions.
Definition: ast.h:69
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
vApgexPattern
void vApgexPattern(void *vpCtx, const char *cpPattern, const char *cpFlags)
Prepare a phrase-matching parser for the given pattern.
Definition: apgex.c:378
apgex_result
The phrase matching results.
Definition: apgex.h:72
vAstTranslate
void vAstTranslate(void *vpCtx, void *vpUserData)
Do a depth-first traversal of the AST with user-defined callback functions to translate the AST recor...
Definition: ast.c:165
cpFmtNext
const char * cpFmtNext(void *vpCtx)
Formats the next line of data.
Definition: format.c:386
vApiDtor
void vApiDtor(void *vpCtx)
The API component destructor.
Definition: api.c:84
cpUtilTrueFalse
const char * cpUtilTrueFalse(luint luiTrue)
Return a human-readable string version of the given value in its true/false sense.
Definition: utilities.c:646
ast_data::uiPhraseLength
aint uiPhraseLength
Definition: ast.h:73
apgex_properties::bDefaultMode
abool bDefaultMode
True if the cpFlags parameter in vApgexPattern() is NULL or empty.
Definition: apgex.h:110
cpFmtFirstUnicode
const char * cpFmtFirstUnicode(void *vpCtx, const uint32_t *uipChars, uint64_t uiLength, uint64_t uiOffset, uint64_t uiLimit)
Initiate the iterator over an array of 32-bit Unicode code points.
Definition: format.c:341
DQUOTE
#define DQUOTE
Definition: main.c:1213
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
BANG
#define BANG
Definition: main.c:538
vpVecPop
void * vpVecPop(void *vpCtx)
Pops one element from the end of the array.
Definition: vector.c:250
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
apgex_result::spResult
apgex_phrase * spResult
The matched phrase. NULL if no match.
Definition: apgex.h:73
apgex_properties::uiLastIndex
aint uiLastIndex
The index of the character in the input string where the attempted pattern match begins....
Definition: apgex.h:108
vApiFile
void vApiFile(void *vpCtx, const char *cpFileName, abool bStrict, abool bPppt)
Quicky way to generate a parser from a grammar file.
Definition: api.c:517
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
callback_data::uiCallbackState
aint uiCallbackState
[input/output] Rule name (RNM) callback functions: If ID_ACTIVE, the parser takes no action....
Definition: parser.h:139
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
vpApgexCtor
void * vpApgexCtor(exception *spEx)
The phrase-matching engine object constructor.
Definition: apgex.c:239
ast_data::uiState
aint uiState
Definition: ast.h:74
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
apgex_result::uiLastIndex
aint uiLastIndex
The last index following the last pattern match attempt.
Definition: apgex.h:81
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
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
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
vpApgexGetParser
void * vpApgexGetParser(void *vpCtx)
Get a pointer to the parser object's context.
Definition: apgex.c:1009
callback_data::uiCallbackPhraseLength
aint uiCallbackPhraseLength
[input/output] The phrase length of the matched phrase if the callback function returns ID_MATCH.
Definition: parser.h:145
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
vpApiOutputParser
void * vpApiOutputParser(void *vpCtx)
Generate a parser object directly from the specified SABNF grammar.
Definition: output.c:217
vpApgexGetTrace
void * vpApgexGetTrace(void *vpCtx)
Get a pointer to the trace object's context.
Definition: apgex.c:984
callback_data
The data struct passed to each callback function.
Definition: parser.h:134
ast_data::acpString
const achar * acpString
Definition: ast.h:70
vApgexDisplayResult
void vApgexDisplayResult(void *vpCtx, apgex_result *spResult, const char *cpFileName)
Display the complete results from a pattern match.
Definition: apgex.c:1129
vApgexDisplayProperties
void vApgexDisplayProperties(void *vpCtx, apgex_properties *spProperties, const char *cpFileName)
Display the object's properties.
Definition: apgex.c:1028
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
spApgexSplit
apg_phrase * spApgexSplit(void *vpCtx, apg_phrase *spSource, aint uiLimit, aint *uipCount)
Split a phrase into an array of sub-phrases.
Definition: apgex.c:648
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
HYPHEN
#define HYPHEN
Definition: main.c:537
bIsBigEndian
abool bIsBigEndian(void)
Determine if the current machine uses big endian word storage.
Definition: tools.c:96
cpApiInFile
const char * cpApiInFile(void *vpCtx, const char *cpFileName)
Reads an SABNF grammar byte stream from a file.
Definition: input.c:117
GT
#define GT
Definition: main.c:539
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
apg_phrase::uiLength
aint uiLength
The number of characters in the array.
Definition: lib.h:62
vApgexSetLastIndex
void vApgexSetLastIndex(void *vpCtx, aint uiLastIndex)
Sets the index of the character in the source where the pattern-match search is to begin.
Definition: apgex.c:874
LT
#define LT
Definition: main.c:540
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
ast_data::vpUserData
void * vpUserData
Definition: ast.h:80
vApgexDisplayPatternErrors
void vApgexDisplayPatternErrors(void *vpCtx, const char *cpFileName)
Definition: apgex.c:1180
ast_translate::vpVecStack
void * vpVecStack
Definition: main.c:729
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
vApgexDtor
void vApgexDtor(void *vpCtx)
The phrase-matching engine object destructor.
Definition: apgex.c:295
ast_translate::sNamePhrase
apg_phrase sNamePhrase
Definition: main.c:728
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
apgex_rule
Information about each rule or UDT in the SABNF pattern.
Definition: apgex.h:58
vApgexEnableRules
void vApgexEnableRules(void *vpCtx, const char *cpNames, abool bEnable)
Enable or disable specified rule and/or UDT names for phrase capture.
Definition: apgex.c:786
vApgexPatternParser
void vApgexPatternParser(void *vpCtx, void *vpParser, const char *cpFlags)
Define the SABNF pattern with a user-created parser.
Definition: apgex.c:444
sApgexProperties
apgex_properties sApgexProperties(void *vpCtx)
Get a copy of the object's properties.
Definition: apgex.c:888
sApgexReplaceFunc
apg_phrase sApgexReplaceFunc(void *vpCtx, apg_phrase *spSource, pfn_replace pfnFunc, void *vpUser)
Replace the matched phrase with a user-generated phrase.
Definition: apgex.c:581
apgex_phrase::sPhrase
apg_phrase sPhrase
The matched phrase.
Definition: apgex.h:46
vFmtDtor
void vFmtDtor(void *vpCtx)
The object destructor.
Definition: format.c:146
bApgexTest
abool bApgexTest(void *vpCtx, apg_phrase *spSource)
Report only success or failure on a pattern match.
Definition: apgex.c:752
vpApgexGetAst
void * vpApgexGetAst(void *vpCtx)
Get a pointer to the AST object's context.
Definition: apgex.c:957
callback_data::uiStringLength
aint uiStringLength
[read only] The input string length.
Definition: parser.h:157
spUtilStrToPhrase
apg_phrase * spUtilStrToPhrase(void *vpMem, const char *cpStr)
Convert a null-terminated ASCII string to an apg_phrase.
Definition: utilities.c:891
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
vpFmtCtor
void * vpFmtCtor(exception *spEx)
The object constructor.
Definition: format.c:118
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
apgex_result::spRules
apgex_rule * spRules
The phrases matched by all enabled rules and/or UDTs. NULL if no match.
Definition: apgex.h:80
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
vVecClear
void vVecClear(void *vpCtx)
Clears all used elements in a vector component.
Definition: vector.c:420
apg_phrase::acpPhrase
const achar * acpPhrase
Pointer to an array of type achar APG alphabet characters.
Definition: lib.h:61
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
APG Version 7.0 is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.