Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
parser.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 * *************************************************************************************/
34 #include "./lib.h"
35 #include "./parserp.h"
36 #include "./operators.h"
37 #ifdef APG_TRACE
38 #include "./tracep.h"
39 #include "./statsp.h"
40 #endif
41 #ifdef APG_STATS
42 #include "./statsp.h"
43 #endif
44 #ifdef APG_BKR
45 #include "./backref.h"
46 #include "./backrefu.h"
47 #include "./backrefp.h"
48 #endif
49 
50 static const void* s_vpMagicNumber = (void*)"parser";
51 
52 //#define PARSER_DEBUG 1
53 #ifdef PARSER_DEBUG
54 #include <stdio.h>
55 #include "../utilities/utilities.h"
56 #endif /* PARSER_DEBUG */
57 
67 void* vpParserCtor(exception* spException, void* vpParserInit) {
68  return vpParserAllocCtor(spException, vpParserInit, APG_FALSE);
69 }
70 
88 void* vpParserAllocCtor(exception* spException, void* vpParserInit, abool bAllocateTables){
89  if(!bExValidate(spException)){
90  vExContext();
91  return NULL;
92  }
93  // validate the size of the alphabet character (achar)
94  parser_init* spParserInit = (parser_init*) vpParserInit;
95  init_hdr* spInitHdr = NULL;
96  luint* luipParserInit = NULL;
97  aint* uipChildList = NULL;
98  achar* acpAcharTable = NULL;
99  parser* spCtx = NULL;
100  void* vpMem = NULL;
101  if ((uint32_t) sizeof(achar) < spParserInit->uiSizeofAchar) {
102  XTHROW(spException, "sizeof(achar) is too small for this parser's grammar");
103  }
104  // validate the size of the working unsigned int (aint)
105  // note: uiSizeofUint is the integer size of the maximum integer in the initialization data.
106  // Since achar max is in the data, it stands that sizeof(aint) >= sizeof(achar) always.
107  if ((uint32_t) sizeof(aint) < spParserInit->uiSizeofUint) {
108  XTHROW(spException, "sizeof(aint) is too small for this parser's maximum integer");
109  }
110  // get the parser context
111  vpMem = vpMemCtor(spException);
112  spCtx = (parser*) vpMemAlloc(vpMem, (aint) sizeof(parser));
113  memset((void*) spCtx, 0, sizeof(parser));
114  spCtx->vpMem = vpMem;
115  spCtx->spException = spException;
116 
117  if(bAllocateTables){
118  size_t uiAlloc;
119  // allocate and copy the string table
120  uiAlloc = sizeof(char) * (size_t)spParserInit->uiStringTableLength;
121  char* cpStr = (char*)vpMemAlloc(vpMem, uiAlloc);
122  memcpy(cpStr, spParserInit->cpStringTable, uiAlloc);
123  spCtx->cpStringTable = (const char*)cpStr;
124  // allocate and copy the PPPT maps table
125  spCtx->ucpMaps = NULL;
126  if(spParserInit->ucpPpptTable){
127  uiAlloc = sizeof(uint8_t) * (size_t)spParserInit->uiPpptTableLength;
128  uint8_t* ucpStr = (uint8_t*)vpMemAlloc(vpMem, uiAlloc);
129  memcpy(ucpStr, spParserInit->ucpPpptTable, uiAlloc);
130  spCtx->ucpMaps = (const uint8_t*)ucpStr;
131  }
132  }else{
133  // get the string table
134  spCtx->cpStringTable = spParserInit->cpStringTable;
135 
136  // get the PPPT maps table
137  spCtx->ucpMaps = spParserInit->ucpPpptTable;
138  }
139 
140  // get the achar table
141  if(spParserInit->uiAcharTableLength){
142  acpAcharTable = (achar*) vpMemAlloc(vpMem, (aint)(spParserInit->uiAcharTableLength * sizeof(achar)));
143  if (!uiGetAcharTable(spParserInit, acpAcharTable)) {
144  XTHROW(spCtx->vpMem, "invalid achar table data");
145  }
146  spCtx->acpAcharTable = acpAcharTable;
147  }
148 
149  // get the parser initialization data in uints
150  luipParserInit = (luint*) vpMemAlloc(vpMem, (aint)(spParserInit->uiParserInitLength * sizeof(luint)));
151  if (!bGetParserInitData(spParserInit, luipParserInit)) {
152  XTHROW(spCtx->vpMem, "invalid parser initialization data");
153  }
154  spInitHdr = (init_hdr*) luipParserInit;
155  spCtx->acAcharMin = (achar)spInitHdr->uiAcharMin;
156  spCtx->acAcharMax = (achar)spInitHdr->uiAcharMax;
157  spCtx->uiMapSize = spInitHdr->uiMapSize;
158  spCtx->uiMapCount = spInitHdr->uiMapCount;
159  spCtx->vpVecInputString = vpVecCtor(vpMem, sizeof(achar), 2048);
160 
161  // get the child list (opcode indexes for children of ALT and CAT)
162  uipChildList = (aint*) vpMemAlloc(vpMem, (aint) (sizeof(aint) * spInitHdr->uiChildListLength));
163  vGetChildListTable(spInitHdr, uipChildList);
164  spCtx->uipChildList = (const aint*) uipChildList;
165 
166  // allocate rules
167  spCtx->uiRuleCount = (aint) spInitHdr->uiRuleCount;
168  spCtx->spRules = (rule*) vpMemAlloc(vpMem, (aint) (sizeof(rule) * spCtx->uiRuleCount));
169  memset((void*)spCtx->spRules, 0, (sizeof(rule) * spCtx->uiRuleCount));
170 
171  // allocate udts
172  spCtx->uiUdtCount = (aint) spInitHdr->uiUdtCount;
173  if (spCtx->uiUdtCount) {
174  spCtx->spUdts = (udt*) vpMemAlloc(vpMem, (aint) (sizeof(udt) * spCtx->uiUdtCount));
175  memset((void*)spCtx->spUdts, 0, (sizeof(udt) * spCtx->uiUdtCount));
176  }
177 
178  // allocate opcodes
179  spCtx->uiOpcodeCount = (aint) spInitHdr->uiOpcodeCount;
180  spCtx->spOpcodes = (opcode*) vpMemAlloc(vpMem, (aint) (sizeof(opcode) * spCtx->uiOpcodeCount));
181  memset((void*)spCtx->spOpcodes, 0, (sizeof(opcode) * spCtx->uiOpcodeCount));
182 
183  // get the rules, UDTs, and opcodes
184  vTranslateRules(spCtx, spCtx->spRules, spCtx->spOpcodes, (luipParserInit + spInitHdr->uiRulesOffset));
185  vTranslateUdts(spCtx, spCtx->spUdts, (luipParserInit + spInitHdr->uiUdtsOffset));
186  vTranslateOpcodes(spCtx, spCtx->spRules, spCtx->spUdts, spCtx->spOpcodes,
187  (luipParserInit + spInitHdr->uiOpcodesOffset));
188  vMemFree(vpMem, luipParserInit);
189 
190  // allocate and set the array of operator function pointers
191  // NOTE: ID_GEN must be greater than all other opcode IDs
192  spCtx->pfnOpFunc = (pfn_op*) vpMemAlloc(vpMem, (aint) (sizeof(pfn_op) * ID_GEN));
193  spCtx->pfnOpFunc[ID_ALT] = vAlt;
194  spCtx->pfnOpFunc[ID_CAT] = vCat;
195  spCtx->pfnOpFunc[ID_REP] = vRep;
196  spCtx->pfnOpFunc[ID_RNM] = vRnm;
197  spCtx->pfnOpFunc[ID_TRG] = vTrg;
198  spCtx->pfnOpFunc[ID_TLS] = vTls;
199  spCtx->pfnOpFunc[ID_TBS] = vTbs;
200 #ifdef APG_BKR
201  spCtx->pfnOpFunc[ID_BKR] = vBkr;
202 #else
203  spCtx->pfnOpFunc[ID_BKR] = NULL;
204 #endif /* APG_BKR */
205 #ifdef APG_STRICT_ABNF
206  spCtx->pfnOpFunc[ID_UDT] = NULL;
207  spCtx->pfnOpFunc[ID_AND] = NULL;
208  spCtx->pfnOpFunc[ID_NOT] = NULL;
209  spCtx->pfnOpFunc[ID_BKA] = NULL;
210  spCtx->pfnOpFunc[ID_BKN] = NULL;
211  spCtx->pfnOpFunc[ID_ABG] = NULL;
212  spCtx->pfnOpFunc[ID_AEN] = NULL;
213 #else
214  spCtx->pfnOpFunc[ID_UDT] = vUdt;
215  spCtx->pfnOpFunc[ID_AND] = vAnd;
216  spCtx->pfnOpFunc[ID_NOT] = vNot;
217  spCtx->pfnOpFunc[ID_BKA] = vBka;
218  spCtx->pfnOpFunc[ID_BKN] = vBkn;
219  spCtx->pfnOpFunc[ID_ABG] = vAbg;
220  spCtx->pfnOpFunc[ID_AEN] = vAen;
221 #endif /* APG_STRICT_ABNF */
222 
223  spCtx->vpBkru = BKRU_CTOR(spCtx);
224  spCtx->vpBkrp = BKRP_CTOR(spCtx);
225 
226 #ifdef PARSER_DEBUG
227  printf("\n");
228  vPrintRules(spCtx, NULL);
229  printf("\n");
230  vPrintUdts(spCtx, NULL);
231  printf("\n");
232  vPrintOpcodes(spCtx, NULL);
233 #endif /* PARSER_DEBUG */
234 
235  // success, return the parser context handle (pointer)
236  spCtx->vpValidate = s_vpMagicNumber;
237  return (void*) spCtx;
238 }
239 
245 void vParserDtor(void* vpCtx) {
246  parser* spCtx = (parser*) vpCtx;
247  if(vpCtx){
248  if (spCtx->vpValidate == s_vpMagicNumber) {
249  void* vpMem = spCtx->vpMem;
250  TRACE_DTOR(spCtx->vpTrace);
251  memset((void*)spCtx, 0, sizeof(*spCtx));
252  vMemDtor(vpMem);
253  }else{
254  vExContext();
255  }
256  }
257 }
258 
268 void vParserParse(void* vpCtx, parser_config* spConfig, parser_state* spState) {
269  parser* spCtx = (parser*) vpCtx;
270  aint ui;
271  if(!vpCtx || (spCtx->vpValidate != s_vpMagicNumber)){
272  vExContext();
273  return; // should never return
274  }
275  if(!spConfig){
276  XTHROW(spCtx->vpMem, "parser configuration pointer cannot be NULL");
277  return; // should never return
278  }
279  if(!spState){
280  XTHROW(spCtx->vpMem, "parser state pointer cannot be NULL");
281  return; // should never return
282  }
283  // validate the input
284  if (!spConfig->acpInput) {
285  XTHROW(spCtx->vpMem, "input string is NULL");
286  }
287  if (spConfig->uiStartRule >= spCtx->uiRuleCount) {
288  XTHROW(spCtx->vpMem, "start rule is out of range");
289  }
290  memset(spState, 0, sizeof(*spState));
291 
292  // verify all UDT callbacks set
293  if (spCtx->uiUdtCount) {
294  for (ui = 0; ui < spCtx->uiUdtCount; ui += 1) {
295  if (spCtx->spUdts[ui].pfnCallback == NULL) {
296  XTHROW(spCtx->spException,
297  "NULL UDT callback function pointers - all UDT callback functions must be set");
298  }
299  }
300  }
301 
302  vVecClear(spCtx->vpVecInputString);
303  spCtx->acpInputString = (achar*)vpVecPushn(spCtx->vpVecInputString, (void*)spConfig->acpInput, spConfig->uiInputLength);
304  spCtx->uiInputStringLength = spConfig->uiInputLength;
305  spCtx->uiStartRule = spConfig->uiStartRule;
306  if (spConfig->bParseSubString) {
307  // set the beginning and end of the sub string
308  if (spConfig->uiSubStringBeg >= spCtx->uiInputStringLength) {
309  XTHROW(spCtx->vpMem, "sub string beginning is beyond the end of the input string");
310  }
311  spCtx->uiSubStringBeg = spConfig->uiSubStringBeg;
312  if (spConfig->uiSubStringLength == 0) {
313  spCtx->uiSubStringEnd = spCtx->uiInputStringLength;
314  } else {
315  spCtx->uiSubStringEnd = spCtx->uiSubStringBeg + spConfig->uiSubStringLength;
316  if(spCtx->uiSubStringEnd > spConfig->uiInputLength){
317  spCtx->uiSubStringEnd = spConfig->uiInputLength;
318  }
319  }
320  } else {
321  // parse the entire string
322  spCtx->uiSubStringBeg = 0;
323  spCtx->uiSubStringEnd = spConfig->uiInputLength;
324  }
325  spCtx->uiSubStringLength = spCtx->uiSubStringEnd - spCtx->uiSubStringBeg;
326  spCtx->uiOffset = spCtx->uiSubStringBeg;
327 
328  // initialize the maximum distance to look behind for operators BKA & BKN
329  if ((spConfig->uiLookBehindLength == 0) || (spConfig->uiLookBehindLength == APG_INFINITE)) {
330  spCtx->uiLookBehindLength = spCtx->uiInputStringLength;
331  } else {
332  spCtx->uiLookBehindLength = spCtx->uiInputStringLength < spCtx->uiLookBehindLength ?
333  spCtx->uiInputStringLength : spCtx->uiLookBehindLength;
334  }
335 
336  // initialize the callback data (callback functions only see the substring)
337  spCtx->sCBData.vpCtx = (void*) spCtx;
338  spCtx->sCBData.vpMem = spCtx->vpMem;
339  spCtx->sCBData.spException = spCtx->spException;
340  spCtx->sCBData.acpString = &spCtx->acpInputString[spCtx->uiSubStringBeg];
341  spCtx->sCBData.uiStringLength = spCtx->uiSubStringLength;
342  spCtx->sCBData.uiParserOffset = 0;
343  spCtx->sCBData.uiParserState = ID_ACTIVE;
344  spCtx->sCBData.uiParserPhraseLength = 0;
345  spCtx->sCBData.vpUserData = spConfig->vpUserData;
346  spCtx->sCBData.uiCallbackPhraseLength = 0;
347  spCtx->sCBData.uiCallbackState = ID_ACTIVE;
348 
349  // reset attached trace and AST if any (stats, if any, are cumulative)
350  TRACE_BEGIN(spCtx->vpTrace);
351  AST_CLEAR(spCtx->vpAst);
352 
353  // create a dummy RNM opcode for the start rule and start the parser
354  memset((void*)&spCtx->sState, 0, sizeof(spCtx->sState));
355  spCtx->uiTreeDepth = 0;
356  spCtx->sStartOp.sRnm.spRule = &spCtx->spRules[spCtx->uiStartRule];
357  spCtx->sStartOp.sRnm.uiId = ID_RNM;
358  spCtx->sStartOp.sRnm.ucpPpptMap = spCtx->spRules[spCtx->uiStartRule].ucpPpptMap;
359  spCtx->pfnOpFunc[ID_RNM](spCtx, &spCtx->sStartOp);
360 
361  // finish the trace output
362  TRACE_END(spCtx->vpTrace);
363 
364  // on parsing errors, success depends on the matched phrase length
365  spCtx->sState.uiState = spCtx->uiOpState;
366  spCtx->sState.uiPhraseLength =
367  spCtx->uiOffset > spCtx->uiSubStringBeg ? spCtx->uiOffset - spCtx->uiSubStringBeg : 0;
368  spCtx->sState.uiStringLength = spCtx->uiSubStringLength;
369  if (spCtx->sState.uiState == ID_NOMATCH) {
370  spCtx->sState.uiSuccess = APG_FALSE;
371  } else if (spCtx->sState.uiPhraseLength == spCtx->sState.uiStringLength) {
372  spCtx->sState.uiSuccess = APG_TRUE;
373  } else {
374  spCtx->sState.uiSuccess = APG_FALSE;
375  }
376  memcpy((void*) spState, (void*) &spCtx->sState, sizeof(*spState));
377 }
378 
386 void vParserSetRuleCallback(void* vpCtx, aint uiRuleId, parser_callback pfnCallback) {
387  parser* spCtx = (parser*) vpCtx;
388  if (vpCtx && (spCtx->vpValidate == s_vpMagicNumber)) {
389  if (uiRuleId < spCtx->uiRuleCount) {
390  spCtx->spRules[uiRuleId].pfnCallback = pfnCallback;
391  }
392  }else{
393  vExContext();
394  }
395 }
396 
407 void vParserSetUdtCallback(void* vpCtx, aint uiUdtId, parser_callback pfnCallback) {
408  parser* spCtx = (parser*) vpCtx;
409  if (vpCtx && (spCtx->vpValidate == s_vpMagicNumber)) {
410  if (uiUdtId < spCtx->uiUdtCount) {
411  spCtx->spUdts[uiUdtId].pfnCallback = pfnCallback;
412  }
413  }else{
414  vExContext();
415  }
416 }
417 
422 abool bParserValidate(void* vpCtx){
423  parser* spCtx = (parser*) vpCtx;
424  if (vpCtx && (spCtx->vpValidate == s_vpMagicNumber)) {
425  return APG_TRUE;
426  }
427  return APG_FALSE;
428 }
429 
440 aint uiParserRuleLookup(void* vpCtx, const char* cpRuleName){
441  aint uiReturn = APG_UNDEFINED;
442  parser* spCtx = (parser*) vpCtx;
443  if (!(vpCtx && (spCtx->vpValidate == s_vpMagicNumber))) {
444  vExContext();
445  }
446 
447  // linear search (qsort + binary search overkill here)
448  rule* spRule = spCtx->spRules;
449  aint ui = 0;
450  for(; ui < spCtx->uiRuleCount; ui++, spRule++){
451  if(iStriCmp(cpRuleName, spRule->cpRuleName) == 0){
452  uiReturn = spRule->uiRuleIndex;
453  break;
454  }
455  }
456  return uiReturn;
457 }
458 
469 const char* cpParserRuleName(void* vpCtx, aint uiRuleIndex){
470  parser* spCtx = (parser*) vpCtx;
471  if (!(vpCtx && (spCtx->vpValidate == s_vpMagicNumber))) {
472  vExContext();
473  }
474 
475  if(uiRuleIndex < spCtx->uiRuleCount){
476  return spCtx->spRules[uiRuleIndex].cpRuleName;
477  }
478  return NULL;
479 }
480 
491 const char* cpParserUdtName(void* vpCtx, aint uiUdtIndex){
492  aint uiReturn = APG_UNDEFINED;
493  parser* spCtx = (parser*) vpCtx;
494  if (!(vpCtx && (spCtx->vpValidate == s_vpMagicNumber))) {
495  vExContext();
496  }
497 
498  if(uiUdtIndex < spCtx->uiUdtCount){
499  return spCtx->spUdts[uiUdtIndex].cpUdtName;
500  }
501  return NULL;
502 }
503 
504 #ifndef APG_NO_PPPT
505 #ifdef PARSER_EVAL_DEBUG
506 #include <stdio.h>
507 #include "../utilities/utilities.h"
508 static const char* cpMapVal(uint8_t ucVal){
509  static char* caVal[5] = {"N", "M", "E", "A", "U"};
510  if(ucVal < 4){
511  return caVal[ucVal];
512  }
513  return caVal[4];
514 }
515 static void vPrintMap(achar acMin, achar acMax, const uint8_t* ucpMap){
516  aint ui;
517  uint8_t ucVal;
518  for(ui = acMin; ui <= acMax; ui++){
519  ucVal = ucGetMapVal(ucpMap, acMin, ui);
520  if(ucVal != ID_PPPT_NOMATCH){
521  printf(" %"PRIuMAX"%s", (luint)ui, cpMapVal(ucVal));
522  }
523  }
524  printf("\n");
525 }
526 #endif /* PARSER_EVAL_DEBUG */
527 
535 aint uiPpptState(parser* spCtx, const opcode* spOp, aint uiOffset){
536  achar acChar;
537  uint8_t ucVal;
538  if(!spCtx->ucpMaps){
539  return ID_ACTIVE;
540  }
541  switch(spOp->sGen.uiId){
542  case ID_BKR:
543  case ID_UDT:
544  case ID_BKA:
545  case ID_BKN:
546  case ID_ABG:
547  case ID_AEN:
548  // no PPPTs for these operators
549  return ID_ACTIVE;
550  }
551  if(uiOffset >= spCtx->uiSubStringEnd){
552  if(spCtx->uiSubStringEnd == 0){
553  // special case when BKA or BKN look behind at beginning of string
554  return ID_NOMATCH;
555  }
556  // map value for end-of-string character
557  ucVal = spOp->sGen.ucpPpptMap[spCtx->acAcharMax + 1 - spCtx->acAcharMin];
558  }else{
559  acChar = spCtx->acpInputString[uiOffset];
560  if(acChar < spCtx->acAcharMin || acChar > spCtx->acAcharMax){
561  return ID_NOMATCH;
562  }
563  ucVal = spOp->sGen.ucpPpptMap[acChar - spCtx->acAcharMin];
564  }
565 #ifdef PARSER_EVAL_DEBUG
566  printf("%s: ", cpOpName(spOp->sGen.uiId));
567  printf(" %"PRIuMAX"%s: ", (luint)acChar, cpMapVal(ucVal));
568  vPrintMap(spCtx->acAcharMin, spCtx->acAcharMax, spOp->sGen.ucpPpptMap);
569  fflush(stdout);
570 #endif /* PARSER_EVAL_DEBUG */
571  if(ucVal == ID_PPPT_NOMATCH){
572  return ID_NOMATCH;
573  }
574  if(ucVal == ID_PPPT_EMPTY){
575  return ID_EMPTY;
576  }
577  if(ucVal == ID_PPPT_MATCH){
578  return ID_MATCH;
579  }
580  return ID_ACTIVE;
581 }
582 
590 abool bPpptEval(parser* spCtx, const opcode* spOp, aint uiOffset){
591  aint uiState = uiPpptState(spCtx, spOp, uiOffset);
592  switch(uiState){
593  case ID_NOMATCH:
594  spCtx->uiOpState = ID_NOMATCH;
595  spCtx->uiPhraseLength = 0;
596  return APG_TRUE;
597  case ID_EMPTY:
598  spCtx->uiOpState = ID_MATCH;
599  spCtx->uiPhraseLength = 0;
600  return APG_TRUE;
601  case ID_MATCH:
602  spCtx->uiOpState = ID_MATCH;
603  spCtx->uiPhraseLength = 1;
604  spCtx->uiOffset++;
605  return APG_TRUE;
606  }
607  return APG_FALSE;
608 }
609 //static uint8_t s_ucGetMask[4] = {0xC0, 0x30, 0xC,0x3};
610 //static uint8_t s_ucGetShift[4] = {6,4,2,0};
611 /* \brief Gets the PPPT values in the map of 2-bit values.
612  *
613  * Note the use of luint rather than achar. This is because the EOS character is assumed to be acAcharMax + 1.
614  * Therefore, depending on the sizeof(achar), it is possible for the EOS character to overflow the achar size.
615  * Using luint for the characters here allows the user to request the EOS character without fear of overflow.
616  *
617  * \param[in] ucpMap - pointer to the map of PPPT values to grammar alphabet characters
618  * \param[in] luiOffset - acAcharMin - the value of the lowest characters in the grammar's alphabet set
619  * \param[in] luiChar - the character for which to set the PPPT value in the map.
620  * \return The 2-bit value as a byte.
621  */
622 /*
623 uint8_t ucGetMapVal(const uint8_t* ucpMap, luint luiOffset, luint luiChar){
624  luint luRelChar = luiChar - luiOffset;
625  luint luMapIndex = luRelChar >> 2;
626  luint ucByteIndex = luRelChar - (luMapIndex << 2);
627  return (ucpMap[luMapIndex] & s_ucGetMask[ucByteIndex]) >> s_ucGetShift[ucByteIndex];
628 }
629 */
630 uint8_t ucGetMapVal(const uint8_t* ucpMap, luint luiOffset, luint luiChar){
631  return ucpMap[luiChar - luiOffset];
632 // luint luRelChar = luiChar - luiOffset;
633 // luint luMapIndex = luRelChar >> 2;
634 // switch(luRelChar % 4){
635 // case 0:
636 // return (ucpMap[luMapIndex] & 0xC0) >> 6;
637 // case 1:
638 // return (ucpMap[luMapIndex] & 0x30) >> 4;
639 // case 2:
640 // return (ucpMap[luMapIndex] & 0xC) >> 2;
641 // case 3:
642 // return ucpMap[luMapIndex] & 0x3;
643 // }
644 // return 0;
645 }
646 #endif /* APG_NO_PPPT */
647 
lib.h
This header "#include"s all publid lib headers and other standard headers needed by most objects.
backrefp.h
The parent-mode back reference object.
BKRU_CTOR
#define BKRU_CTOR(x)
Definition: apg.h:214
vCat
void vCat(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:99
parser_config::bParseSubString
abool bParseSubString
If true (non-zero), only parse the defined sub-string of the input string.
Definition: parser.h:202
APG_INFINITE
#define APG_INFINITE
Definition: apg.h:320
vpParserCtor
void * vpParserCtor(exception *spException, void *vpParserInit)
The parser's constructor for file initialization data.
Definition: parser.c:67
parser_config::uiSubStringBeg
aint uiSubStringBeg
The first character of the sub-string to parse. Must be < uiInputLength or exception is thrown.
Definition: parser.h:203
vMemDtor
void vMemDtor(void *vpCtx)
Destroys a Memory component. Frees all memory allocated.
Definition: memory.c:141
ID_RNM
#define ID_RNM
rule name
Definition: parser.h:46
vBka
void vBka(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:189
parser_init::uiSizeofUint
uint32_t uiSizeofUint
Minimum size, in bytes, required for the basic parser unsigned integer, aint.
Definition: parserp.h:48
vRnm
void vRnm(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:245
parserp.h
Private header for the SABNF parser.
vTranslateRules
void vTranslateRules(parser *spCtx, rule *spRules, opcode *spOpcodes, luint *luipData)
Translate the initialization data for the rules into the internal rules format.
Definition: parser-translate-init.c:43
init_hdr::uiOpcodesOffset
luint uiOpcodesOffset
Offset from the beginning of the initialization data to the to the list of opcodes.
Definition: parserp.h:94
parser_init::cpStringTable
const char * cpStringTable
Pointer to the string table.
Definition: parserp.h:53
init_hdr::uiUdtCount
luint uiUdtCount
The number of UDTs in the grammar.
Definition: parserp.h:78
parser_config::acpInput
const achar * acpInput
Pointer to the input string.
Definition: parser.h:199
ID_ALT
#define ID_ALT
alternation
Definition: parser.h:43
ID_BKR
#define ID_BKR
back reference to a previously matched rule or UDT name
Definition: parser.h:58
init_hdr::uiRuleCount
luint uiRuleCount
The number of rules in the grammar.
Definition: parserp.h:77
ID_UDT
#define ID_UDT
user-defined terminal
Definition: parser.h:55
TRACE_END
#define TRACE_END(x)
Definition: apg.h:170
parser_init::uiAcharTableLength
uint32_t uiAcharTableLength
Length of this data's alphabet character table.
Definition: parserp.h:50
uiParserRuleLookup
aint uiParserRuleLookup(void *vpCtx, const char *cpRuleName)
Find the rule index corresponding to a rule name.
Definition: parser.c:440
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
vTranslateOpcodes
void vTranslateOpcodes(parser *spCtx, rule *spRules, udt *spUdts, opcode *spOpcodes, luint *luipData)
Translate the initialization data for the opcodes into the internal opcode format.
Definition: parser-translate-init.c:76
vAbg
void vAbg(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:233
parser_config::vpUserData
void * vpUserData
Pointer to user data, if any. Not examined or used by the parser in any way. Presented to the user's ...
Definition: parser.h:210
achar
uint_fast8_t achar
achar is the type for the parser's alphabet characters.
Definition: apg.h:91
iStriCmp
int iStriCmp(const char *cpLeft, const char *cpRight)
Compare two strings. A case-insensitive version of strcmp().
Definition: tools.c:53
vTranslateUdts
void vTranslateUdts(parser *spCtx, udt *spUdts, luint *luipData)
Translate the initialization data for the UDTs into the internal UDT format.
Definition: parser-translate-init.c:60
vParserSetRuleCallback
void vParserSetRuleCallback(void *vpCtx, aint uiRuleId, parser_callback pfnCallback)
Set a call back function for a specific rule.
Definition: parser.c:386
ID_EMPTY
#define ID_EMPTY
indicates a matched empty phrase parser state on return from parse tree below this node
Definition: parser.h:75
vpParserInit
const void * vpParserInit
Definition: sabnf-grammar.c:1422
ID_PPPT_NOMATCH
#define ID_PPPT_NOMATCH
deterministic NOMATCH – there is no chance of a phrase match with this leading character
Definition: parser.h:81
init_hdr::uiOpcodeCount
luint uiOpcodeCount
The number of opcodes in the grammar.
Definition: parserp.h:79
ID_NOT
#define ID_NOT
negative look ahead
Definition: parser.h:57
vGetChildListTable
void vGetChildListTable(init_hdr *spInitHdr, aint *uipList)
Extract the child index list from the initialization data.
Definition: parser-get-init.c:130
ID_AND
#define ID_AND
positive look ahead
Definition: parser.h:56
uiGetAcharTable
aint uiGetAcharTable(parser_init *spParserInit, achar *acpAcharTable)
Extract the alphabet character table from the initialization data.
Definition: parser-get-init.c:43
bGetParserInitData
abool bGetParserInitData(parser_init *spParserInit, luint *luipParserInit)
Re-size the initialization data to the required integer size.
Definition: parser-get-init.c:80
vAen
void vAen(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:249
parser_init::uiSizeofAchar
uint32_t uiSizeofAchar
Minimum size, in bytes, required for the alphabet characters, achar.
Definition: parserp.h:47
parser_init::uiParserInitLength
uint32_t uiParserInitLength
Length of the parser initialization data.
Definition: parserp.h:52
parser_init::uiStringTableLength
uint32_t uiStringTableLength
Length of this data's string table.
Definition: parserp.h:49
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
parser_init
The initialization information generated by APG.
Definition: parserp.h:46
parser_callback
void(* parser_callback)(callback_data *spData)
User-written callback function prototype.
Definition: parser.h:178
rule::uiRuleIndex
aint uiRuleIndex
The rule index - zero-based order in which the rule appears in the SABNF grammar.
Definition: parserp.h:127
vBkn
void vBkn(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:215
vParserSetUdtCallback
void vParserSetUdtCallback(void *vpCtx, aint uiUdtId, parser_callback pfnCallback)
Set a call back function for a specific UDT.
Definition: parser.c:407
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
vTbs
void vTbs(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:386
backref.h
Private declarations common to both universal and parent modes.
parser_config::uiInputLength
aint uiInputLength
Number of input string alphabet characters.
Definition: parser.h:200
vTrg
void vTrg(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:323
parser_config
Defines the input string and other configuration parameters for the parser,.
Definition: parser.h:198
ID_CAT
#define ID_CAT
concatenation
Definition: parser.h:44
init_hdr::uiAcharMin
luint uiAcharMin
The minimum value of all of the alphabet characters (achar) present in the grammar.
Definition: parserp.h:71
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
init_hdr::uiUdtsOffset
luint uiUdtsOffset
Offset from the beginning of the initialization data to the to the list of UDTs.
Definition: parserp.h:91
ID_PPPT_MATCH
#define ID_PPPT_MATCH
deterministic MATCH – this character constitutes a single character phrase match of length 1
Definition: parser.h:82
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
pfn_op
void(* pfn_op)(struct parser_tag *spCtx, const union opcode_tag *spOp)
Prototype for the node operation functions.
Definition: parserp.h:114
ID_TRG
#define ID_TRG
terminal range
Definition: parser.h:47
ID_REP
#define ID_REP
repetition
Definition: parser.h:45
parser_state
The parser's final state.
Definition: parser.h:183
exception
A structure to describe the type and location of a caught exception.
Definition: exception.h:47
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
TRACE_DTOR
#define TRACE_DTOR(x)
Definition: apg.h:171
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
vUdt
void vUdt(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:49
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
parser_config::uiLookBehindLength
aint uiLookBehindLength
The maximum length to look behind for a match. Use 0 or APG_INFINITE for infinite look behind.
Definition: parser.h:208
parser_init::ucpPpptTable
const uint8_t * ucpPpptTable
Pointer to the PPPT or NULL if none.
Definition: parserp.h:54
vTls
void vTls(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:347
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
bExValidate
abool bExValidate(exception *spException)
Test an exception structure for validity.
Definition: exception.c:70
TRACE_BEGIN
#define TRACE_BEGIN(x)
Definition: apg.h:169
vpVecPushn
void * vpVecPushn(void *vpCtx, void *vpElement, aint uiCount)
Adds one or more elements to the end of the array.
Definition: vector.c:221
ID_BKA
#define ID_BKA
positive look behind
Definition: parser.h:59
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
ID_GEN
#define ID_GEN
general opcode (not SABNF). Serves to locate the ID in any opcode structure and must be larger than a...
Definition: parser.h:63
vRep
void vRep(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:148
tracep.h
Private header file for the trace functions.
ID_TLS
#define ID_TLS
terminal literal string
Definition: parser.h:49
vBkr
void vBkr(parser *spCtx, const opcode *spOp)
Definition: operators-bkr.c:51
rule
Data structure for a single rule.
Definition: parserp.h:119
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
parser_config::uiSubStringLength
aint uiSubStringLength
The number of characters in the sub-string. If 0, then the remainder of the string from uiSubStringBe...
Definition: parser.h:205
init_hdr::uiRulesOffset
luint uiRulesOffset
Offset from the beginning of the initialization data to the to the list of rules.
Definition: parserp.h:88
init_hdr::uiAcharMax
luint uiAcharMax
The maximum value of all of the alphabet characters (achar) present in the grammar.
Definition: parserp.h:72
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
vAnd
void vAnd(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:106
ID_PPPT_EMPTY
#define ID_PPPT_EMPTY
deterministic EMTPY – this is an empty string match, the parse succeeds but the phrase length is 0
Definition: parser.h:83
ucGetMapVal
uint8_t ucGetMapVal(const uint8_t *ucpMap, luint luiOffset, luint luiChar)
ID_BKN
#define ID_BKN
negative look behind
Definition: parser.h:60
init_hdr::uiChildListLength
luint uiChildListLength
The number of integers in the child index list.
Definition: parserp.h:87
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
vAlt
void vAlt(parser *spCtx, const opcode *spOp)
Definition: operators-abnf.c:66
vNot
void vNot(parser *spCtx, const opcode *spOp)
Definition: operators-sabnf.c:130
parser_config::uiStartRule
aint uiStartRule
Index of the start rule. Any rule in the SABNF grammar may be used as the start rule.
Definition: parser.h:201
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
parser_init::uiPpptTableLength
uint32_t uiPpptTableLength
Length of this data's PPPT.
Definition: parserp.h:51
init_hdr::uiMapSize
luint uiMapSize
The number of bytes in one PPPT map.
Definition: parserp.h:81
vpParserAllocCtor
void * vpParserAllocCtor(exception *spException, void *vpParserInit, abool bAllocateTables)
The parser constructor.
Definition: parser.c:88
ID_ABG
#define ID_ABG
anchor - beginning of string
Definition: parser.h:61
init_hdr::uiMapCount
luint uiMapCount
The number rule, UDT, and opcode PPPT maps.
Definition: parserp.h:80
backrefu.h
The universal-mode back reference object.
AST_CLEAR
#define AST_CLEAR(v)
Definition: apg.h:252
init_hdr
Header for the parser initialization data.
Definition: parserp.h:69
cpParserUdtName
const char * cpParserUdtName(void *vpCtx, aint uiUdtIndex)
Find the UDT name corresponding to a UDT index.
Definition: parser.c:491
operators.h
Header file for the suite of the parser's operator functions.
ID_TBS
#define ID_TBS
terminal binary string
Definition: parser.h:48
bParserValidate
abool bParserValidate(void *vpCtx)
Validate the context pointer of a parser.
Definition: parser.c:422
statsp.h
Private header file for the statistics gathering functions.
udt
Data structure for a single UDT.
Definition: parserp.h:133
vVecClear
void vVecClear(void *vpCtx)
Clears all used elements in a vector component.
Definition: vector.c:420
cpParserRuleName
const char * cpParserRuleName(void *vpCtx, aint uiRuleIndex)
Find the rule name from the corresponding index.
Definition: parser.c:469
rule::cpRuleName
const char * cpRuleName
Pointer to the (null-terminated) ASCII rule name.
Definition: parserp.h:120
BKRP_CTOR
#define BKRP_CTOR(x)
Definition: apg.h:220
ID_AEN
#define ID_AEN
anchor - end of string
Definition: parser.h:62
APG_FALSE
#define APG_FALSE
Definition: apg.h:292
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.