diff --git a/docs/metadesk_reference.md b/docs/metadesk_reference.md index c1014bb..b3ea46f 100644 --- a/docs/metadesk_reference.md +++ b/docs/metadesk_reference.md @@ -1136,6 +1136,13 @@ main: tag: *MD_Node, }; +@send(Nodes) +@func MD_PushReference: { + list: *MD_Node, + target: *MD_Node, + return: *MD_Node, +}; + //////////////////////////////// //~ Introspection Helpers diff --git a/samples/node_errors/node_errors.c b/samples/node_errors/node_errors.c index ec01de6..9e707f7 100644 --- a/samples/node_errors/node_errors.c +++ b/samples/node_errors/node_errors.c @@ -5,6 +5,8 @@ int main(int argument_count, char **arguments) { + // TODO(allen): use list system + // NOTE(rjf): Parse all the files passed in via command line. MD_Node *first = MD_NilNode(); MD_Node *last = MD_NilNode(); diff --git a/samples/old_style_custom_layer.c b/samples/old_style_custom_layer.c index 9dcee0b..26bfd8a 100644 --- a/samples/old_style_custom_layer.c +++ b/samples/old_style_custom_layer.c @@ -23,6 +23,8 @@ CleanUp(void) int main(int argument_count, char **arguments) { + // TODO(allen): use list system + // NOTE(rjf): Parse all the files passed in via command line. MD_Node *first = MD_NilNode(); MD_Node *last = MD_NilNode(); diff --git a/samples/output_parse/output_parse.c b/samples/output_parse/output_parse.c index 3138f18..1e294a6 100644 --- a/samples/output_parse/output_parse.c +++ b/samples/output_parse/output_parse.c @@ -58,6 +58,8 @@ static void PrintNode(MD_Node* node, FILE* file, int indent_count) { int main(int argument_count, char **arguments) { + // TODO(allen): use list system + // NOTE(pmh): Parse all the files passed in via command line. MD_Node *first = MD_NilNode(); MD_Node *last = MD_NilNode(); diff --git a/samples/static_site_generator/static_site_generator.c b/samples/static_site_generator/static_site_generator.c index 42d3455..bf14ce2 100644 --- a/samples/static_site_generator/static_site_generator.c +++ b/samples/static_site_generator/static_site_generator.c @@ -55,6 +55,8 @@ int main(int argument_count, char **arguments) site_info = ParseSiteInfo(site_info_file); } + // TODO(allen): use list system + //~ NOTE(rjf): Parse pages. MD_Node *first_root = MD_NilNode(); MD_Node *last_root = MD_NilNode(); diff --git a/samples/toy_language/toy_language.c b/samples/toy_language/toy_language.c index 38ae3fb..379cdb5 100644 --- a/samples/toy_language/toy_language.c +++ b/samples/toy_language/toy_language.c @@ -179,6 +179,8 @@ int main(int argument_count, char **arguments) //- rjf: parse command line MD_CommandLine cmdln = MD_CommandLineFromOptions(MD_StringListFromArgCV(argument_count, arguments)); + // TODO(allen): use list system + //- rjf: parse all input files MD_Node *first_file = MD_NilNode(); MD_Node *last_file = MD_NilNode(); diff --git a/source/md.h b/source/md.h index 85e2384..0d55b89 100644 --- a/source/md.h +++ b/source/md.h @@ -334,6 +334,8 @@ enum MD_NodeFlag_CharLiteral = (1<<13), }; +#define MD_NodeFlag_AfterFromBefore(f) ((f) << 2) + typedef struct MD_Node MD_Node; struct MD_Node { @@ -708,12 +710,11 @@ MD_FUNCTION MD_Node *MD_NilNode(void); MD_FUNCTION MD_Node *MD_MakeNode(MD_NodeKind kind, MD_String8 string, MD_String8 whole_string, MD_String8 filename, MD_u8 *file_contents, MD_u8 *at); -MD_FUNCTION MD_Node *MD_MakeNodeFromString(MD_NodeKind kind, MD_String8 filename, MD_u8 *file, MD_u8 *at, MD_String8 string); -MD_FUNCTION MD_Node *MD_MakeNodeReference(MD_Node *target); MD_FUNCTION void MD_PushSibling(MD_Node **first, MD_Node **last, MD_Node *new_sibling); MD_FUNCTION void MD_PushChild(MD_Node *parent, MD_Node *new_child); MD_FUNCTION void MD_PushTag(MD_Node *node, MD_Node *tag); MD_FUNCTION void MD_InsertToNamespace(MD_Node *ns, MD_Node *node); +MD_FUNCTION MD_Node *MD_PushReference(MD_Node *list, MD_Node *target); //~ Introspection Helpers MD_FUNCTION MD_Node * MD_NodeFromString(MD_Node *first, MD_Node *last, MD_String8 string); diff --git a/source/md_impl.c b/source/md_impl.c index 5a0e0d5..af84d93 100644 --- a/source/md_impl.c +++ b/source/md_impl.c @@ -1667,37 +1667,56 @@ MD_Parse_RequireKind(MD_ParseCtx *ctx, MD_TokenKind kind, MD_Token *out_token) MD_FUNCTION_IMPL void MD_Parse_Set(MD_ParseCtx *ctx, MD_Node *parent, MD_ParseSetFlags flags) { - MD_b32 brace = 0; - MD_b32 paren = 0; - MD_b32 bracket = 0; - MD_b32 terminate_with_separator = (!!(flags & MD_ParseSetFlag_Implicit)); - MD_Token initial_token = MD_Parse_PeekSkipSome(ctx, MD_TokenGroup_Comment|MD_TokenGroup_Whitespace); + // check for set opener + MD_u8 set_opener = 0; if((flags & MD_ParseSetFlag_Brace) && MD_Parse_Require(ctx, MD_S8Lit("{"), MD_TokenKind_Symbol)) { - parent->flags |= MD_NodeFlag_BraceLeft; - brace = 1; - terminate_with_separator = 0; + set_opener = '{'; } else if((flags & MD_ParseSetFlag_Paren) && MD_Parse_Require(ctx, MD_S8Lit("("), MD_TokenKind_Symbol)) { - parent->flags |= MD_NodeFlag_ParenLeft; - paren = 1; - terminate_with_separator = 0; + set_opener = '('; } else if((flags & MD_ParseSetFlag_Bracket) && MD_Parse_Require(ctx, MD_S8Lit("["), MD_TokenKind_Symbol)) { - parent->flags |= MD_NodeFlag_BracketLeft; - bracket = 1; - terminate_with_separator = 0; + set_opener = '['; + } + + // something else + MD_b32 brace = 0; + MD_b32 paren = 0; + MD_b32 bracket = 0; + MD_b32 terminate_with_separator = 0; + switch (set_opener){ + default: + { + terminate_with_separator = (!!(flags & MD_ParseSetFlag_Implicit)); + }break; + + case '{': + { + parent->flags |= MD_NodeFlag_BraceLeft; + brace = 1; + }break; + case '(': + { + parent->flags |= MD_NodeFlag_ParenLeft; + paren = 1; + }break; + case '[': + { + parent->flags |= MD_NodeFlag_BracketLeft; + bracket = 1; + }break; } // NOTE(rjf): Parse children. - if(brace || paren || bracket || terminate_with_separator) + if((set_opener != 0) || terminate_with_separator) { MD_u8 *at_before_children = ctx->at; MD_NodeFlags next_child_flags = 0; @@ -1738,30 +1757,35 @@ MD_Parse_Set(MD_ParseCtx *ctx, MD_Node *parent, MD_ParseSetFlags flags) } } + // NOTE(allen): parse the next node MD_ParseResult parse = MD_ParseOneNodeFromCtx(ctx); MD_Node *child = parse.node; - child->flags |= next_child_flags; - next_child_flags = 0; if(MD_NodeIsNil(child)) { - if(brace || paren || bracket) + if(set_opener != 0) { - char delimiter_char = 0; - if(brace) delimiter_char = '{'; - else if(paren) delimiter_char = '('; - else if(bracket) delimiter_char = '['; MD_PushTokenErrorF(ctx, initial_token, MD_MessageKind_CatastrophicError, - "Unbalanced \"%c\"", delimiter_char); + "Unbalanced \"%c\"", set_opener); } goto end_parse; } - else - { - MD_PushSibling(&parent->first_child, &parent->last_child, child); - child->parent = parent; - } + + // connect node into graph + MD_PushChild(parent, child); + + // fill flags from surrounding context + child->flags |= next_child_flags; + + // TODO(allen): I find it kind of concerning that ParseWholeString and + // ParseOneNode are both doing this. I did some refactors in the + // ParseWholeString to break it down into flatter blocks, not realizing + // very similar logic happens here too. + // I also see that these really are slightly different, but it seems + // like it should be possible to express the whole-string case as a + // special case of this and avoid the duplication. // NOTE(rjf): Separators. + next_child_flags = 0; { MD_b32 result = 0; if(terminate_with_separator) @@ -2108,29 +2132,31 @@ MD_ParseWholeString(MD_String8 filename, MD_String8 contents) // NOTE(allen): parse the next node MD_ParseResult parse = MD_ParseOneNodeFromCtx(&ctx); MD_Node *child = parse.node; - child->flags |= next_child_flags; - next_child_flags = 0; if(MD_NodeIsNil(child)) { break; } - else - { - MD_PushSibling(&root->first_child, &root->last_child, child); - child->parent = root; - MD_InsertToNamespace(selected_namespace, child); - } + // connect node into graph + MD_PushChild(root, child); + MD_InsertToNamespace(selected_namespace, child); + + // check trailing symbol + MD_u32 symbol_flags = 0; if(MD_Parse_Require(&ctx, MD_S8Lit(","), MD_TokenKind_Symbol)) { - child->flags |= MD_NodeFlag_BeforeComma; - next_child_flags |= MD_NodeFlag_AfterComma; + symbol_flags = MD_NodeFlag_BeforeComma; } else if(MD_Parse_Require(&ctx, MD_S8Lit(";"), MD_TokenKind_Symbol)) { - child->flags |= MD_NodeFlag_BeforeSemicolon; - next_child_flags |= MD_NodeFlag_AfterSemicolon; + symbol_flags = MD_NodeFlag_BeforeSemicolon; } + + // fill flags from surrounding context + child->flags |= next_child_flags|symbol_flags; + + // setup next_child_flags + next_child_flags = MD_NodeFlag_AfterFromBefore(symbol_flags); } result.namespaces = namespaces; result.bytes_parsed = (MD_u64)(ctx.at - contents.str); @@ -2215,15 +2241,6 @@ MD_MakeNode(MD_NodeKind kind, MD_String8 string, return node; } -MD_FUNCTION_IMPL MD_Node * -MD_MakeNodeReference(MD_Node *target) -{ - MD_String8 string = MD_S8Lit("`reference node`"); - MD_Node *n = MD_MakeNode(MD_NodeKind_Reference, string, string, string, 0, 0); - n->ref_target = target; - return n; -} - MD_FUNCTION_IMPL void MD_PushSibling(MD_Node **firstp, MD_Node **lastp, MD_Node *node) { @@ -2272,6 +2289,16 @@ MD_InsertToNamespace(MD_Node *ns, MD_Node *node) MD_PushChild(ns, ref); } +MD_FUNCTION_IMPL MD_Node* +MD_PushReference(MD_Node *list, MD_Node *target) +{ + MD_String8 string = MD_S8Lit("`reference node`"); + MD_Node *n = MD_MakeNode(MD_NodeKind_Reference, string, string, string, 0, 0); + n->ref_target = target; + MD_PushChild(list, n); + return(n); +} + //~ Introspection Helpers MD_FUNCTION_IMPL MD_Node *