Skip to content

Review: Parsing preprocessor in one pass edge cases. #54

@Ed94

Description

@Ed94

I think I found a way to resolve issues I have with trying to preserve with WYSIWYG AST of any regular C/C++ file, even for edge cases messes.

static AudioData AUDIO = {
#ifndef __cplusplus
	.Buffer.defaultSize = 0,
	.mixedProcessor = NULL
#else
	0,
	NULL
#endif
};

In the above example, a programmer implicitly knows the context of the preprocessor is within the context of the Audio's initialization definition's scope. The traditional parser cannot. This is not good for a WYSIWYG as it makes it harder to parse contextually a file based on relative symbols.

Ideally to parse this definition and change out the context of this if def you would want to find the AUDIO static variable definition, then go to its assignment expression node and find within the block node the preprocessor conditional.
Technically speaking, this is possible to do by adding the ability to support conditional preprocessor blocks as valid nodes within assignment expressions. But not all preprocessor definitions are organized in such a way.

The other way around is also valid:

#if defined(_WIN32)
    typedef void *PVOID;
    typedef PVOID HANDLE;
    typedef HANDLE HWND;
    #define GLFW_EXPOSE_NATIVE_WIN32
    #define GLFW_NATIVE_INCLUDE_NONE // To avoid some symbols re-definition in windows.h
    #include "GLFW/glfw3native.h"

    #if defined(RL_SUPPORT_WINMM_HIGHRES_TIMER) && !defined(RL_SUPPORT_BUSY_WAIT_LOOP)
        // NOTE: Those functions require linking with winmm library
    #if __cplusplus
        extern "C" {
    #endif
        unsigned int __stdcall timeBeginPeriod(unsigned int uPeriod);
        unsigned int __stdcall timeEndPeriod(unsigned int uPeriod);
    #if __cplusplus
        }
    #endif
    #endif
#endif

In this case we just have to allow for untyped lexical nodes for unresolved text definitions in preprocessor contextes ( the extern "C" { and } at the closing of the extern for c++. These could be difficult to navigation but not impossible with a proper visual debugger of the ast for metaprograms. This still allows the user to traverse the AST with as much contextual ergonomics possible.

If the preprocessor macro or conditional block intersects the construction of a complete context of a C++ definition, where to put the preprocessors' node becomes ambiguous:

#define UNFORTUNATE 1

void Something
#if UNFORTUNATE
	(void)
#else
	(int)
#endif
{
}

This one is quite horrible as there is no salvaging the function definition. It will just break. The only thing that could be done is moving void Something to an untyped lexed node. The preprocessor conditionals would be in a global body node and the block scope will not have a context assignable (and thus not know what context to interpret it with). In that worst case you would have to use a parsing function that could deal with the 'laundry mat' of possible context that could be shoved in a executable context ( parse_any_execution_block).

So long as each parsing function can handle its failure correctly and 'recover' to a valid context for continuing to parse valid operations is setup iny any body/scope function a condition to handle parse failures with : on failure -> call parser:: recover_from_unresolved_state`. Which the function can provide a way for the parser to limit the bad definition to the least amount of tokens / scope possible. And continue from a valid state from then on.

int main()
{
	#define CURSED_EXP + 5 +
	int why = 2 CURSED_EXP some_var_you_might_want_to_refactor;
}

If the macro is within the statements bound we can just resolve the assignment's expression to be an untyped lexed text (so sucks, but not horrible). In a context system could still identifysome_var_you_might_want_to_refactor.

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or requesttesting

    Projects

    Status

    Todo

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions