Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
semantics.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 "./api.h"
35 #include "./apip.h"
36 #include "./semantics.h"
37 
38 //#define SEMANTICS_DEBUG 1
39 #ifdef SEMANTICS_DEBUG
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44 
45 #include "./parserp.h"
46 #include "./astp.h"
47 #include "../utilities/utilities.h"
48 static void vPrintSemanticOpcodes(api* spApi, semantic_data* spData);
49 #endif /* SEMANTICS_DEBUG */
50 
51 #define BUF_SIZE 256
52 
53 static void vGenerateUdtList(api* spApi, semantic_data* spData);
54 static void vValidateRnmOps(api* spApi, semantic_data* spData);
55 static void vValidateBkrOps(api* spApi, semantic_data* spData);
56 static void vReduceOpcodes(api* spApi, semantic_data* spData);
57 static void vStringTable(api* spApi, semantic_data* spData);
58 static abool bLCCompare(const char* cpL, aint uiLLen, const char* cpR, aint uiRLen);
59 static void vPpptSize(api* spApi);
60 
64 void vApiOpcodes(void* vpCtx) {
65  if(!bApiValidate(vpCtx)){
66  vExContext();
67  }
68  api* spApi = (api*) vpCtx;
69  semantic_data sData = {};
70  memset((void*) &sData, 0, sizeof(sData));
71  vMsgsClear(spApi->vpLog);
72  // validate that we are at the semantic stage
73  if (!spApi->bInputValid) {
74  XTHROW(spApi->spException,
75  "attempted opcodes phase but input grammar not validated");
76  }
77  if (!spApi->bSyntaxValid) {
78  XTHROW(spApi->spException,
79  "attempted opcodes phase but syntax not validated");
80  }
81  if (spApi->bSemanticsValid) {
82  XTHROW(spApi->spException,
83  "attempted opcodes phase but opcodes have already been constructed and validated");
84  }
85 
86  // initialize the callback data
87  sData.vpMem = spApi->vpMem;
88  sData.spApi = spApi;
89  sData.vpVecAcharsTable = vpVecCtor(sData.vpMem, sizeof(luint), 1000);
90  sData.vpVecChildIndexTable = vpVecCtor(sData.vpMem, sizeof(aint), 1000);
91  sData.vpVecStringTable = vpVecCtor(sData.vpMem, sizeof(char), 1000);
92  sData.vpVecRules = vpVecCtor(sData.vpMem, sizeof(semantic_rule), 1000);
93  sData.vpVecUdts = vpVecCtor(sData.vpMem, sizeof(semantic_udt), 1000);
94 
95  // semantics - translate the AST generated in the syntax phase
96  // NOTE: the achar table (for TLS/TBS character strings) is created during translation (semantic-callbacks.c)
97  vAstTranslate(spApi->vpAst, &sData);
98 
99  // scan the opcodes and find all UDTs referenced
100  vGenerateUdtList(spApi, &sData);
101 
102  // make sure all RNM and BKR operators refer to defined rules or UDTs
103  vValidateRnmOps(spApi, &sData);
104  vValidateBkrOps(spApi, &sData);
105 
106  // create the string table and initialize the rule and UDT lists
107  vStringTable(spApi, &sData);
108 
109  // eliminate redundant opcodes (ALT & CAT with only one child, REP(1,1) or 1*1)
110  // this also moves all required data from sData, to the permanent API context
111 #ifdef SEMANTICS_DEBUG
112  vPrintSemanticOpcodes(spApi, &sData);
113  vReduceOpcodes(spApi, &sData);
114  break;
115  }
116  vPrintGeneratedOpcodes(spApi);
117 #else
118  vReduceOpcodes(spApi, &sData);
119 #endif /* SEMANTICS_DEBUG */
120  vPpptSize(spApi);
121 
122  // AST translation to opcodes success
123  spApi->bSemanticsValid = APG_TRUE;
124 
125  // free the callback data
126  vVecDtor(sData.vpVecAcharsTable);
127  vVecDtor(sData.vpVecChildIndexTable);
128  vVecDtor(sData.vpVecStringTable);
129  aint ui = 0;
130  aint uiRules = uiVecLen(sData.vpVecRules);
131  semantic_rule* spRules = vpVecFirst(sData.vpVecRules);
132  if(!spRules || !uiRules){
133  XTHROW(spApi->spException, "no rule names found");
134  }
135  for(; ui < uiRules; ui++){
136  vVecDtor(spRules[ui].vpVecAltStack);
137  vVecDtor(spRules[ui].vpVecCatStack);
138  semantic_op* spOp = (semantic_op*)vpVecFirst(spRules[ui].vpVecOps);
139  semantic_op* spOpEnd = (semantic_op*)vpVecLast(spRules[ui].vpVecOps);
140  if(spOp){
141  for(; spOp <= spOpEnd; spOp++){
142  vVecDtor(spOp->vpVecChildList);
143  }
144  }
145  vVecDtor(spRules[ui].vpVecOps);
146  }
147  vVecDtor(sData.vpVecRules);
148  vVecDtor(sData.vpVecUdts);
149 }
150 
160 aint uiFindRule(semantic_rule* spRules, aint uiRuleCount, const char* cpName, aint uiNameLength) {
161  aint ui, uiFound;
162  for(ui = 0; ui < uiRuleCount; ui++){
163  uiFound = bLCCompare(spRules->cpName, spRules->uiNameLength, cpName, uiNameLength);
164  if (uiFound) {
165  return ui;
166  }
167  spRules++;
168  }
169  return APG_UNDEFINED;
170 }
171 
172 aint uiFindUdt(semantic_udt* spUdts, aint uiUdtCount, const char* cpName, aint uiNameLength) {
173  aint ui, uiFound;
174  for(ui = 0; ui < uiUdtCount; ui++){
175  uiFound = bLCCompare(spUdts->cpName, spUdts->uiNameLength, cpName, uiNameLength);
176  if (uiFound) {
177  return ui;
178  }
179  spUdts++;
180  }
181  return APG_UNDEFINED;
182 }
183 
184 static abool bLCCompare(const char* cpL, aint uiLLen, const char* cpR, aint uiRLen) {
185  if (uiLLen == uiRLen) {
186  char l, r;
187  while (uiLLen--) {
188  l = *cpL;
189  if (l >= 65 && l <= 90) {
190  l += 32;
191  }
192  r = *cpR;
193  if (r >= 65 && r <= 90) {
194  r += 32;
195  }
196  if (l != r) {
197  return APG_FALSE;
198  }
199  cpL++;
200  cpR++;
201  }
202  return APG_TRUE;
203  }
204  return APG_FALSE;
205 }
211 static void vStringTable(api* spApi, semantic_data* spData) {
212  // compute the string table length
213  semantic_rule* spSemRules = (semantic_rule*) vpVecFirst(spData->vpVecRules);
214  semantic_udt* spSemUdts = (semantic_udt*) vpVecFirst(spData->vpVecUdts);
215  aint uiSize = 0;
216  char* cpNext;
217  api_rule* spRule;
218  api_udt* spUdt;
219  aint ui;
220  spApi->uiRuleCount = uiVecLen(spData->vpVecRules);
221  spApi->uiUdtCount = uiVecLen(spData->vpVecUdts);
222  for (ui = 0; ui < spApi->uiRuleCount; ui++) {
223  uiSize += spSemRules[ui].uiNameLength + 1;
224  }
225  for (ui = 0; ui < spApi->uiUdtCount; ui++) {
226  uiSize += spSemUdts[ui].uiNameLength + 1;
227  }
228  uiSize += strlen(APG_VERSION) + 1;
229  uiSize += strlen(APG_COPYRIGHT) + 1;
230  uiSize += strlen(APG_LICENSE) + 1;
231  uiSize++;
232 
233  // get the string table
234  spApi->cpStringTable = (char*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(char) * uiSize));
235  spApi->uiStringTableLength = uiSize;
236  memset((void*) spApi->cpStringTable, 0, (sizeof(char) * uiSize));
237 
238  // get the achar table
239  uiSize = uiVecLen(spData->vpVecAcharsTable);
240  if(uiSize){
241  spApi->luipAcharTable = (luint*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(luint) * uiSize));
242  spApi->uiAcharTableLength = uiSize;
243  memcpy((void*) spApi->luipAcharTable, vpVecFirst(spData->vpVecAcharsTable), (sizeof(luint) * uiSize));
244  }else{
245  spApi->luipAcharTable = NULL;
246  spApi->uiAcharTableLength = 0;
247  }
248 
249  // allocate the rule list
250  spApi->spRules = (api_rule*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(api_rule) * spApi->uiRuleCount));
251  memset((void*) spApi->spRules, 0, (sizeof(api_rule) * spApi->uiRuleCount));
252 
253  if (spApi->uiUdtCount) {
254  // allocate the UDT list
255  spApi->spUdts = (api_udt*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(api_udt) * spApi->uiUdtCount));
256  memset((void*) spApi->spUdts, 0, (sizeof(api_udt) * spApi->uiUdtCount));
257  }
258 
259  // initialize the rule list and put rule names in string table
260  cpNext = spApi->cpStringTable;
261  spRule = spApi->spRules;
262  for (ui = 0; ui < spApi->uiRuleCount; ui++, spRule++) {
263  memcpy(cpNext, spSemRules[ui].cpName, spSemRules[ui].uiNameLength);
264  spRule->cpName = cpNext;
265  spRule->uiIndex = ui;
266  cpNext += spSemRules[ui].uiNameLength + 1;
267  }
268 
269  // initialize the UDT list, if any, and put rule names in string table
270  spUdt = spApi->spUdts;
271  for (ui = 0; ui < spApi->uiUdtCount; ui++, spUdt++) {
272  memcpy(cpNext, spSemUdts[ui].cpName, spSemUdts[ui].uiNameLength);
273  spUdt->cpName = cpNext;
274  spUdt->uiIndex = ui;
275  spUdt->uiEmpty = spSemUdts[ui].uiEmpty;
276  cpNext += spSemUdts[ui].uiNameLength + 1;
277  }
278 
279  // add the version info
280  spApi->uiVersionOffset = cpNext - spApi->cpStringTable;
281  strcpy(cpNext, APG_VERSION);
282  cpNext += strlen(APG_VERSION) + 1;
283  spApi->uiVersionLength = strlen(APG_VERSION) + 1;
284 
285  // add the license info
286  spApi->uiLicenseOffset = cpNext - spApi->cpStringTable;
287  strcpy(cpNext, APG_LICENSE);
288  cpNext += strlen(APG_LICENSE) + 1;
289  spApi->uiLicenseLength = strlen(APG_LICENSE) + 1;
290 
291  // add the copyright info
292  spApi->uiCopyrightOffset = cpNext - spApi->cpStringTable;
293  strcpy(cpNext, APG_COPYRIGHT);
294  cpNext += strlen(APG_COPYRIGHT) + 1;
295  spApi->uiCopyrightLength = strlen(APG_COPYRIGHT) + 1;
296 }
297 
298 static void vGenerateUdtList(api* spApi, semantic_data* spData) {
299  semantic_op* spOp;
300  aint uiUdtCount;
301  semantic_udt* spUdts;
302  aint uiFound;
303  semantic_op* spOps;
304  aint uiRuleCount;
305  aint ui, uii;
306  aint uiOpCount;
307  semantic_udt sUdt;
308  semantic_rule* spRules;
309  char caBuf[BUF_SIZE];
310  spRules = (semantic_rule*) vpVecFirst(spData->vpVecRules);
311  if (!spRules) {
312  XTHROW(spData->spApi->spException, "grammar contains no rules");
313  }
314  uiRuleCount = uiVecLen(spData->vpVecRules);
315  for (ui = 0; ui < uiRuleCount; ui++) {
316  spOps = (semantic_op*) vpVecFirst(spRules[ui].vpVecOps);
317  if (!spOps) {
318  snprintf(caBuf, BUF_SIZE, "rule %"PRIuMAX" has no opcodes", (luint) ui);
319  XTHROW(spData->spApi->spException, caBuf);
320  }
321  uiOpCount = uiVecLen(spRules[ui].vpVecOps);
322  for (uii = 0; uii < uiOpCount; uii++) {
323  spOp = &spOps[uii];
324  if (spOp->uiId == ID_UDT) {
325  sUdt.cpName = spOp->cpName;
326  sUdt.uiNameLength = spOp->uiNameLength;
327  sUdt.uiEmpty = spOp->uiEmpty;
328  uiUdtCount = uiVecLen(spData->vpVecUdts);
329  spUdts = (semantic_udt*) vpVecFirst(spData->vpVecUdts);
330  uiFound = uiFindUdt(spUdts, uiUdtCount, sUdt.cpName, sUdt.uiNameLength);
331  if (uiFound == APG_UNDEFINED) {
332  sUdt.uiIndex = spData->uiUdtIndex++;
333  spOp->uiBkrIndex = sUdt.uiIndex;
334  vpVecPush(spData->vpVecUdts, (void*) &sUdt);
335  }else{
336  // add the UDT index to the UDT opcode
337  spOp->uiBkrIndex = uiFound;
338  }
339  }
340  }
341  }
342 
343  /*
344  // !!!! SEMANTICS_DEBUG
345  spUdts = (semantic_udt*) vpVecFirst(spData->vpVecUdts);
346  uiUdtCount = uiVecLen(spData->vpVecUdts);
347  printf("\nUDTS FOUND: %"PRIuMAX"\n", (luint) uiUdtCount);
348  for (ui = 0; ui < uiUdtCount; ui++) {
349  char* cpTF;
350  char caBuf[128];
351  memcpy((void*) &caBuf[0], (void*) spUdts[ui].cpName, (size_t) spUdts[ui].uiNameLength);
352  caBuf[spUdts[ui].uiNameLength] = 0;
353  printf("UDT: %s: empty: ", caBuf);
354  cpTF = spUdts[ui].uiEmpty ? "TRUE" : "FALSE";
355  printf("%s\n", cpTF);
356  }
357 */
358 }
359 
360 static void vValidateRnmOps(api* spApi, semantic_data* spData) {
361  semantic_op* spOp;
362  aint uiFound;
363  semantic_op* spOps;
364  aint uiRuleCount;
365  aint ui, uii;
366  aint uiOpCount;
367  semantic_rule* spRules;
368  char caBuf[BUF_SIZE];
369  spRules = (semantic_rule*) vpVecFirst(spData->vpVecRules);
370  if (!spRules) {
371  XTHROW(spData->spApi->spException, "grammar contains no rules");
372  }
373  uiRuleCount = uiVecLen(spData->vpVecRules);
374  for (ui = 0; ui < uiRuleCount; ui++) {
375  spOps = (semantic_op*) vpVecFirst(spRules[ui].vpVecOps);
376  if (!spOps) {
377  snprintf(caBuf, BUF_SIZE, "rule %"PRIuMAX" has no opcodes", (luint) ui);
378  XTHROW(spData->spApi->spException, caBuf);
379  }
380  uiOpCount = uiVecLen(spRules[ui].vpVecOps);
381  for (uii = 0; uii < uiOpCount; uii++) {
382  spOp = &spOps[uii];
383  if (spOp->uiId == ID_RNM) {
384  uiFound = uiFindRule(spRules, uiRuleCount, spOp->cpName, spOp->uiNameLength);
385  if (uiFound == APG_UNDEFINED) {
386  aint uiIndex = spOp->cpName - spApi->cpInput;
387  char caName[126];
388  char caMsg[256];
389  memcpy((void*) &caName[0], (void*) spOp->cpName, (size_t) spOp->uiNameLength);
390  caName[spOp->uiNameLength] = 0;
391  snprintf(caMsg, 256, "rule name \"%s\" not found", caName);
392  vLineError(spApi, uiIndex, "invalid RNM", caMsg);
393  }else{
394  spOp->uiBkrIndex = uiFound;
395  }
396  }
397  }
398  if(uiMsgsCount(spApi->vpLog)){
399  XTHROW(spData->spApi->spException, "some rule names not found - see the API error log");
400  }
401  }
402 }
403 static void vValidateBkrOps(api* spApi, semantic_data* spData) {
404  semantic_op* spOp;
405  aint uiFound;
406  semantic_op* spOps;
407  aint ui, uii;
408  aint uiOpCount;
409  semantic_rule* spRules;
410  aint uiRuleCount;
411  semantic_udt* spUdts;
412  aint uiUdtCount;
413  char caBuf[BUF_SIZE];
414  spRules = (semantic_rule*) vpVecFirst(spData->vpVecRules);
415  if (!spRules) {
416  XTHROW(spData->spApi->spException, "grammar contains no rules");
417  }
418  uiRuleCount = uiVecLen(spData->vpVecRules);
419  spUdts = (semantic_udt*) vpVecFirst(spData->vpVecUdts);
420  uiUdtCount = uiVecLen(spData->vpVecUdts);
421  for (ui = 0; ui < uiRuleCount; ui++) {
422  spOps = (semantic_op*) vpVecFirst(spRules[ui].vpVecOps);
423  if (!spOps) {
424  snprintf(caBuf, BUF_SIZE, "rule %"PRIuMAX" has no opcodes", (luint) ui);
425  XTHROW(spData->spApi->spException, caBuf);
426  }
427  uiOpCount = uiVecLen(spRules[ui].vpVecOps);
428  for (uii = 0; uii < uiOpCount; uii++) {
429  spOp = &spOps[uii];
430  if (spOp->uiId == ID_BKR) {
431  uiFound = uiFindRule(spRules, uiRuleCount, spOp->cpName, spOp->uiNameLength);
432  if (uiFound == APG_UNDEFINED) {
433  uiFound = uiFindUdt(spUdts, uiUdtCount, spOp->cpName, spOp->uiNameLength);
434  if (uiFound == APG_UNDEFINED) {
435  aint uiIndex = spOp->cpName - spApi->cpInput;
436  char caName[128];
437  char caMsg[256];
438  memcpy((void*) &caName[0], (void*) spOp->cpName, (size_t) spOp->uiNameLength);
439  caName[spOp->uiNameLength] = 0;
440  snprintf(caMsg, 256, "back reference rule or UDT name, \"%s\", not found", caName);
441  vLineError(spApi, uiIndex, "invalid BKR", caMsg);
442  } else {
443  spOp->uiBkrIndex = uiRuleCount + uiFound;
444  }
445  } else {
446  spOp->uiBkrIndex = uiFound;
447  }
448  }
449  }
450  }
451  if(uiMsgsCount(spApi->vpLog)){
452  XTHROW(spData->spApi->spException, "some rule names not found - see the API error log");
453  }
454 }
455 
456 static void vReduceOpcodes(api* spApi, semantic_data* spData) {
457  aint uiSeq, uiLen, uiOpcodes, uiOffset;
458  api_rule* spApiRule;
459  semantic_rule* spRule;
460  semantic_rule* spRuleBeg = (semantic_rule*) vpVecFirst(spData->vpVecRules);
461  if(!spRuleBeg){
462  XTHROW(spData->spApi->spException, "no rules found");
463  }
464  semantic_rule* spRuleEnd = (semantic_rule*) vpVecLast(spData->vpVecRules);
465  semantic_op* spOp;
466  semantic_op* spOpEnd;
467  semantic_op* spOpChild;
468  api_op* spApiOp;
469  aint* uipIndex;
470  aint* uipIndexEnd;
471  aint* uipChildIndexTable;
472 
473  /*
474  // !!!! SEMANTICS_DEBUG
475  // set all sequence numbers and print the raw opcodes before reduction
476  spRule = spRuleBeg;
477  for (; spRule <= spRuleEnd; spRule++) {
478  spOp = (semantic_op*) vpVecFirst(spRule->vpVecOps);
479  spOpEnd = (semantic_op*) vpVecLast(spRule->vpVecOps);
480  for (uiSeq = 0; spOp <= spOpEnd; spOp++) {
481  spOp->uiSeq = uiSeq++;
482  }
483  }
484  printf("All opcodes\n");
485  vPrintSemanticOpcodes(spApi, spData);
486  // !!!! SEMANTICS_DEBUG
487 */
488 
489  // sequence essential opcodes - ALT & CAT with only one child and REP(1,1) are redundant and can be eliminated
490  spRule = spRuleBeg;
491  for (; spRule <= spRuleEnd; spRule++) {
492  spOp = (semantic_op*) vpVecFirst(spRule->vpVecOps);
493  spOpEnd = (semantic_op*) vpVecLast(spRule->vpVecOps);
494  for (uiSeq = 0; spOp <= spOpEnd; spOp++) {
495  if ((spOp->uiId == ID_ALT) || (spOp->uiId == ID_CAT)) {
496  uiLen = uiVecLen(spOp->vpVecChildList);
497  if (uiLen == 0) {
498  XTHROW(spData->spApi->spException, "ALT or CAT operator has no children");
499  }
500  if (uiVecLen(spOp->vpVecChildList) > 1) {
501  spOp->uiSeq = uiSeq++;
502  } else {
503  spOp->uiSeq = APG_UNDEFINED;
504  }
505  } else if (spOp->uiId == ID_REP) {
506  if (spOp->luiMin == 1 && spOp->luiMax == 1) {
507  spOp->uiSeq = APG_UNDEFINED;
508  } else {
509  spOp->uiSeq = uiSeq++;
510  }
511  } else {
512  spOp->uiSeq = uiSeq++;
513  }
514  }
515  }
516 
517  // reset the ALT and CAT child lists
518  spRule = spRuleBeg;
519  for (; spRule <= spRuleEnd; spRule++) {
520  spOp = (semantic_op*) vpVecFirst(spRule->vpVecOps);
521  spOpEnd = (semantic_op*) vpVecLast(spRule->vpVecOps);
522  for (; spOp <= spOpEnd; spOp++) {
523  if ((spOp->uiId == ID_ALT) || (spOp->uiId == ID_CAT)) {
524  if (spOp->uiSeq != APG_UNDEFINED) {
525  uiLen = uiVecLen(spOp->vpVecChildList);
526  if (uiLen <= 1) {
527  XTHROW(spData->spApi->spException, "ALT or CAT operator has no children");
528  }
529  uipIndex = (aint*) vpVecFirst(spOp->vpVecChildList);
530  uipIndexEnd = (aint*) vpVecLast(spOp->vpVecChildList);
531  for (; uipIndex <= uipIndexEnd; uipIndex++) {
532  spOpChild = (semantic_op*) vpVecAt(spRule->vpVecOps, *uipIndex);
533  while (spOpChild->uiSeq == APG_UNDEFINED) {
534  spOpChild++;
535  }
536  *uipIndex = spOpChild->uiSeq;
537  }
538  }
539  }
540  }
541  }
542 // printf("Reduced opcodes\n");
543 // vPrintSemanticOpcodes(spApi, spData);
544 
545  // get the size of child and opcode lists
546  spRule = spRuleBeg;
547  uiLen = 0;
548  uiOpcodes = 0;
549  for (; spRule <= spRuleEnd; spRule++) {
550  spOp = (semantic_op*) vpVecFirst(spRule->vpVecOps);
551  spOpEnd = (semantic_op*) vpVecLast(spRule->vpVecOps);
552  for (; spOp <= spOpEnd; spOp++) {
553  if (spOp->uiSeq != APG_UNDEFINED) {
554  if ((spOp->uiId == ID_ALT) || (spOp->uiId == ID_CAT)) {
555  uiLen += uiVecLen(spOp->vpVecChildList);
556  }
557  uiOpcodes++;
558  }
559  }
560  }
561 
562  // allocate the child list
563  spApi->uipChildIndexTable = (aint*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(aint) * uiLen));
564  spApi->uiChildIndexTableLength = uiLen;
565 
566  // allocate the opcode list
567  spApi->spOpcodes = (api_op*) vpMemAlloc(spApi->vpMem, (aint) (sizeof(api_op) * uiOpcodes));
568  spApi->uiOpcodeCount = uiOpcodes;
569  memset((void*)spApi->spOpcodes, 0, (sizeof(api_op) * uiOpcodes));
570 
571  // complete the API opcode and child list tables
572  aint ui;
573  aint* uipBeg;
574  spRule = spRuleBeg;
575  uiLen = 0;
576  uiOffset = 0;
577  uipChildIndexTable = spApi->uipChildIndexTable;
578  spApiRule = spApi->spRules;
579  spApiOp = spApi->spOpcodes;
580  for (; spRule <= spRuleEnd; spRule++, spApiRule++) {
581  uiOpcodes = 0;
582  spOp = (semantic_op*) vpVecFirst(spRule->vpVecOps);
583  spOpEnd = (semantic_op*) vpVecLast(spRule->vpVecOps);
584  for (; spOp <= spOpEnd; spOp++) {
585  if (spOp->uiSeq != APG_UNDEFINED) {
586  spApiOp->uiId = spOp->uiId;
587  switch (spOp->uiId) {
588  case ID_ALT:
589  case ID_CAT:
590  spApiOp->uiChildCount = uiVecLen(spOp->vpVecChildList);
591  spApiOp->uipChildIndex = uipChildIndexTable;
592  uipBeg = (aint*) vpVecFirst(spOp->vpVecChildList);
593  for(ui = 0; ui < spApiOp->uiChildCount; ui++){
594  *uipChildIndexTable++ = uiOffset + *uipBeg++;
595  }
596  break;
597  case ID_REP:
598  case ID_TRG:
599  spApiOp->luiMin = spOp->luiMin;
600  spApiOp->luiMax = spOp->luiMax;
601  break;
602  case ID_RNM:
603  spApiOp->uiIndex = spOp->uiBkrIndex;
604  break;
605  case ID_TBS:
606  case ID_TLS:
607  spApiOp->luipAchar = &spApi->luipAcharTable[spOp->uiStringIndex];
608  spApiOp->uiAcharLength = spOp->uiStringLength;
609  break;
610  case ID_UDT:
611  spApiOp->uiIndex = spOp->uiBkrIndex;
612  spApiOp->uiEmpty = spOp->uiEmpty;
613  break;
614  case ID_BKR:
615  spApiOp->uiBkrIndex = spOp->uiBkrIndex;
616  spApiOp->uiCase = spOp->uiCase;
617  spApiOp->uiMode = spOp->uiMode;
618  break;
619  case ID_AND:
620  case ID_NOT:
621  case ID_BKA:
622  case ID_BKN:
623  case ID_ABG:
624  case ID_AEN:
625  break;
626  default:
627  XTHROW(spData->spApi->spException, "unrecognized operator ID");
628  break;
629  }
630  uiOpcodes++;
631  spApiOp++;
632  }
633  }
634  spApiRule->uiOpCount = uiOpcodes;
635  spApiRule->uiOpOffset = uiOffset;
636  uiOffset += uiOpcodes;
637  }
638 // vPrintReducedOpcodes(spApi);
639 }
640 
641 static void vPpptSize(api* spApi){
642  aint ui;
643 // char caBuf[128];
644  api_op* spOp = NULL;
645 
646  // get achar min and max
647  spApi->luiAcharMin = (luint)-1;
648  spApi->luiAcharMax = 0;
649  spOp = spApi->spOpcodes;
650  for(ui = 0; ui < spApi->uiOpcodeCount; ui++, spOp++){
651  if(spOp->uiId == ID_TRG) {
652  if(spOp->luiMax > spApi->luiAcharMax){
653  spApi->luiAcharMax = spOp->luiMax;
654  }
655  if(spOp->luiMin < spApi->luiAcharMin){
656  spApi->luiAcharMin = spOp->luiMin;
657  }
658  }else if(spOp->uiId == ID_TBS){
659  if(*spOp->luipAchar > spApi->luiAcharMax){
660  spApi->luiAcharMax = *spOp->luipAchar;
661  }
662  if(*spOp->luipAchar < spApi->luiAcharMin){
663  spApi->luiAcharMin = *spOp->luipAchar;
664  }
665  }else if(spOp->uiId == ID_TLS){
666  if(spOp->uiAcharLength){
667  if(*spOp->luipAchar > spApi->luiAcharMax){
668  spApi->luiAcharMax = *spOp->luipAchar;
669  }
670  if(*spOp->luipAchar >= 97 && *spOp->luipAchar <= 122){
671  if((*spOp->luipAchar - 32) < spApi->luiAcharMin){
672  spApi->luiAcharMin = (*spOp->luipAchar - 32);
673  }
674  }else{
675  if(*spOp->luipAchar < spApi->luiAcharMin){
676  spApi->luiAcharMin = *spOp->luipAchar;
677  }
678  }
679  }
680  }
681  }
682 
683  // get map size per opcode in bytes
684  if(spApi->luiAcharMin == (luint)-1){
685  spApi->luiAcharMin = 0;
686  }
687  // NOTE: map size is the number of alphabet characters plus one for the (virtual) EOS character
688  if(spApi->luiAcharMax == (luint)-1){
689  spApi->luiAcharEos = 0;
690  spApi->luiPpptMapSize = (luint)-1;
691  }else{
692  spApi->luiAcharEos = spApi->luiAcharMax + 1;
693  spApi->luiPpptMapSize = spApi->luiAcharEos - spApi->luiAcharMin + 1;
694  }
695 
696  // compute the number of opcode maps needed
697  spApi->luiPpptMapCount = 0;
698  for(ui = 0; ui < spApi->uiRuleCount; ui++){
699  spApi->luiPpptMapCount++;
700  }
701  spOp = spApi->spOpcodes;
702  for(ui = 0; ui < spApi->uiOpcodeCount; ui++, spOp++){
703  switch (spOp->uiId) {
704  case ID_ALT:
705  case ID_CAT:
706  case ID_REP:
707  case ID_TRG:
708  case ID_TLS:
709  case ID_TBS:
710  case ID_AND:
711  case ID_NOT:
712  spApi->luiPpptMapCount++;
713  break;
714  // rule indexes set consecutively later
715  case ID_RNM:
716  // these opcodes have no PPPT map
717  // we can't predict what the user will do in a UDT
718  case ID_UDT:
719  // case insensitivity BKR it is possible for BKR to accept characters outside of AcharMin and AcharMax
720  case ID_BKR:
721  // look behind is iterative and impossible (or extremely difficult) to determine a PPPT map
722  case ID_BKA:
723  case ID_BKN:
724  // anchor opcodes only examine the character position, not the character value
725  case ID_ABG:
726  case ID_AEN:
727  break;
728  default:
729  XTHROW(spApi->spException, "unrecognized operator ID");
730  }
731  }
732 
733  // compute the PPPT table size
735  luint luiTemp, luiTest;
736  while(APG_TRUE){
737  if(!bMultiplyLong(spApi->luiPpptMapCount, spApi->luiPpptMapSize, &luiTemp)){
738 // XTHROW(spApi->spException, "multiplication overflow computing PPPT table size");
739  break;
740  }
741  if(!bMultiplyLong((luint)sizeof(uint8_t), luiTemp, &luiTest)){
742 // XTHROW(spApi->spException, "multiplication overflow computing PPPT table size");
743  break;
744  }
745  luiTemp = (luint)APG_MAX_AINT;
746  if(spApi->luiPpptMapSize >= luiTemp){
747 // snprintf(caBuf, 128, "PPPT map size too big: %"PRIuMAX"", spApi->luiPpptMapSize);
748 // XTHROW(spApi->spException, caBuf);
749  break;
750  }
751  if(spApi->luiPpptMapCount >= luiTemp){
752 // snprintf(caBuf, 128, "PPPT number of maps too big: %"PRIuMAX"", spApi->luiPpptMapCount);
753 // XTHROW(spApi->spException, caBuf);
754  break;
755  }
756  if(luiTest >= luiTemp){
757 // snprintf(caBuf, 128, "PPPT table length (bytes) too long: %"PRIuMAX"", spApi->luiPpptTableLength);
758 // XTHROW(spApi->spException, caBuf);
759  break;
760  }
761 
762  // table size is valid (but may still be too big to be handled)
763  spApi->luiPpptTableLength = luiTest;
764  break;
765  }
766 }
767 
768 #ifdef SEMANTICS_DEBUG
769 static void vPrintSemanticOpcodes(api* spApi, semantic_data* spData) {
770  char caName[RULENAME_MAX];
771  aint uiRuleCount = uiVecLen(spData->vpVecRules);
772  aint uiOpCount;
773  aint ui, uj, uk;
774  aint uiCount;
775  aint* uipBeg;
776  luint* luipBeg;
777  semantic_rule* spRules = (semantic_rule*) vpVecFirst(spData->vpVecRules);
778  semantic_rule* spRule;
779  semantic_op* spOps;
780  semantic_op* spOp;
781  printf("RAW OPCODES:\n");
782  for (ui = 0; ui < uiRuleCount; ui++) {
783  spRule = &spRules[ui];
784  memcpy(caName, spRule->cpName, spRule->uiNameLength);
785  caName[spRule->uiNameLength] = 0;
786  printf("rule: %"PRIuMAX": %s\n", (luint) ui, caName);
787  uiOpCount = uiVecLen(spRule->vpVecOps);
788  spOps = (semantic_op*) vpVecFirst(spRule->vpVecOps);
789  for (uj = 0; uj < uiOpCount; uj++) {
790  spOp = &spOps[uj];
791  if (spOp->uiSeq == APG_UNDEFINED) {
792  continue;
793  }
794  switch (spOp->uiId) {
795  case ID_ALT:
796  uiCount = uiVecLen(spOp->vpVecChildList);
797  uipBeg = (aint*) vpVecFirst(spOp->vpVecChildList);
798  printf("%"PRIuMAX": ", (luint) uj);
799  printf("ALT: ");
800  printf("children: %"PRIuMAX":", (luint) uiCount);
801  for (uk = 0; uk < uiCount; uk++, uipBeg++) {
802  if (uk == 0) {
803  printf(" %"PRIuMAX"", (luint) *uipBeg);
804  } else {
805  printf(", %"PRIuMAX"", (luint) *uipBeg);
806 
807  }
808  }
809  printf("\n");
810  break;
811  case ID_CAT:
812  uiCount = uiVecLen(spOp->vpVecChildList);
813  uipBeg = (aint*) vpVecFirst(spOp->vpVecChildList);
814  printf("%"PRIuMAX": ", (luint) uj);
815  printf("CAT: ");
816  printf("children: %"PRIuMAX":", (luint) uiCount);
817  for (uk = 0; uk < uiCount; uk++, uipBeg++) {
818  if (uk == 0) {
819  printf(" %"PRIuMAX"", (luint) *uipBeg);
820  } else {
821  printf(", %"PRIuMAX"", (luint) *uipBeg);
822 
823  }
824  }
825  printf("\n");
826  break;
827  case ID_REP:
828  printf("%"PRIuMAX": ", (luint) uj);
829  printf("REP: ");
830  printf("min: %"PRIuMAX": ", spOp->luiMin);
831  if (spOp->luiMax == (luint) -1) {
832  printf("max: infinity");
833  } else {
834  printf("max: %"PRIuMAX"", spOp->luiMax);
835  }
836  printf("\n");
837  break;
838  case ID_RNM:
839  memcpy(caName, spOp->cpName, spOp->uiNameLength);
840  caName[spOp->uiNameLength] = 0;
841  printf("%"PRIuMAX": ", (luint) uj);
842  printf("RNM: ");
843  printf("%s", caName);
844  printf("\n");
845  break;
846  case ID_TBS:
847  printf("%"PRIuMAX": ", (luint) uj);
848  printf("TBS: ");
849  uiCount = spOp->uiStringLength;
850  luipBeg = (luint*) vpVecFirst(spData->vpVecAcharsTable);
851  luipBeg += spOp->uiStringIndex;
852  for (uk = 0; uk < uiCount; uk++, luipBeg++) {
853  if (*luipBeg >= 32 && *luipBeg <= 126) {
854  printf("%c", (char) *luipBeg);
855  } else {
856  printf("0x%.2lX", *luipBeg);
857  }
858  }
859  printf("\n");
860  break;
861  case ID_TLS:
862  printf("%"PRIuMAX": ", (luint) uj);
863  printf("TLS: ");
864  uiCount = spOp->uiStringLength;
865  luipBeg = (luint*) vpVecFirst(spData->vpVecAcharsTable);
866  luipBeg += spOp->uiStringIndex;
867  for (uk = 0; uk < uiCount; uk++, luipBeg++) {
868  printf("%c", (char) *luipBeg);
869  }
870  printf("\n");
871  break;
872  case ID_TRG:
873  printf("%"PRIuMAX": ", (luint) uj);
874  printf("TRG: ");
875  printf("min: %"PRIuMAX": ", spOp->luiMin);
876  printf("max: %"PRIuMAX"", spOp->luiMax);
877  printf("\n");
878  break;
879  case ID_UDT:
880  printf("%"PRIuMAX": ", (luint) uj);
881  printf("UDT: ");
882  memcpy(caName, spOp->cpName, spOp->uiNameLength);
883  caName[spOp->uiNameLength] = 0;
884  printf("%s", caName);
885  printf("\n");
886  break;
887  case ID_AND:
888  printf("%"PRIuMAX": ", (luint) uj);
889  printf("AND: ");
890  printf("\n");
891  break;
892  case ID_NOT:
893  printf("%"PRIuMAX": ", (luint) uj);
894  printf("NOT: ");
895  printf("\n");
896  break;
897  case ID_BKA:
898  printf("%"PRIuMAX": ", (luint) uj);
899  printf("BKA: ");
900  printf("\n");
901  break;
902  case ID_BKN:
903  printf("%"PRIuMAX": ", (luint) uj);
904  printf("BKN: ");
905  printf("\n");
906  break;
907  case ID_BKR:
908  printf("%"PRIuMAX": ", (luint) uj);
909  printf("BKR: ");
910  if (spOp->uiCase == ID_BKR_CASE_I) {
911  printf("\\%%i");
912  } else {
913  printf("\\%%s");
914  }
915  if (spOp->uiMode == ID_BKR_MODE_U) {
916  printf("%%u");
917  } else {
918  printf("%%p");
919  }
920  memcpy(caName, spOp->cpName, spOp->uiNameLength);
921  caName[spOp->uiNameLength] = 0;
922  printf("%s", caName);
923  printf("\n");
924  break;
925  case ID_ABG:
926  printf("%"PRIuMAX": ", (luint) uj);
927  printf("ABG: ");
928  printf("\n");
929  break;
930  case ID_AEN:
931  printf("%"PRIuMAX": ", (luint) uj);
932  printf("AEN: ");
933  printf("\n");
934  break;
935  }
936  }
937  printf("\n");
938  }
939 }
940 #endif /* SEMANTICS_DEBUG */
semantic_udt::uiIndex
aint uiIndex
Definition: semantics.h:44
api::uiUdtCount
aint uiUdtCount
The number of UDTs referenced in the SABNF grammar.
Definition: apip.h:148
bApiValidate
abool bApiValidate(void *vpCtx)
Validates an API context pointer.
Definition: api.c:104
semantic_udt::uiEmpty
aint uiEmpty
Definition: semantics.h:45
vApiOpcodes
void vApiOpcodes(void *vpCtx)
Parse the SABNF grammar and translate its AST into opcodes for all the rules.
Definition: semantics.c:64
ID_BKR_CASE_I
#define ID_BKR_CASE_I
the back reference is case insensitive
Definition: parser.h:121
semantic_op::uiSeq
aint uiSeq
Definition: semantics.h:63
api_rule::uiIndex
aint uiIndex
index of this rule in the rule list
Definition: apip.h:57
api::spRules
api_rule * spRules
Points to an array of rule structures.
Definition: apip.h:145
api_op::luiMax
luint luiMax
maximum value for REP and TRG opcodes
Definition: apip.h:85
semantic_op::uiNameLength
aint uiNameLength
Definition: semantics.h:61
semantic_op::luiMin
luint luiMin
Definition: semantics.h:53
ID_RNM
#define ID_RNM
rule name
Definition: parser.h:46
api::uiLicenseOffset
aint uiLicenseOffset
Offset into the string table for the License string.
Definition: apip.h:153
semantic_op::vpVecChildList
void * vpVecChildList
Definition: semantics.h:52
semantic_udt
Generalized UDT for first-pass semantic processing.
Definition: semantics.h:41
api::uiOpcodeCount
aint uiOpcodeCount
Number of opcodes.
Definition: apip.h:163
api::cpInput
char * cpInput
Definition: apip.h:139
semantic_data
User data passed to the AST translator for use by the AST callback functions.
Definition: semantics.h:83
api::spOpcodes
api_op * spOpcodes
Pointer to the array of opcodes for the SANF grammar.
Definition: apip.h:162
api::uiVersionLength
aint uiVersionLength
Length of the Version Number string.
Definition: apip.h:152
api_op::uiAcharLength
aint uiAcharLength
number of characters in TLS/TBS strings
Definition: apip.h:87
parserp.h
Private header for the SABNF parser.
api::luiAcharEos
luint luiAcharEos
The special End-Of-String character. In practice, luiAcharMax + 1.
Definition: apip.h:176
api::vpLog
void * vpLog
A msglog context for error reporting.
Definition: apip.h:179
uiMsgsCount
aint uiMsgsCount(void *vpCtx)
Get the number of logged messages.
Definition: msglog.c:213
semantic_rule::vpVecOps
void * vpVecOps
Definition: semantics.h:78
vVecDtor
void vVecDtor(void *vpCtx)
The vector component destructor.
Definition: vector.c:161
semantic_op::cpName
char * cpName
Definition: semantics.h:60
ID_ALT
#define ID_ALT
alternation
Definition: parser.h:43
semantics.h
Header file for the semantic translation functions.
ID_BKR
#define ID_BKR
back reference to a previously matched rule or UDT name
Definition: parser.h:58
ID_UDT
#define ID_UDT
user-defined terminal
Definition: parser.h:55
api_rule
API information about each rule.
Definition: apip.h:55
apip.h
Private header file for the APG API suite of functions.
vExContext
void vExContext()
Handles bad context pointers.
Definition: exception.c:126
api::bInputValid
abool bInputValid
APG_TRUE if theer is input and it has been validated, APG_FALSE otherwise.
Definition: apip.h:182
api_op::uiChildCount
aint uiChildCount
number of children for this ALT or CAT operator
Definition: apip.h:83
uiFindUdt
aint uiFindUdt(semantic_udt *spUdts, aint uiUdtCount, const char *cpName, aint uiNameLength)
Definition: semantics.c:172
semantic_data::vpVecRules
void * vpVecRules
Definition: semantics.h:99
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
api::cpStringTable
char * cpStringTable
Pointer to a list of null-terminated ASCII strings representing the rule and UDT names.
Definition: apip.h:149
ID_NOT
#define ID_NOT
negative look ahead
Definition: parser.h:57
ID_AND
#define ID_AND
positive look ahead
Definition: parser.h:56
vpVecAt
void * vpVecAt(void *vpCtx, aint uiIndex)
Get a the indexed vector element. The vector is not altered.
Definition: vector.c:362
api_op::luipAchar
luint * luipAchar
pointer to the first character in the achar table for this TLS/TBS operator
Definition: apip.h:86
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
api_op::luiMin
luint luiMin
minimum value for REP and TRG opcodes
Definition: apip.h:84
semantic_op::uiMode
aint uiMode
Definition: semantics.h:57
api::spUdts
api_udt * spUdts
Points to an array of UDT structures, if one or more UDTs are referenced in the SABNF grammar.
Definition: apip.h:147
semantic_op::uiCase
aint uiCase
Definition: semantics.h:56
api::uiRuleCount
aint uiRuleCount
The number of rules in the SABNF grammar and in the array.
Definition: apip.h:146
APG_LICENSE
#define APG_LICENSE
Definition: apg.h:67
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
api::uipChildIndexTable
aint * uipChildIndexTable
Pointer to a list of child indexes. ALT & CAT operators have two or more children operators....
Definition: apip.h:159
vpVecLast
void * vpVecLast(void *vpCtx)
Get the last element one the vector. The vector is not altered.
Definition: vector.c:343
semantic_data::vpVecAcharsTable
void * vpVecAcharsTable
Definition: semantics.h:96
ID_CAT
#define ID_CAT
concatenation
Definition: parser.h:44
api_op::uiMode
aint uiMode
ID_BKR_MODE_U of ID_BKR_MODE_P for BKR.
Definition: apip.h:89
vMsgsClear
void vMsgsClear(void *vpCtx)
Clears the object of all messages.
Definition: msglog.c:124
api::uiChildIndexTableLength
aint uiChildIndexTableLength
The number of indexes (integers) in the child index table.
Definition: apip.h:161
vpMemAlloc
void * vpMemAlloc(void *vpCtx, aint uiBytes)
Allocates memory.
Definition: memory.c:196
APG_COPYRIGHT
#define APG_COPYRIGHT
Definition: apg.h:66
semantic_op::uiId
aint uiId
Definition: semantics.h:51
api::uiCopyrightOffset
aint uiCopyrightOffset
Offset into the string table for the Copyright string.
Definition: apip.h:155
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_TRG
#define ID_TRG
terminal range
Definition: parser.h:47
api_udt::cpName
char * cpName
pointer to null-terminated string in the string table
Definition: apip.h:70
ID_REP
#define ID_REP
repetition
Definition: parser.h:45
api::luiPpptMapCount
luint luiPpptMapCount
The number of operator maps in the table.
Definition: apip.h:172
api::uiLicenseLength
aint uiLicenseLength
Length of the License string.
Definition: apip.h:154
semantic_udt::cpName
char * cpName
Definition: semantics.h:42
api_op::uiCase
aint uiCase
ID_BKR_CASE_S or ID_BKR_CASE_I for BKR.
Definition: apip.h:88
api_op::uiIndex
aint uiIndex
index of this referenced rule or UDT
Definition: apip.h:80
api
The API context.
Definition: apip.h:123
api::luipAcharTable
luint * luipAcharTable
Pointer to the Achar Table - a table of all of the alphabet characters referenced by the terminal nod...
Definition: apip.h:157
RULENAME_MAX
#define RULENAME_MAX
Definition: semantics.h:37
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
APG_VERSION
#define APG_VERSION
Definition: apg.h:65
semantic_op::uiBkrIndex
aint uiBkrIndex
Definition: semantics.h:62
semantic_op
Generalized opcode for first-pass semantic processing.
Definition: semantics.h:50
APG_UNDEFINED
#define APG_UNDEFINED
Definition: apg.h:318
semantic_rule::uiNameLength
aint uiNameLength
Definition: semantics.h:71
api::bSyntaxValid
abool bSyntaxValid
APG_TRUE if the input syntax is valid, APG_FALSE otherwise.
Definition: apip.h:183
api_op
API information about each opcode.
Definition: apip.h:78
api::vpAst
void * vpAst
context handle to the AST object
Definition: apip.h:129
vpVecFirst
void * vpVecFirst(void *vpCtx)
Get the first element one the vector. The vector is not altered.
Definition: vector.c:326
api_udt
API information about each UDT.
Definition: apip.h:69
ID_BKA
#define ID_BKA
positive look behind
Definition: parser.h:59
semantic_data::spApi
api * spApi
Definition: semantics.h:84
api::uiVersionOffset
aint uiVersionOffset
Offset into the string table for the Version Number string.
Definition: apip.h:151
semantic_rule::cpName
char * cpName
Definition: semantics.h:69
semantic_op::luiMax
luint luiMax
Definition: semantics.h:54
semantic_udt::uiNameLength
aint uiNameLength
Definition: semantics.h:43
api::uiAcharTableLength
aint uiAcharTableLength
Number of alphabet characters in the Achar Table.
Definition: apip.h:158
api::luiPpptMapSize
luint luiPpptMapSize
The size, in bytes, of a single operator map.
Definition: apip.h:173
api_op::uiId
aint uiId
type of opcode, ID_ALT, etc.
Definition: apip.h:79
semantic_data::uiUdtIndex
aint uiUdtIndex
Definition: semantics.h:95
uiFindRule
aint uiFindRule(semantic_rule *spRules, aint uiRuleCount, const char *cpName, aint uiNameLength)
Find the index of the named rule in the rule list.
Definition: semantics.c:160
api::uiCopyrightLength
aint uiCopyrightLength
Length of the copyright string.
Definition: apip.h:156
ID_TLS
#define ID_TLS
terminal literal string
Definition: parser.h:49
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
api_op::uiEmpty
aint uiEmpty
APG_TRUE if this UDT can be empty, APG_FALSE otherwise
Definition: apip.h:81
semantic_op::uiStringIndex
int uiStringIndex
Definition: semantics.h:58
bMultiplyLong
abool bMultiplyLong(luint luiL, luint luiR, luint *luipA)
Multiply two long unsigned integers with overflow notification.
Definition: tools.c:110
APG_MAX_AINT
#define APG_MAX_AINT
Since the maximum unsigned integer value is used to indicate Infinite and Undefined values,...
Definition: apg.h:329
ID_BKN
#define ID_BKN
negative look behind
Definition: parser.h:60
abool
uint8_t abool
abool is the APG bool type.
Definition: apg.h:140
api_rule::cpName
char * cpName
pointer to null-terminated string in the string table
Definition: apip.h:56
api::uiStringTableLength
aint uiStringTableLength
The number of characters in the string table.
Definition: apip.h:150
api_udt::uiIndex
aint uiIndex
index of this UDT in the UDT list
Definition: apip.h:71
BUF_SIZE
#define BUF_SIZE
Definition: semantics.c:51
api::luiAcharMin
luint luiAcharMin
The minimum alphabet character referenced by the terminal nodes, TLS, TBL & TRG.
Definition: apip.h:174
api_op::uiBkrIndex
aint uiBkrIndex
if BKR, this is the index to the rule or UDT that is being back referenced
Definition: apip.h:90
api::vpMem
void * vpMem
Pointer to the memory context used for all memory allocations and exceptions thrown.
Definition: apip.h:126
astp.h
Private header file for the AST functions.
api::luiAcharMax
luint luiAcharMax
The maximum alphabet character referenced by the terminal nodes, TLS, TBL & TRG.
Definition: apip.h:175
semantic_rule
Generalized rule for first-pass semantic processing.
Definition: semantics.h:68
api_op::uipChildIndex
aint * uipChildIndex
pointer to the first child index of this ALT or CAT operator
Definition: apip.h:82
ID_ABG
#define ID_ABG
anchor - beginning of string
Definition: parser.h:61
api::spException
exception * spException
Definition: apip.h:125
api::bSemanticsValid
abool bSemanticsValid
APG_TRUE if the the input semantics are valid. That is, the opcodes for the parser have been generate...
Definition: apip.h:184
vLineError
void vLineError(api *spCtx, aint uiCharIndex, const char *cpSrc, const char *cpMsg)
Finds the grammar line associated with a character index and formats an error message to the error lo...
Definition: input.c:383
api_rule::uiOpOffset
aint uiOpOffset
offset into the opcode table to the first opcode of this rule
Definition: apip.h:58
semantic_op::uiStringLength
aint uiStringLength
Definition: semantics.h:59
ID_BKR_MODE_U
#define ID_BKR_MODE_U
the back reference is universal mode
Definition: parser.h:118
semantic_data::vpVecUdts
void * vpVecUdts
Definition: semantics.h:100
api_udt::uiEmpty
aint uiEmpty
APG_TRUE if this UDT can be empty, APG_FALSE otherwise
Definition: apip.h:72
ID_TBS
#define ID_TBS
terminal binary string
Definition: parser.h:48
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
api::luiPpptTableLength
luint luiPpptTableLength
The PPPT length.
Definition: apip.h:171
api_rule::uiOpCount
aint uiOpCount
the number of opcodes in this rule
Definition: apip.h:59
semantic_op::uiEmpty
aint uiEmpty
Definition: semantics.h:55
ID_AEN
#define ID_AEN
anchor - end of string
Definition: parser.h:62
api.h
Public header file for the APG API suite of functions.
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.