Version 7.0
Copyright © 2021 Lowell D. Thomas
APG
… an ABNF Parser Generator
main.c
Go to the documentation of this file.
1 /* *************************************************************************************
2  Copyright (c) 2021, Lowell D. Thomas
3  All rights reserved.
4 
5  This file is part of APG Version 7.0.
6  APG Version 7.0 may be used under the terms of the BSD 2-Clause License.
7 
8  Redistribution and use in source and binary forms, with or without
9  modification, are permitted provided that the following conditions are met:
10 
11  1. Redistributions of source code must retain the above copyright notice, this
12  list of conditions and the following disclaimer.
13 
14  2. Redistributions in binary form must reproduce the above copyright notice,
15  this list of conditions and the following disclaimer in the documentation
16  and/or other materials provided with the distribution.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 
29 * *************************************************************************************/
78 #include "../../api/api.h"
79 
80 #include "source.h"
81 
82 static const char* cpMakeFileName(char* cpBuffer, const char* cpBase, const char* cpDivider, const char* cpName){
83  strcpy(cpBuffer, cpBase);
84  strcat(cpBuffer, cpDivider);
85  strcat(cpBuffer, cpName);
86  return cpBuffer;
87 }
88 
89 static char* s_cpDescription =
90  "Illustrate parsing of wide characters.";
91 
92 static char* s_cppCases[] = {
93  "Display application information.",
94  "Parse lines of Cherokee language UTF-32 Unicode text.",
95 };
96 static long int s_iCaseCount = (long int)(sizeof(s_cppCases) / sizeof(s_cppCases[0]));
97 
98 static int iHelp(void){
99  long int i = 0;
101  printf("description: %s\n", s_cpDescription);
102  printf(" usage: ex-api arg\n");
103  printf(" arg = n, 1 <= n <= %ld\n", s_iCaseCount);
104  printf(" execute case number n\n");
105  printf(" arg = anthing else\n");
106  printf(" print this help screen\n");
107  printf("\n");
108  for(; i < s_iCaseCount; i++){
109  printf("case %ld %s\n", (i + 1), s_cppCases[i]);
110  }
111  return EXIT_SUCCESS;
112 }
113 
114 static int iApp() {
115  // print the current working directory
117  printf("\n");
118 
119  // display the current APG sizes and macros
120  vUtilApgInfo();
121  return EXIT_SUCCESS;
122 }
123 
124 typedef struct{
127 } my_line;
128 static void vLine(callback_data* spData) {
129  if (spData->uiParserState == ID_MATCH) {
130  // increment the A node count
131  void* vpVec = spData->vpUserData;
132  my_line* spLine = (my_line*)vpVecPush(vpVec, NULL);
133  spLine->uiOffset = spData->uiParserOffset;
134  spLine->uiLength = spData->uiParserPhraseLength;
135  }
136 }
137 static int iLines() {
138  int iReturn = EXIT_SUCCESS;
139  static void* vpApi = NULL;
140  static void* vpMem = NULL;
141  static void* vpVec = NULL;
142  static void* vpParser = NULL;
143  static FILE* spOut = NULL;
144  char* cpCherokee =
145  "lines = 1*line\n"
146  "line = line-text %d13.10\n"
147  "line-text = *(%x13A0-13F4 / %x20 / %x2e)\n";
148  uint8_t ucaBuf[1024];
149  aint uiBufSize = 1024;
150  aint ui, uiSize;
151  my_line* spMyLine;
152  const achar* acpBeg, *acpEnd;
153  const char* cpInput, *cpInputBig, *cpInputLittle;
154  char* cpOutName = "cherokee.html";
155  char* cpInBig = "cherokee.utf32be";
156  char* cpInLittle = "cherokee.utf32le";
157  const char* cpOutput;
158  char caBufOut[PATH_MAX], caBufIn[PATH_MAX];
159  parser_config sConfig;
160  parser_state sState;
161  exception e;
162  XCTOR(e);
163  if(e.try){
164  // try block
165  vpApi = vpApiCtor(&e);
166  vpMem = vpMemCtor(&e);
167  vpVec = vpVecCtor(vpMem, sizeof(my_line), 64);
168 
169  // validate the alphabet character width
170  if(sizeof(achar) != 4){
171  XTHROW(&e, "sizeof(achar) must be == 4");
172  }
173 
174  // get and display the input string
175  if(bIsBigEndian()){
176  cpInput = cpMakeFileName(caBufIn, SOURCE_DIR, "/../input/", cpInBig);
177  }else{
178  cpInput = cpMakeFileName(caBufIn, SOURCE_DIR, "/../input/", cpInLittle);
179  }
180  cpOutput = cpMakeFileName(caBufOut, SOURCE_DIR, "/../output/", cpOutName);
181 
182  // !!!! DEBUG
183  printf(" input file name: %s\n", cpInput);
184  printf("output file name: %s\n", cpOutput);
185  // !!!! DEBUG
186 
187  uiSize = uiBufSize;
188  vUtilFileRead(vpMem, cpInput, ucaBuf, &uiSize);
189  if(uiSize > uiBufSize){
190  XTHROW(&e, "buffer size too small for input file");
191  }
192 
193  // concatenate the grammar from three sources
194  vApiString(vpApi, cpCherokee, APG_FALSE, APG_TRUE);
195  vpParser = vpApiOutputParser(vpApi);
196 
197  // validate the input
198  memset(&sConfig, 0, sizeof(sConfig));
199  sConfig.acpInput = (achar*)ucaBuf;
200  sConfig.uiInputLength = (uiSize/4);
201  sConfig.uiStartRule = 0;
202  sConfig.vpUserData = vpVec;
203  vParserSetRuleCallback(vpParser, uiParserRuleLookup(vpParser, "line-text"), vLine);
204  vParserParse(vpParser, &sConfig, &sState);
205 
206  // display the state
207  printf("\nParser State\n");
208  vUtilPrintParserState(&sState);
209  printf("\nlines parsed: %"PRIuMAX"\n", (luint)uiVecLen(vpVec));
210 
211 
212  // generate the HTML file
213  spOut = fopen(cpOutput, "wb");
214  if(!spOut){
215  XTHROW(&e, "can't open output file for HTML");
216  }
217  fprintf(spOut, "<!DOCTYPE html>\n");
218  fprintf(spOut, "<html lang=\"en\">\n");
219  fprintf(spOut, " <head>\n");
220  fprintf(spOut, " <meta charset=\"utf-8\">\n");
221  fprintf(spOut, " <title>Cherokee Text</title>\n");
222  fprintf(spOut, " </head>\n");
223  fprintf(spOut, " <body>\n");
224  fprintf(spOut, " <h1>Cherokee Sample</h1>\n");
225  fprintf(spOut, " <p>Wikipedia <a href=\"https://en.wikipedia.org/wiki/Cherokee_language#Samples\">source</a>. </p>\n");
226  fprintf(spOut, " <p>\n");
227  for(ui = 0; ui < uiVecLen(vpVec); ui++){
228  spMyLine = (my_line*)vpVecAt(vpVec, ui);
229  acpBeg = sConfig.acpInput + spMyLine->uiOffset;
230  acpEnd = acpBeg + spMyLine->uiLength;
231  for(; acpBeg < acpEnd; acpBeg++){
232  fprintf(spOut, "&#%"PRIuMAX";", (luint)*acpBeg);
233  }
234  fprintf(spOut, " <br>\n");
235  }
236  fprintf(spOut, " </p>\n");
237  fprintf(spOut, " </body>\n");
238  fprintf(spOut, "</html>\n");
239 
240  printf("\nOpen file %s in browser to view parsed lines.\n", cpOutput);
241 
242 
243  }else{
244  // catch block - display the exception location and message
246  iReturn = EXIT_FAILURE;
247  }
248 
249  // clean up resources
250  if(spOut){
251  fclose(spOut);
252  }
253  vParserDtor(vpParser);
254  vApiDtor(vpApi);
255  vMemDtor(vpMem);
256  return iReturn;
257 }
258 
266 int main(int argc, char **argv) {
267  long int iCase = 0;
268  if(argc > 1){
269  iCase = atol(argv[1]);
270  }
271  if((iCase > 0) && (iCase <= s_iCaseCount)){
272  printf("%s\n", s_cppCases[iCase -1]);
273  }
274  switch(iCase){
275  case 1:
276  return iApp();
277  case 2:
278  return iLines();
279  default:
280  return iHelp();
281  }
282 }
283 
my_line::uiOffset
aint uiOffset
Definition: main.c:125
XCTOR
#define XCTOR(e)
This macro will initialize an exception structure and prepare entry to the "try" block.
Definition: exception.h:77
vUtilFileRead
void vUtilFileRead(void *vpMem, const char *cpFileName, uint8_t *ucpData, aint *uipLen)
Read a file into the caller's data area.
Definition: utilities.c:252
vMemDtor
void vMemDtor(void *vpCtx)
Destroys a Memory component. Frees all memory allocated.
Definition: memory.c:141
exception::try
abool try
True for the try block, false for the catch block.
Definition: exception.h:49
callback_data::uiParserOffset
aint uiParserOffset
[read only] Offset from acpString to the first character to match
Definition: parser.h:160
parser_config::acpInput
const achar * acpInput
Pointer to the input string.
Definition: parser.h:199
vpApiCtor
void * vpApiCtor(exception *spEx)
Construct an API component context (object).
Definition: api.c:55
callback_data::uiParserState
aint uiParserState
[read only] ID_ACTIVE if the parser is going down the tree. ID_MATCH or ID_NOMATCH if coming up the t...
Definition: parser.h:158
uiParserRuleLookup
aint uiParserRuleLookup(void *vpCtx, const char *cpRuleName)
Find the rule index corresponding to a rule name.
Definition: parser.c:440
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
vApiDtor
void vApiDtor(void *vpCtx)
The API component destructor.
Definition: api.c:84
vParserSetRuleCallback
void vParserSetRuleCallback(void *vpCtx, aint uiRuleId, parser_callback pfnCallback)
Set a call back function for a specific rule.
Definition: parser.c:386
vpVecAt
void * vpVecAt(void *vpCtx, aint uiIndex)
Get a the indexed vector element. The vector is not altered.
Definition: vector.c:362
XTHROW
#define XTHROW(ctx, msg)
Exception throw macro.
Definition: exception.h:67
aint
uint_fast32_t aint
The APG parser's unsigned integer type.
Definition: apg.h:79
parser_config::uiInputLength
aint uiInputLength
Number of input string alphabet characters.
Definition: parser.h:200
callback_data::uiParserPhraseLength
aint uiParserPhraseLength
[read only] The parser's matched phrase length if uiParserState is ID_MATCH or ID_NOMATCH....
Definition: parser.h:161
parser_config
Defines the input string and other configuration parameters for the parser,.
Definition: parser.h:198
main
int main(int argc, char **argv)
The executable from this main function is the ABNF Parser Generator application, APG.
Definition: main.c:61
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
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
ID_MATCH
#define ID_MATCH
indicates a matched phrase parser state on return from parse tree below this node
Definition: parser.h:73
luint
uintmax_t luint
luint is used to cast integers suitable for the %"PRIuMAX" printf format.
Definition: apg.h:133
vpApiOutputParser
void * vpApiOutputParser(void *vpCtx)
Generate a parser object directly from the specified SABNF grammar.
Definition: output.c:217
callback_data
The data struct passed to each callback function.
Definition: parser.h:134
vpMemCtor
void * vpMemCtor(exception *spException)
Construct a memory component.
Definition: memory.c:121
bIsBigEndian
abool bIsBigEndian(void)
Determine if the current machine uses big endian word storage.
Definition: tools.c:96
callback_data::vpUserData
void * vpUserData
[input/output] User-defined data passed to to the parser in parser_config.
Definition: parser.h:136
APG_TRUE
#define APG_TRUE
Definition: apg.h:291
vParserDtor
void vParserDtor(void *vpCtx)
Clears the parser component's context and frees all heap memory associated with this parser.
Definition: parser.c:245
vUtilApgInfo
void vUtilApgInfo(void)
Display the current state of apg.h.
Definition: utilities.c:60
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
my_line
Definition: main.c:124
vApiString
void vApiString(void *vpCtx, const char *cpString, abool bStrict, abool bPppt)
Quicky way to generate a parser from a grammar string.
Definition: api.c:544
vUtilPrintException
void vUtilPrintException(exception *spEx)
Prints exception information from an exception structure.
Definition: utilities.c:415
vpVecPush
void * vpVecPush(void *vpCtx, void *vpElement)
Adds one element to the end of the array.
Definition: vector.c:193
vUtilCurrentWorkingDirectory
void vUtilCurrentWorkingDirectory(void)
Display the current working directory.
Definition: utilities.c:191
my_line::uiLength
aint uiLength
Definition: main.c:126
vUtilPrintParserState
void vUtilPrintParserState(parser_state *spState)
Display the parser state in human-readable format to stdout.
Definition: utilities.c:727
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.