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