Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
backrefp.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 * *************************************************************************************/
36 #include "./apg.h"
37 #ifdef APG_BKR
38 #include "./lib.h"
39 #include "./parserp.h"
40 #include "./backref.h"
41 #include "./backrefp.h"
42 
43 //static const int iError = 1;
44 static const char* s_cpEmpty = "vector is empty";
45 
46 // rule states
47 static const aint uiUndefined = APG_UNDEFINED;
48 static const aint uiNotFound = 0;
49 static const aint uiFound = 1;
50 static const aint uiOpen = 2;
51 //static const aint uiIsBkr = 3;
52 //static const aint uiRecursive = 4;
53 
54 typedef struct{
56 } bkrp_frame;
57 
58 typedef struct {
59  const opcode* spOp;
61  jmp_buf aJumpBuf;
62  void* vpVecStack;
63 } bkrp_input;
64 
65 static aint uiSESTWalk(backref* spCtx);
66 static void vOpWalk(backref* spCtx, bkrp_input* spInput);
67 static void vRnmWalk(backref* spCtx, bkrp_input* spInput);
68 static void vAltWalk(backref* spCtx, bkrp_input* spInput);
69 static void vCatWalk(backref* spCtx, bkrp_input* spInput);
70 static void vRepWalk(backref* spCtx, bkrp_input* spInput);
71 static void vFreeAll(backref* spCtx);
72 static void vSetPhrase(backref* spCtx, aint uiIndex, aint uiOffset, aint uiLength);
73 static void vRestoreCheckPoints(backref* spCtx, aint* uipCheckPoints);
74 static void vSetCheckPoints(backref* spCtx, aint* uipCheckPoints);
75 static void vPushEmptyPhrase(backref* spCtx);
76 
77 // !!!! DEBUG
78 //#include <stdio.h>
79 //typedef struct print_tag {
80 // bkr_rule* spRule;
81 // aint uiTreeDepth;
82 // aint uiDirection; // down = 1, up = 0, middle = 2;
83 // aint uiState;
84 //} print;
85 //static char* cpState(aint uiState);
86 //static void vPrintRule(print* spPrint);
87 //
89 //static const aint uiDown = 0;
90 //static const aint uiInner = 1;
91 //static const aint uiUp = 2;
92 // !!!! DEBUG
93 
97 void* vpBkrpCtor(parser* spParserCtx) {
98  // component mem allocations
99  backref* spCtx = NULL;
100 
101  // temp allocations
102  aint* uipCounters = NULL;
103 
104  void* vpReturn = NULL;
105  aint ui = 0;
106  aint uiCount = spParserCtx->uiRuleCount + spParserCtx->uiUdtCount;
107  aint uiIndex;
108  while (APG_TRUE) {
109  // initialize the component context
110  spCtx = (backref*) vpMemAlloc(spParserCtx->vpMem, (aint) sizeof(backref));
111  memset((void*) spCtx, 0, (aint) sizeof(backref));
112  spCtx->spParserCtx = spParserCtx;
113  spCtx->spException = spMemException(spParserCtx->vpMem);
114 
115  // create space for temp array of counters
116  uipCounters = (aint*) vpMemAlloc(spParserCtx->vpMem, ((aint) sizeof(aint) * uiCount));
117  memset((void*) uipCounters, 0, ((aint) sizeof(aint) * uiCount));
118 
119  // initialize rules and UDTS
120  spCtx->spRules = (bkr_rule*) vpMemAlloc(spParserCtx->vpMem,
121  ((aint) sizeof(bkr_rule) * spParserCtx->uiRuleCount));
122  memset((void*) spCtx->spRules, 0, ((aint) sizeof(bkr_rule) * spParserCtx->uiRuleCount));
123  if (spParserCtx->uiUdtCount) {
124  spCtx->spUdts = (bkr_udt*) vpMemAlloc(spParserCtx->vpMem,
125  ((aint) sizeof(bkr_udt) * spParserCtx->uiUdtCount));
126  }
127  for (ui = 0; ui < spParserCtx->uiRuleCount; ui += 1) {
128  spCtx->spRules[ui].spRule = &spParserCtx->spRules[ui];
129  spCtx->spRules[ui].uiIsBackRef = APG_FALSE;
130  spCtx->spRules[ui].uiHasBackRef = uiUndefined;
131  spCtx->spRules[ui].uiBackRefIndex = uiUndefined;
132  }
133  for (ui = 0; ui < spParserCtx->uiUdtCount; ui += 1) {
134  spCtx->spUdts[ui].spUdt = &spParserCtx->spUdts[ui];
135  spCtx->spUdts[ui].uiIsBackRef = APG_FALSE;
136  spCtx->spUdts[ui].uiBackRefIndex = uiUndefined;
137  }
138 
139  // count the number of back parent-mode referenced rules and UDTs
140  spCtx->uiBkrCount = 0;
141  for (ui = 0; ui < spParserCtx->uiOpcodeCount; ui += 1) {
142  if (spParserCtx->spOpcodes[ui].sGen.uiId == ID_BKR) {
143  if (spParserCtx->spOpcodes[ui].sBkr.uiMode == ID_BKR_MODE_P) {
144  uiIndex = spParserCtx->spOpcodes[ui].sBkr.uiRuleIndex;
145  if (uipCounters[uiIndex] == 0) {
146  if (uiIndex < spParserCtx->uiRuleCount) {
147  spCtx->spRules[uiIndex].uiIsBackRef = APG_TRUE;
148  spCtx->spRules[uiIndex].uiBackRefIndex = spCtx->uiBkrCount;
149  } else {
150  spCtx->spUdts[uiIndex - spParserCtx->uiRuleCount].uiIsBackRef = APG_TRUE;
151  spCtx->spUdts[uiIndex - spParserCtx->uiRuleCount].uiBackRefIndex = spCtx->uiBkrCount;
152  }
153  spCtx->uiBkrCount += 1;
154  }
155  uipCounters[uiIndex] += 1;
156  }
157  }
158  }
159 
160  // !!!! DEBUG
161 // {
162 // aint uiCount = 0;
163 // printf("RULES THAT ARE PARENT-MODE BACK REFERENCED:\n");
164 // for (ui = 0; ui < spParserCtx->uiRuleCount; ui += 1) {
165 // bkr_rule* spRule = &spCtx->spRules[ui];
166 // if(spRule->uiIsBackRef){
167 // printf("rule: %s: uiIsBackRef: %"PRIuMAX": uiBackRefIndex: %"PRIuMAX"\n",
168 // spRule->spRule->cpRuleName, (luint) spRule->uiIsBackRef, (luint) spRule->uiBackRefIndex);
169 // uiCount++;
170 // }
171 // }
172 // for (ui = 0; ui < spParserCtx->uiUdtCount; ui += 1) {
173 // bkr_udt* spUdt = &spCtx->spUdts[ui];
174 // if(spUdt->uiIsBackRef){
175 // printf(" udt: %s: uiIsBackRef: %"PRIuMAX": uiBackRefIndex: %"PRIuMAX"\n", spUdt->spUdt->cpUdtName, (luint) spUdt->uiIsBackRef, (luint) spUdt->uiBackRefIndex);
176 // uiCount++;
177 // }
178 // }
179 // if(!uiCount){
180 // printf(" *** NONE ***\n");
181 // }
182 // printf("\n");
183 // }
184  // !!!! DEBUG
185 
186  if (spCtx->uiBkrCount == 0) {
187  // no universal-mode back referenced rules, nothing more to do, return a NULL context
188  break;
189  }
190 
191  // create an initialize the array of stack frames
192  spCtx->vppPhraseStacks = (void**) vpMemAlloc(spParserCtx->vpMem, ((aint) sizeof(void*) * spCtx->uiBkrCount));
193  memset(spCtx->vppPhraseStacks, 0, ((aint) sizeof(void*) * spCtx->uiBkrCount));
194  aint uiIndex = 0;
195  for (ui = 0; ui < uiCount; ui += 1) {
196  if (uipCounters[ui]) {
197  spCtx->vppPhraseStacks[uiIndex] = vpVecCtor(spParserCtx->vpMem, (aint) sizeof(bkr_phrase), 20);
198  uiIndex++;
199  }
200  }
201 
202  // walk the SEST an mark all rules that reference universal-mode back referenced rules & UDTs.
203  if (!uiSESTWalk(spCtx)) {
204  break;
205  }
206 
207  // !!!! DEBUG
208 // {
209 // aint uiCount = 0;
210 // printf("RULES CONTAINING AT LEAST ONE PARENT-MODE BACK REFERENCED RULE IN ITS (SEST) SYNTAX TREE:\n");
211 // for (ui = 0; ui < spParserCtx->uiRuleCount; ui += 1) {
212 // bkr_rule* spRule = &spCtx->spRules[ui];
213 // if(spRule->uiHasBackRef){
214 // printf("rule: %s: uiHasBackRef: %"PRIuMAX"\n", spRule->spRule->cpRuleName, (luint) spRule->uiHasBackRef);
215 // uiCount++;
216 // }
217 // }
218 // if(!uiCount){
219 // printf(" *** NONE ***\n");
220 // }
221 // printf("\n");
222 // }
223  // !!!! DEBUG
224 
225  // stack of check points
226  spCtx->vpCheckPoints = vpVecCtor(spParserCtx->vpMem, ((aint) sizeof(aint) * spCtx->uiBkrCount), 100);
227 
228  // create the stack of open rules
229  spCtx->vpOpenRules = vpVecCtor(spParserCtx->vpMem, (aint) sizeof(aint), 100);
230 
231  spCtx->vpValidate = (void*) spCtx;
232  vpReturn = (void*) spCtx;
233  // success
234  break;
235  }
236  if (!vpReturn) {
237  // free allocated memory on error
238  vFreeAll(spCtx);
239  }
240 
241  // always free temporary storage, if any
242  vMemFree(spParserCtx->vpMem, uipCounters);
243  return vpReturn;
244 }
245 
246 void vBkrpRuleOpen(void* vpCtx, aint uiIndex) {
247  backref* spCtx = (backref*) vpCtx;
248  aint* uipCheckPoints;
249  if (spCtx->spRules[uiIndex].uiHasBackRef || spCtx->spRules[uiIndex].uiIsBackRef) {
250  // this rule is or has on its syntax tree a back referenced rule
251  // save checkpoints on the found back reference stack - may need to restore if this rule fails
252  uipCheckPoints = (aint*)vpVecPush(spCtx->vpCheckPoints, NULL);
253  vSetCheckPoints(spCtx, uipCheckPoints);
254  }
255 
256  if (spCtx->spRules[uiIndex].uiHasBackRef) {
257  // push an empty phrase on each back referenced rule
258  vPushEmptyPhrase(spCtx);
259  }
260 
261  // let the operators in this rule's syntax tree know whether or not they need to bother looking for back referenced rules
262  vpVecPush(spCtx->vpOpenRules, (void*) &spCtx->spRules[uiIndex].uiHasBackRef);
263 }
264 
265 void vBkrpRuleClose(void* vpCtx, aint uiIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength) {
266  backref* spCtx = (backref*) vpCtx;
267  aint* uipCheckPoints;
268  if (spCtx->spRules[uiIndex].uiHasBackRef || spCtx->spRules[uiIndex].uiIsBackRef) {
269  // restore the check points on NOMATCH (this is primarily what make it different from universal mode)
270  uipCheckPoints = (aint*)vpVecPop(spCtx->vpCheckPoints);
271  if(!uipCheckPoints){
272  XTHROW(spCtx->spException, s_cpEmpty);
273  return;
274  }
275  vRestoreCheckPoints(spCtx, uipCheckPoints);
276  }
277  if(spCtx->spRules[uiIndex].uiIsBackRef && (uiState == ID_MATCH)){
278  // fill all empty phrases on the stack
279  vSetPhrase(spCtx, spCtx->spRules[uiIndex].uiBackRefIndex, uiPhraseOffset, uiPhraseLength);
280  }
281  // always pop the open rules stack - it was only of use to operators in syntax tree below this rule
282  if (!vpVecPop(spCtx->vpOpenRules)) {
283  XTHROW(spCtx->spException, s_cpEmpty);
284  return;
285  }
286 }
287 
288 void vBkrpUdtClose(void* vpCtx, aint uiIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength) {
289  backref* spCtx = (backref*) vpCtx;
290  if (spCtx->spUdts[uiIndex].uiIsBackRef && (uiState == ID_MATCH)) {
291  vSetPhrase(spCtx, spCtx->spUdts[uiIndex].uiBackRefIndex, uiPhraseOffset, uiPhraseLength);
292  }
293 }
294 
295 void vBkrpOpOpen(void* vpCtx) {
296  backref* spCtx = (backref*) vpCtx;
297  aint* uipCheckPoints;
298  aint* uipOpen = (aint*) vpVecLast(spCtx->vpOpenRules);
299  if (!uipOpen) {
300  XTHROW(spCtx->spException, s_cpEmpty);
301  }
302  if (*uipOpen) {
303  uipCheckPoints = (aint*)vpVecPush(spCtx->vpCheckPoints, NULL);
304  vSetCheckPoints(spCtx, uipCheckPoints);
305  }
306 }
307 
308 void vBkrpOpClose(void* vpCtx, aint uiState) {
309  backref* spCtx = (backref*) vpCtx;
310  aint* uipCheckPoints;
311  aint* uipOpen = (aint*) vpVecLast(spCtx->vpOpenRules);
312  if (!uipOpen) {
313  XTHROW(spCtx->spException, s_cpEmpty);
314  }
315  if (*uipOpen) {
316  uipCheckPoints = (aint*)vpVecPop(spCtx->vpCheckPoints);
317  if (!uipCheckPoints) {
318  XTHROW(spCtx->spException, s_cpEmpty);
319  }
320  if(uiState == ID_NOMATCH){
321  vRestoreCheckPoints(spCtx, uipCheckPoints);
322  }
323  }
324 }
325 
326 bkr_phrase sBkrpFetch(void* vpCtx, aint uiIndex) {
327  backref* spCtx = (backref*) vpCtx;
328  bkr_phrase* spFrame;
329  bkr_phrase sReturn;
330  if (uiIndex < spCtx->spParserCtx->uiRuleCount) {
331 
332  // !!!! DEBUG
333 // aint uiLen = uiVecLen(spCtx->vppPhraseStacks[spCtx->spRules[uiIndex].uiBackRefIndex]);
334 // aint ui;
335 // bkr_phrase* spPhrase = (bkr_phrase*)vpVecFirst(spCtx->vppPhraseStacks[spCtx->spRules[uiIndex].uiBackRefIndex]);
336 // printf("sBkrpFetch: phrase frames: %"PRIuMAX"\n", (luint)uiLen);
337 // for(ui = 0; ui < uiLen; ui++, spPhrase++){
338 // printf(" phrase offset: %"PRIuMAX": phrase length: %"PRIuMAX"\n", (luint)spPhrase->uiPhraseOffset, (luint)spPhrase->uiPhraseLength);
339 // }
340  // !!!! DEBUG
341 
342  spFrame = (bkr_phrase*) vpVecLast(spCtx->vppPhraseStacks[spCtx->spRules[uiIndex].uiBackRefIndex]);
343  if (!spFrame) {
344  XTHROW(spCtx->spException, "unexpected empty phrase stack vector");
345  }
346  sReturn.uiPhraseLength = spFrame->uiPhraseLength;
347  sReturn.uiPhraseOffset = spFrame->uiPhraseOffset;
348  } else {
349  spFrame = (bkr_phrase*) vpVecLast(
350  spCtx->vppPhraseStacks[spCtx->spUdts[uiIndex - spCtx->spParserCtx->uiRuleCount].uiBackRefIndex]);
351  if (!spFrame) {
352  XTHROW(spCtx->spException, "unexpected empty phrase stack vector");
353  }
354  sReturn.uiPhraseLength = spFrame->uiPhraseLength;
355  sReturn.uiPhraseOffset = spFrame->uiPhraseOffset;
356  }
357  return sReturn;
358 }
359 
360 static void vFreeAll(backref* spCtx){
361  // free all vectors
362  aint ui;
363  for(ui = 0; ui < spCtx->uiBkrCount; ui += 1){
364  vVecDtor(spCtx->vppPhraseStacks[ui]);
365  }
366  vVecDtor(spCtx->vpCheckPoints);
367  vVecDtor(spCtx->vpOpenRules);
368  // free all memory allocations
369  void* vpMem = spCtx->spParserCtx->vpMem;
370  vMemFree(vpMem, spCtx->vppPhraseStacks);
371  vMemFree(vpMem, (void*)spCtx->spRules);
372  vMemFree(vpMem, (void*)spCtx->spUdts);
373  memset((void*)spCtx, 0, sizeof(*spCtx));
374  vMemFree(vpMem, (void*)spCtx);
375 }
376 
377 static void vSetCheckPoints(backref* spCtx, aint* uipCheckPoints) {
378  aint ui;
379  for (ui = 0; ui < spCtx->uiBkrCount; ui += 1) {
380  uipCheckPoints[ui] = uiVecLen(spCtx->vppPhraseStacks[ui]);
381  }
382 }
383 static void vRestoreCheckPoints(backref* spCtx, aint* uipCheckPoints) {
384  aint ui;
385  for (ui = 0; ui < spCtx->uiBkrCount; ui += 1) {
386  vpVecPopi(spCtx->vppPhraseStacks[ui], uipCheckPoints[ui]);
387  }
388 }
389 static void vSetPhrase(backref* spCtx, aint uiIndex, aint uiOffset, aint uiLength) {
390  bkr_phrase sPhrase = { uiOffset, uiLength };
391  aint uiLen = uiVecLen(spCtx->vppPhraseStacks[uiIndex]);
392  if(uiLen){
393  bkr_phrase* spPhrase = (bkr_phrase*)vpVecFirst(spCtx->vppPhraseStacks[uiIndex]);
394  aint ui;
395  for(ui = 0; ui < uiLen; ui++, spPhrase++){
396  if(spPhrase->uiPhraseOffset == APG_UNDEFINED){
397  *spPhrase = sPhrase;
398  }
399  }
400  }
401 }
402 
403 static void vPushEmptyPhrase(backref* spCtx) {
404  bkr_phrase sPhrase = { APG_UNDEFINED, APG_UNDEFINED };
405  aint ui = 0;
406  for(; ui < spCtx->uiBkrCount; ui += 1){
407  vpVecPush(spCtx->vppPhraseStacks[ui], (void*) &sPhrase);
408  }
409 }
410 
411 static void vSetAllParents(backref* spCtx, bkrp_input* spInput) {
412  aint uiLen = uiVecLen(spInput->vpVecStack);
413  if (uiLen) {
414  aint ui = 0;
415  bkrp_frame* spBeg = (bkrp_frame*) vpVecFirst(spInput->vpVecStack);
416  if (!spBeg) {
417  XTHROW(spCtx->spException, s_cpEmpty);
418  }
419  for (; ui < uiLen; ui += 1) {
420  spBeg[ui].spRule->uiHasBackRef = uiFound;
421  }
422  }
423 }
424 static void vRnmWalk(backref* spCtx, bkrp_input* spInput) {
425  bkrp_frame* spFrame;
426 // print sPrint;
427  bkr_rule* spRule = spInput->spRule;
428 // sPrint.spRule = spInput->spRule;
429  if (spRule->uiHasBackRef == uiOpen) {
430  if (spRule->uiIsBackRef) {
431  // set all rules on the open frames
432  vSetAllParents(spCtx, spInput);
433 // sPrint.uiDirection = uiInner;
434 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
435 // vPrintRule(&sPrint);
436  }
437 // sPrint.uiDirection = uiInner;
438 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
439 // sPrint.uiState = uiRecursive;
440 // vPrintRule(&sPrint);
441  } else if (spRule->uiHasBackRef == uiUndefined) {
442  if (spRule->uiIsBackRef) {
443  // set all rules on the open frames
444  vSetAllParents(spCtx, spInput);
445 // sPrint.uiDirection = uiInner;
446 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
447 // sPrint.uiState = uiIsBkr;
448 // vPrintRule(&sPrint);
449  }
450 
451 // sPrint.uiDirection = uiDown;
452 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
453 // sPrint.uiState = spRule->uiHasBackRef;
454 // vPrintRule(&sPrint);
455 
456  spFrame = (bkrp_frame*) vpVecPush(spInput->vpVecStack, NULL);
457  spFrame->spRule = spRule;
458  spInput->spOp = spRule->spRule->spOp;
459  spRule->uiHasBackRef = uiOpen;
460  vOpWalk(spCtx, spInput);
461  if (spRule->uiHasBackRef == uiOpen) {
462  spRule->uiHasBackRef = uiNotFound;
463  }
464  if (!vpVecPop(spInput->vpVecStack)) {
465  XTHROW(spCtx->spException, s_cpEmpty);
466  }
467 
468 // sPrint.uiDirection = uiUp;
469 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
470 // sPrint.uiState = spRule->uiHasBackRef;
471 // vPrintRule(&sPrint);
472  } else {
473  if (spRule->uiHasBackRef || spRule->uiIsBackRef) {
474  // set all rules on the open frames
475  vSetAllParents(spCtx, spInput);
476 // sPrint.uiDirection = uiInner;
477 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
478 // sPrint.uiState = uiIsBkr;
479 // vPrintRule(&sPrint);
480  }
481  // already know the state
482 // sPrint.uiDirection = uiDown;
483 // sPrint.uiTreeDepth = uiVecLen(spInput->vpVecStack);
484 // sPrint.uiState = spRule->uiHasBackRef;
485 // vPrintRule(&sPrint);
486 // sPrint.uiDirection = uiUp;
487 // vPrintRule(&sPrint);
488  }
489 }
490 static void vAltWalk(backref* spCtx, bkrp_input* spInput) {
491  const aint* uipChildBeg = spInput->spOp->sAlt.uipChildList;
492  const aint* uipChildEnd = uipChildBeg + spInput->spOp->sAlt.uiChildCount;
493  for (; uipChildBeg < uipChildEnd; uipChildBeg++) {
494  spInput->spOp = spCtx->spParserCtx->spOpcodes + *uipChildBeg;
495  vOpWalk(spCtx, spInput);
496  }
497 }
498 static void vCatWalk(backref* spCtx, bkrp_input* spInput) {
499  const aint* uipChildBeg = spInput->spOp->sCat.uipChildList;
500  const aint* uipChildEnd = uipChildBeg + spInput->spOp->sCat.uiChildCount;
501  for (; uipChildBeg < uipChildEnd; uipChildBeg++) {
502  spInput->spOp = spCtx->spParserCtx->spOpcodes + *uipChildBeg;
503  vOpWalk(spCtx, spInput);
504  }
505 }
506 static void vRepWalk(backref* spCtx, bkrp_input* spInput) {
507  spInput->spOp = spInput->spOp + 1;
508  vOpWalk(spCtx, spInput);
509 }
510 static void vOpWalk(backref* spCtx, bkrp_input* spInput) {
511  switch (spInput->spOp->sGen.uiId) {
512  case ID_RNM:
513  spInput->spRule = &spCtx->spRules[spInput->spOp->sRnm.spRule->uiRuleIndex];
514  vRnmWalk(spCtx, spInput);
515  break;
516  case ID_UDT:
517  if (spCtx->spUdts[spInput->spOp->sUdt.spUdt->uiUdtIndex].uiIsBackRef) {
518  vSetAllParents(spCtx, spInput);
519  }
520  break;
521  case ID_ALT:
522  vAltWalk(spCtx, spInput);
523  break;
524  case ID_CAT:
525  vCatWalk(spCtx, spInput);
526  break;
527  case ID_REP:
528  vRepWalk(spCtx, spInput);
529  break;
530  default:
531  // all other operators either terminals or empty strings
532  break;
533  }
534 }
535 static aint uiSESTWalk(backref* spCtx) {
536  aint uiReturn = APG_FAILURE;
537  aint ui;
538  bkrp_input sInput;
539  while (APG_TRUE) {
540  sInput.vpVecStack = vpVecCtor(spCtx->spParserCtx->vpMem, (aint) sizeof(bkrp_frame), 100);
541  if (setjmp(sInput.aJumpBuf) != 0) {
542  break;
543  }
544 
545  // walk the SEST of each rule
546  for (ui = 0; ui < spCtx->spParserCtx->uiRuleCount; ui += 1) {
547  sInput.spRule = &spCtx->spRules[ui];
548  if (sInput.spRule->uiHasBackRef == uiUndefined) {
549 // printf("SEST WALK BEGIN: RULE: %s\n", sInput.spRule->spRule->cpRuleName);
550  vRnmWalk(spCtx, &sInput);
551 // printf("SEST WALK END: tree depth: %"PRIuMAX"\n", (luint) uiVecLen(sInput.vpVecStack));
552 // printf("\n");
553  }
554  }
555 
556  // success
557  uiReturn = APG_SUCCESS;
558  break;
559  }
560  vVecDtor(sInput.vpVecStack);
561  return uiReturn;
562 }
563 
564 // !!!! DEBUG
565 //static char* cpState(aint uiState) {
566 // if (uiState == uiUndefined) {
567 // return "undefined";
568 // }
569 // if (uiState == uiNotFound) {
570 // return "BKR not found";
571 // }
572 // if (uiState == uiFound) {
573 // return "BKR found";
574 // }
575 // if (uiState == uiOpen) {
576 // return "recursive rule open";
577 // }
578 // if (uiState == uiIsBkr) {
579 // return "rule is back referenced";
580 // }
581 // return "unknown";
582 //}
583 //static void vPrintRule(print* spPrint) {
584 // aint ui = 0;
585 // bkr_rule* spRule = spPrint->spRule;
586 //
587 // // indent
588 // for (; ui < spPrint->uiTreeDepth; ui += 1) {
589 // printf(" ");
590 // }
591 // if (spPrint->uiDirection == uiDown) {
592 // printf("+");
593 // } else if (spPrint->uiDirection == uiUp) {
594 // printf("-");
595 // } else if (spPrint->uiDirection == uiInner) {
596 // printf("=>");
597 // } else {
598 // printf("???");
599 // }
600 // printf("%s: node state: %s: rule uiHasBackRef: %s\n", spRule->spRule->cpRuleName, cpState(spPrint->uiState),
601 // cpState(spRule->uiHasBackRef));
602 //}
603 // !!!! DEBUG
604 #endif /* APG_BKR */
605 
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.
apg.h
The APG header file.
APG_FAILURE
#define APG_FAILURE
Definition: apg.h:308
bkrp_frame::spRule
bkr_rule * spRule
Definition: backrefp.c:55
ID_RNM
#define ID_RNM
rule name
Definition: parser.h:46
bkr_udt::uiBackRefIndex
aint uiBackRefIndex
If this UDT is back referenced, this is the UDT's index in the bkr map.
Definition: backref.h:56
parserp.h
Private header for the SABNF parser.
bkrp_input::spRule
bkr_rule * spRule
Definition: backrefp.c:60
backref::vpCheckPoints
void * vpCheckPoints
A stack of check points (a check point is the current record count in each of the frame stacks).
Definition: backref.h:79
vVecDtor
void vVecDtor(void *vpCtx)
The vector component destructor.
Definition: vector.c:161
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
bkrp_input::spOp
const opcode * spOp
Definition: backrefp.c:59
ID_UDT
#define ID_UDT
user-defined terminal
Definition: parser.h:55
backref::spException
exception * spException
Pointer to the exception structure for reporting fatal errors.
Definition: backref.h:73
bkr_udt::uiIsBackRef
aint uiIsBackRef
APG_TRUE if this UDT has been back referenced in, APG_FALSE otherwise.
Definition: backref.h:55
rule::spOp
const union opcode_tag * spOp
Pointer to the first opcode of the rule.
Definition: parserp.h:122
bkr_phrase::uiPhraseOffset
aint uiPhraseOffset
The offset to the matched phrase.
Definition: backref.h:64
vBkrpRuleClose
void vBkrpRuleClose(void *vpCtx, aint uiIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength)
Definition: backrefp.c:265
backref::uiBkrCount
aint uiBkrCount
Number of back referenced rules/UDTS.
Definition: backref.h:81
backref::spParserCtx
parser * spParserCtx
Pointer to the parser context that created this object.
Definition: backref.h:74
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
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
vpVecLast
void * vpVecLast(void *vpCtx)
Get the last element one the vector. The vector is not altered.
Definition: vector.c:343
backref.h
Private declarations common to both universal and parent modes.
spMemException
exception * spMemException(void *vpCtx)
Get a pointer to this memory objects's exception handler.
Definition: memory.c:174
ID_CAT
#define ID_CAT
concatenation
Definition: parser.h:44
bkr_udt
Back referencing information for each UDT.
Definition: backref.h:53
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
bkr_phrase::uiPhraseLength
aint uiPhraseLength
The matched phrase length.
Definition: backref.h:65
uiVecLen
aint uiVecLen(void *vpCtx)
Get the vector length. That is, the number of elements on the vector.
Definition: vector.c:385
vpVecCtor
void * vpVecCtor(void *vpMem, aint uiElementSize, aint uiInitialAlloc)
The vector object constructor.
Definition: vector.c:118
ID_REP
#define ID_REP
repetition
Definition: parser.h:45
vBkrpUdtClose
void vBkrpUdtClose(void *vpCtx, aint uiIndex, aint uiState, aint uiPhraseOffset, aint uiPhraseLength)
Definition: backrefp.c:288
backref::spUdts
bkr_udt * spUdts
Pointer to the back reference UDT information.
Definition: backref.h:76
APG_SUCCESS
#define APG_SUCCESS
Definition: apg.h:307
vMemFree
void vMemFree(void *vpCtx, const void *vpData)
Free memory previously allocated with vpMemAlloc().
Definition: memory.c:226
bkrp_input
Definition: backrefp.c:58
bkrp_frame
Definition: backrefp.c:54
bkr_rule::spRule
rule * spRule
Definition: backref.h:44
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
backref
The back reference object's context.
Definition: backref.h:71
backref::vppPhraseStacks
void ** vppPhraseStacks
An array of frame structs, vector context if rule/UDT index is universally back referenced....
Definition: backref.h:77
bkrp_input::aJumpBuf
jmp_buf aJumpBuf
Definition: backrefp.c:61
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
vBkrpOpClose
void vBkrpOpClose(void *vpCtx, aint uiState)
Definition: backrefp.c:308
bkrp_input::vpVecStack
void * vpVecStack
Definition: backrefp.c:62
bkr_rule::uiIsBackRef
aint uiIsBackRef
APG_TRUE if this rule has been back referenced, APG_FALSE otherwise.
Definition: backref.h:46
vBkrpRuleOpen
void vBkrpRuleOpen(void *vpCtx, aint uiIndex)
Definition: backrefp.c:246
vBkrpOpOpen
void vBkrpOpOpen(void *vpCtx)
Definition: backrefp.c:295
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
bkr_phrase
Defines one frame on the back reference stack.
Definition: backref.h:63
vpVecPopi
void * vpVecPopi(void *vpCtx, aint uiIndex)
Pops the element at the given zero-based index and all higher indexes.
Definition: vector.c:306
ID_NOMATCH
#define ID_NOMATCH
indicates that no phrase was matched on return from parse tree below this node
Definition: parser.h:74
bkr_rule::uiBackRefIndex
aint uiBackRefIndex
If this rule is back referenced, this is the rule's index in the bkr map.
Definition: backref.h:47
bkr_rule::uiHasBackRef
aint uiHasBackRef
APG_TRUE if this rule refers to a referenced rule in it syntax tree, APG_FALSE otherwise.
Definition: backref.h:45
sBkrpFetch
bkr_phrase sBkrpFetch(void *vpCtx, aint uiIndex)
Definition: backrefp.c:326
bkr_rule
Back referencing information for each rule.
Definition: backref.h:43
vpBkrpCtor
void * vpBkrpCtor(parser *spParserCtx)
The parent-mode back reference object constructor.
Definition: backrefp.c:97
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
backref::spRules
bkr_rule * spRules
Pointer to the back reference rule information.
Definition: backref.h:75
backref::vpOpenRules
void * vpOpenRules
A stack indicating if the top rule has a BKR in its syntax tree.
Definition: backref.h:80
ID_BKR_MODE_P
#define ID_BKR_MODE_P
the back reference is parent mode
Definition: parser.h:119
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.