From 09b3696de9bde237f0dc7d912902cb8c376ed2a9 Mon Sep 17 00:00:00 2001 From: Kyle Gunger Date: Mon, 29 Jul 2024 01:14:02 -0400 Subject: Refactor ast code --- tnslc/parse/ast.tnsl | 435 ++++++++++----------------------------------------- 1 file changed, 84 insertions(+), 351 deletions(-) diff --git a/tnslc/parse/ast.tnsl b/tnslc/parse/ast.tnsl index 7ad9390..a01a185 100644 --- a/tnslc/parse/ast.tnsl +++ b/tnslc/parse/ast.tnsl @@ -43,25 +43,6 @@ struct Node { ;/ ;/ -/; _ast_import(~utils.File fin, ~Node mod, ~Token first) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - - ~uint8 path = utils.unquote_str(tmp.data) - utils.File _import = fin`.relative(path) - _delete(path) - path = _import.path.to_cstr('/') - - _printf("Importing ./\0") - _printf(path) - _printf("\n\0") - _delete(path) - - _ast_file(~_import, mod) - _import.end() -;/ - /; _get_closing_delim(uint8 ch) [uint8] /; if (ch == '/' || ch == ';') return ';' @@ -75,388 +56,135 @@ struct Node { return 0 ;/ -/; _ast_type (~utils.File fin, ~Node mod, ~Token first) - Node out - out.init(NTYPE_TYPE, utils.strcpy("\0")) - - # Handle pointer and array types - /; loop (first`.eq("~\0") == true || first`.eq("{\0") == true) - Node pre - pre.init(NTYPE_PRE_OP, first`.data) - - /; if (first`.eq("{\0") == true) - first` = produce_next_token(fin, first`) - /; if (first`._type == TTYPE_LITRL && is_numeric(first`.data`)) - Node i - i.init(NTYPE_LITERAL, first`.data) - pre.sub.push(~i) - ;; else if (first`.eq("}\0") == false) - _printf("Expected integer for array type or '}':") - _printf(" \0") - print_token(first`) - _printf("\n\0") - ;; else - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ - ;/ - - out.sub.push(~pre) - first` = produce_next_token(fin, first`) +/; _advance_check(~utils.File fin, ~Token tok, ~uint8 eq) [bool] + /; if (tok`.eq(eq) == true) + Token tmp = produce_next_token(fin, tok`) + tok`.end() + tok` = tmp + return true ;/ + return false +;/ - /; if (first`._type !== TTYPE_KEYTP && first`._type !== TTYPE_USRWD) - _printf("Expected key type or user type:") - _printf(" \0") - print_token(first`) - _printf("\n\0") - ;/ - - # Are we a void type? (Matters for getting params or ) - bool vd = false - /; if (first`.eq("void\0") == true) - vd = true - ;/ +/; _ast_print_err (~Token tok, ~uint8 msg) + _printf(msg) + _printf(":\n\0") + _printf(" \0") + print_token(tok`) + _printf("\n\0") +;/ - # Fully qualified type name - /; if (first`._type == TTYPE_USRWD) - /; loop (bool run = true; run == true) - Node usr - usr.init(NTYPE_ID, first`.data) - first` = produce_next_token(fin, first`) - out.sub.push(~usr) - - /; if (first`.eq(".\0") == true) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - /; if (first`._type !== TTYPE_USRWD) - run = false - _printf("Expected completion of user type:") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - ;/ - ;; else - run = false - ;/ - ;/ - ;; else - Node tp - tp.init(NTYPE_ID, first`.data) - out.sub.push(~tp) +# Top level directives - first` = produce_next_token(fin, first`) - ;/ +/; _ast_import (~utils.File fin, ~Node mod, ~Token first) - # Generics or void call type - /; if (first`._type == TTYPE_DELIM && first`.data` == '(') - _ast_type_list(fin, ~out, first) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ + /; if (first`._type !== TTYPE_LITRL || first`.data` !== '"') + _ast_print_err(first, "Expected string or import literal after 'import'\0") - # Void return type - /; if (vd && first`._type == TTYPE_DELIM && first`.data` == '[') - _ast_type_list(fin, ~out, first) Token tmp = produce_next_token(fin, first`) first`.end() first` = tmp + + return ;/ - # Reference - /; if (first`.eq("`\0") == true) - Node post - post.init(NTYPE_PRE_OP, first`.data) - - out.sub.push(~post) - first` = produce_next_token(fin, first`) - ;/ - - mod`.sub.push(~out) -;/ - -/; _ast_decl (~utils.File fin, ~Node mod, ~Token first) -;/ - -/; _ast_decl_list (~utils.File fin, ~Node mod, ~Token first) - -;/ + ~uint8 rel = utils.unquote_str(first`.data) + utils.File imp = fin`.relative(rel) + _delete(rel) -/; _ast_expr (~utils.File fin, ~Node mod, ~Token first) - -;/ + rel = imp.path.to_cstr('/') + _printf("Importing \0") + _printf(rel) + _printf("\n\0") + _delete(rel) -/; _ast_maybe_expr_decl (~utils.File fin, ~Node mod, ~Token first) - # Handle the case where it's ambiguous whether we have a type definition or an expression + _ast_file(~imp, mod) + imp.end() + Token tmp = produce_next_token(fin, first`) + first`.end() + first` = tmp ;/ -/; _ast_expr_list(~utils.File fin, ~Node mod, ~Token first) - uint8 closing = _get_closing_delim(first`.data`) - - Node expr_list - expr_list.init(NTYPE_ELIST, first`.data) - - first` = produce_next_token(fin, first`) - bool run = true - - /; if (first`._type == TTYPE_DELIM && first`.data` == closing) - run = false - ;; else - _ast_maybe_expr_decl(fin, ~expr_list, first) - ;/ +/; _ast_asm (~utils.File fin, ~Node mod, ~Token first) - /; loop (run == true && first`._type !== TTYPE_ERR) - /; if (first`._type == TTYPE_DELIM && first`.data` == closing) - run = false - ;; else if (first`._type == TTYPE_SEP && first`.eq(";\0")) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp + /; if (first`._type !== TTYPE_LITRL || first`.data` !== '"') + _ast_print_err(first, "Expected string literal after 'ast'\0") - _ast_maybe_expr_decl(fin, ~expr_list, first) - ;; else - _printf("Unexpected token when parsing a list of types:\n\0") - _printf(" \0") - print_token(first`) - _printf("\n\0") - - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ + Token tmp = produce_next_token(fin, first`) + first`.end() + first` = tmp + + return ;/ - - mod`.sub.push(~expr_list) -;/ - -/; _ast_type_list (~utils.File fin, ~Node mod, ~Token first) - uint8 closing = _get_closing_delim(first`.data`) - - Node type_list - type_list.init(NTYPE_TLIST, first`.data) + + Node an + an.init(NTYPE_ASM, utils.unquote_str(first`.data)) + mod`.sub.push(~an) Token tmp = produce_next_token(fin, first`) + first`.end() first` = tmp - bool run = true - /; if (first`._type == TTYPE_DELIM && first`.data` == closing) - run = false - ;; else if (first`._type == TTYPE_KEYTP || first`._type == TTYPE_USRWD || first`.eq("~\0") == true) - _ast_type(fin, ~type_list, first) - ;; else - _printf("Expected type or closing of type list:\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - ;/ - - /; loop (bool run = true; run == true && first`._type !== TTYPE_ERR) - /; if (first`._type == TTYPE_DELIM && first`.data` == closing) - run = false - ;; else if (first`._type == TTYPE_SEP && first`.eq(",\0")) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - - /; if (first`._type == TTYPE_KEYTP || first`._type == TTYPE_USRWD || first`.eq("~\0") == true) - _ast_type(fin, ~type_list, first) - ;/ - ;; else - _printf("Expected comma ',' and then type:\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ - ;/ - - mod`.sub.push(~type_list) ;/ /; _ast_struct (~utils.File fin, ~Node mod, ~Token first) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp + + # Identifier check + /; if (first`._type !== TTYPE_USRWD) + _ast_print_err(first, "Expected new identifier for typedef after 'struct'\0") - /; if (tmp._type !== TTYPE_USRWD) - _printf("Unexpected token after struct keyword:\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") + Token tmp = produce_next_token(fin, first`) + first`.end() + first` = tmp + return ;/ - Node out - out.init(NTYPE_STRUCT, tmp.data) + # Root struct node + Node sct + sct.init(NTYPE_STRUCT, first`.data) + first` = produce_next_token(fin, first`) - first` = produce_next_token(fin, tmp) - _ast_decl_list(fin, out, first) + # Check for def list + /; if (first`._type !== TTYPE_DELIM || first`.data` !== '{') + _ast_print_err(first, "Expected new identifier for typedef after 'struct'\0") + mod`.sub.push(~sct) - mod`.sub.push(~out) -;/ - -/; _ast_method (~utils.File fin, ~Node mod, ~Token first) - Token tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - - /; if (tmp._type !== TTYPE_USRWD) - _printf("Expected a user-defined type after 'method':\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") + Token tmp = produce_next_token(fin, first`) + first`.end() + first` = tmp + return ;/ - Node out - out.init(NTYPE_METHOD, tmp.data) - - tmp = produce_next_token(fin, tmp) - first` = tmp - /; loop (first`._type !== TTYPE_ERR && first`.eq(";;\0") == false && first`.eq(";/\0") == false) - /; if (first`.eq("/;\0") == true) - tmp = produce_next_token(fin, tmp) - first`.end() - first` = tmp - _ast_function(fin, ~out, first) - - /; loop (first`.eq(";;") == true) - tmp = produce_next_token(fin, tmp) - first`.end() - first` = tmp - _ast_function(fin, ~out, first) - ;/ - ;; else - _printf("Expected only function blocks in method block:\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - - tmp = produce_next_token(fin, tmp) - first`.end() - first` = tmp - ;/ - ;/ - - mod`.sub.push(~out) -;/ - -/; _ast_asm(~utils.File fin, ~Node mod, ~Token first) + # Parse deflist and push root node into module + _ast_list_def(fin, mod, first) + mod`.sub.push(~sct) + Token tmp = produce_next_token(fin, first`) first`.end() first` = tmp - - /; if (tmp._type !== TTYPE_LITRL || tmp.data{0} !== '"') - _printf("Expected string token after 'asm' keyword:\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - return - ;/ - - Node out - out.init(NTYPE_ASM, utils.unquote_str(tmp.data)) - - mod`.sub.push(~out) - first` = produce_next_token(fin, tmp) - tmp.end() ;/ -/; _ast_function (~utils.File fin, ~Node mod, ~Token first) +/; _ast_decl (~utils.File fin, ~Node mod, ~Token first) Token tmp = produce_next_token(fin, first`) first`.end() first` = tmp - /; if (tmp._type !== TTYPE_USRWD) - _printf("Expected function name (Compiler bug, not user program issue):\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - return - ;/ - - uint line = first`.line - /; loop (line == first`.line) - ;/ ;/ -/; _ast_block (~utils.File fin, ~Node mod, ~Token first) +/; _ast_top_block(~utils.File fin, ~Node mod, ~Token first) Token tmp = produce_next_token(fin, first`) first`.end() first` = tmp - /; if (tmp._type == TTYPE_USRWD) - _ast_function(fin, mod, first) - ;; else if (tmp.eq("method\0") == true) - _ast_method(fin, mod, first) - ;; else if (tmp.eq("module\0") == true || tmp.eq("export\0") == true) - _ast_module(fin, mod, first) - ;; else - _printf("Expected function definition, 'method', or 'module' after block opening (root of file or module):\n\0") - _printf(" \0") - print_token(tmp) - _printf("\n\0") - ;/ - - /; if (first`.eq(";;\0") == true) - _ast_block(fin, mod, first) - ;; else - tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ ;/ -/; _ast_module (~utils.File fin, ~Node mod, ~Token first) - Token tmp - uint16 _type = NTYPE_MODULE - /; if (first`.eq("export\0")) - _type = NTYPE_EXPORT - tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ - - tmp = produce_next_token(fin, first`) +/; _ast_module(~utils.File fin, ~Node mod, ~Token first) + Token tmp = produce_next_token(fin, first`) first`.end() first` = tmp - /; if (tmp._type !== TTYPE_USRWD) - _printf("Expected module name: \0") - print_token(tmp) - return - ;/ - - Node out - out.init(_type, tmp.data) - - tmp = produce_next_token(fin, first`) - first` = tmp - /; loop(first`._type !== TTYPE_ERR && first`.eq(";;\0") == false && first`.eq(";/\0") == false) - /; if (first`.eq("import\0") == true) - _ast_import(fin, ~out, first) - ;; else if (first`.eq("struct\0") == true) - _ast_struct(fin, ~out, first) - ;; else if (first`.eq("asm\0") == true) - _ast_asm(fin, ~out, first) - ;; else if (first`.eq("/;\0") == true) - _ast_block(fin, ~out, first) - ;; else if (first`._type == TTYPE_KEYTP || first`._type == TTYPE_USRWD || first`.eq("~\0") == true) - _ast_decl(fin, ~out, first) - ;; else - tmp = produce_next_token(fin, first`) - first`.end() - first` = tmp - ;/ - ;/ - - mod`.sub.push(~out) ;/ /; _ast_file (~utils.File fin, ~Node mod) @@ -464,17 +192,22 @@ struct Node { Token first = produce_first_token(fin) /; loop (first._type !== TTYPE_ERR) - /; if (first.eq("import\0") == true) + /; if (_advance_check(fin, ~first, "import\0") == true) _ast_import(fin, mod, ~first) - ;; else if (first.eq("struct\0") == true) + ;; else if (_advance_check(fin, ~first, "struct\0") == true) _ast_struct(fin, mod, ~first) - ;; else if (first.eq("asm\0") == true) + ;; else if (_advance_check(fin, ~first, "asm\0") == true) _ast_asm(fin, mod, ~first) ;; else if (first.eq("/;\0") == true) - _ast_block(fin, mod, ~first) + _ast_top_block(fin, mod, ~first) ;; else if (first._type == TTYPE_KEYTP || first._type == TTYPE_USRWD || first.eq("~\0") == true) _ast_decl(fin, mod, ~first) ;; else + _printf("Expected 'import', 'struct', 'asm', block, or declaration in top level:\n\0") + _printf(" \0") + print_token(first) + _printf("\n\0") + Token tmp = produce_next_token(fin, first) first.end() first = tmp -- cgit v1.2.3