Implementation
Once you generate your parser you can use it as a part of you project. It can be used with any C/C++ compiler that supports C99 syntax. The code is compatible with both Linux and Windows.
You can generate the parser as single file or multiple files. By default, the parser includes a main function (for demo purposes), machine code (runs the parser) and program code (defines the parser). You can exclude the main and the machine code from the generation. Declarations are included inside the source file by default but you can generate a separate header file if you want.
You can generate multiple parsers (as programs) and use a single machine to run all of them.
The generated program is stored as a struct Program
. It is normally in the name of the parser such as
struct Program ParserProgram;
. You can use GetTokenizeResult
to generate the tokens and
GetAnalyzeResult
to generate the syntax. You can quickly print the result to your screen using
PrintTokenizeResult
and ExportAnalyzeResult
respectfully. These print function will also print any
encountered error.
When it comes to extracting the parsed data to use in your program/library you can use the raw data
from struct TokenizeResult
and struct AnalyzeResult
. These structs do not allocate strings but refer
to the text (passed to the parser to be parsed) buffer using indices. However, an easier way to
extract the parsed data is using the functions ExportTokenizeResult
and ExportAnalyzeResult
. These
function converts the data in struct TokenizeResult
and struct AnalyzeResult
into string pairs, stored
in the types struct TokenPairList
and struct NodePairList
respectfully. The strings in these structs
are allocated and should be released after no longer needed with the functions DestroyTokenPairList
and
DestroyNodePairList
respectfully.
You can see the generated main function as a example on how to use the parser in your program.
Here is a sample code
#ifndef ALGODAL_GENERATED_PARSER_MAIN_C
#define ALGODAL_GENERATED_PARSER_MAIN_C
#include <time.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ALGODAL_GENERATED_PARSER_MAIN_PRINT_USING_EXPORT
static void printNodePair(struct AlgodalParser_NodePair nodePair, uint32_t indent)
{
for(uint32_t i = 0; i < indent; i++) cwpc_printf("\t");
cwpc_printf("%u.%u %s : %s\n",
nodePair.lineNumber,
nodePair.columnNumber,
nodePair.key,
nodePair.value ? nodePair.value : ""
);
for(uint32_t i = 0; i < nodePair.children.size; i++)
{
printNodePair(nodePair.children.addr[i], indent + 1);
}
}
#endif
static int ExitParsing(int retv[], int retc)
{
for(int i = 0; i < retc; i++)
{
if(retv[i] != 0) return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
int main(int argc, char *argv[])
{
if(argc > 1)
{
FILE* fp = fopen(argv[1], "rb");
if(fp)
{
if(fp == 0) return EXIT_FAILURE;
fseek(fp, 0, SEEK_END);
size_t length = ftell(fp);
fseek(fp, 0, SEEK_SET);
char *text = malloc(length + 1);
text[length] = 0;
fread(text, 1, length, fp);
fclose(fp);
#if defined(ALGODAL_GENERATED_PARSER_UTILITY_H) || defined(ALGODAL_GENERATED_PARSER_UTILITY_C)
#ifndef __linux__
char*temp = text;
text = AlgodalParserUtility_CreateFilteredOutString(temp, length, (const char*[]){"\r"}, 1, &length);
free(temp);
#endif
#endif
clock_t begin = clock(), end;
double duration;
struct AlgodalParser_TokenizeResult TokenizeResult = AlgodalParser_GetTokenizeResult(*ProgramPtr, text, length, 0);
struct AlgodalParser_AnalyzeResult AnalyzeResult = AlgodalParser_GetAnalyzeResult(*ProgramPtr, text, TokenizeResult.tokens.addr, TokenizeResult.tokens.size, 0);
end = clock();
duration = (double)(end - begin) / CLOCKS_PER_SEC;
#ifndef ALGODAL_GENERATED_PARSER_MAIN_NO_PRINT
struct AlgodalParser_Linenumber *PLn = AlgodalParser_CreateParserLinenumber(text, length);
cwpc_printf("\nTokenization:\n");
#ifndef ALGODAL_GENERATED_PARSER_MAIN_PRINT_USING_EXPORT
AlgodalParser_PrintTokenizeResult(*ProgramPtr, TokenizeResult, text, PLn);
#else
struct AlgodalParser_TokenPairList tokenStringPairs = AlgodalParser_ExportTokenizeResult(TokenizeResult, *ProgramPtr, text, PLn);
for(uint32_t i = 0; i < tokenStringPairs.size; i++)
{
cwpc_printf("%u.%u %s : %s\n",
tokenStringPairs.addr[i].lineNumber,
tokenStringPairs.addr[i].columnNumber,
tokenStringPairs.addr[i].key,
tokenStringPairs.addr[i].value
);
}
#endif
if(TokenizeResult.error.flags == 0)
{
cwpc_printf("\nAnalyzation:\n");
#ifndef ALGODAL_GENERATED_PARSER_MAIN_PRINT_USING_EXPORT
AlgodalParser_PrintAnalyzeResult(*ProgramPtr, AnalyzeResult, TokenizeResult.tokens.addr, text, PLn);
#else
struct AlgodalParser_NodePairList nodeStringPairs = AlgodalParser_ExportAnalyzeResult(TokenizeResult.tokens.addr, AnalyzeResult, *ProgramPtr, text, PLn);
for(uint32_t i = 0; i < nodeStringPairs.size; i++)
{
printNodePair(nodeStringPairs.addr[i], 0);
}
#endif
}
else
{
if((*ProgramPtr).CountOfEntrypoints)
{
cwpc_printf("Tokenization step contains error - Analyzation not done.\n");
}
}
cwpc_printf("completed in %f milliseconds\n", duration * 1000);
AlgodalParser_DestroyParserLinenumber(PLn);
#endif
AlgodalParser_DestroyTokenizeResult(TokenizeResult);
AlgodalParser_DestroyAnalyzeResult(AnalyzeResult);
free(text);
int ret[] = {TokenizeResult.error.flags, AnalyzeResult.error.flags};
return ExitParsing(ret, sizeof(ret)/sizeof(int));
}
cwpc_printf("FAILED TO OPEN FILE %s\n", argv[1]);
}
cwpc_printf("PASS THE NAME OF THE FILE TO PARSE\n");
return EXIT_FAILURE;
}
#ifdef __cplusplus
}
#endif
#endif //ALGODAL_GENERATED_PARSER_MAIN_C