From 680659a3e7c80b796e451cc7721d86d1d48d5a69 Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Fri, 29 Mar 2019 15:15:27 -0400 Subject: [PATCH] started structuring parser to support inheritance and instrumented tracing for debug --- example.src | 6 ++-- source/parser.c | 94 ++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 77 insertions(+), 23 deletions(-) diff --git a/example.src b/example.src index b60c809..ef80023 100644 --- a/example.src +++ b/example.src @@ -47,9 +47,9 @@ fun main(args string[]) int { 123 } # UFCS call (call regular function like a method) - foo.bar() +# foo.bar() # foo.bar.baz() # Struct/Union field access - foo.bar -# foo.bar.baz +# let a int = foo.bar +# let b int = foo.bar.baz } diff --git a/source/parser.c b/source/parser.c index 9192190..96dd223 100644 --- a/source/parser.c +++ b/source/parser.c @@ -16,6 +16,18 @@ static AST* if_expression(Parser* p); static AST* identifier(Parser* p); static AST* expr_list(Parser* p, int firstc, int endc); +#define TRACE +#ifdef TRACE +static int Indent = 0; +#define parse_enter() \ + (printf("%*c-> %s\n", ++Indent * 2, ' ', __func__)) +#define parse_exit() \ + (printf("%*c<- %s\n", --Indent * 2, ' ', __func__)) +#else +#define parse_enter() +#define parse_exit() +#endif + /* Parsing Routines *****************************************************************************/ static Tok* peek(Parser* p) { @@ -68,14 +80,17 @@ static Tok* expect_val(Parser* p, TokType type) { /* Grammar Definition *****************************************************************************/ void toplevel(Parser* p) { + parse_enter(); if (matches(p, T_REQUIRES)) require_list(p); if (matches(p, T_PROVIDES)) provide_list(p); definition_list(p); + parse_exit(); } static void require_list(Parser* p) { + parse_enter(); accept(p, T_REQUIRES); expect(p, '('); while (!matches(p, ')')) { @@ -83,9 +98,11 @@ static void require_list(Parser* p) { pkg_add_require(&(p->pkg), tok->text); } expect(p, ')'); + parse_exit(); } static void provide_list(Parser* p) { + parse_enter(); accept(p, T_PROVIDES); expect(p, '('); while (!matches(p, ')')) { @@ -93,9 +110,11 @@ static void provide_list(Parser* p) { pkg_add_provide(&(p->pkg), tok->text); } expect(p, ')'); + parse_exit(); } static void definition_list(Parser* p) { + parse_enter(); while (!matches(p, T_END_FILE)) { AST* def = NULL; if (matches(p, T_LET) || matches(p, T_VAR)) { @@ -111,9 +130,11 @@ static void definition_list(Parser* p) { puts(""); pkg_add_definition(&(p->pkg), def); } + parse_exit(); } static AST* definition(Parser* p) { + parse_enter(); bool is_const = matches(p, T_LET); if (!accept(p, T_LET) && !accept(p, T_VAR)) error(p, "constant or variable definition expected"); @@ -121,18 +142,22 @@ static AST* definition(Parser* p) { AST* type = type_expression(p); expect(p, '='); AST* val = expression(p); + parse_exit(); return Var(str, val, type, SF_CONSTANT); } static AST* type_definition(Parser* p) { + parse_enter(); expect(p, T_TYPE); char* str = strdup(expect_val(p, T_ID)->text); expect(p, '='); AST* type = type_expression(p); + parse_exit(); return Var(str, NULL, type, SF_TYPEDEF); } static AST* func_definition(Parser* p) { + parse_enter(); expect(p, T_FUN); char* name = strdup(expect_val(p, T_ID)->text); expect(p, '('); @@ -149,45 +174,73 @@ static AST* func_definition(Parser* p) { AST* type = type_expression(p); AST* body = expression_block(p); AST* func = Func(arglist, body, type); + parse_exit(); return Var(name, func, type, SF_CONSTANT); } +static AST* member_access(Parser* p); +static AST* parenthesized(Parser* p); +static AST* literal(Parser* p); + static AST* expression(Parser* p) { + parse_enter(); + AST* exp; + if (matches(p, '{')) { + exp = expression_block(p); + } else if (matches(p, T_IF)) { + exp = if_expression(p); + } else { + exp = member_access(p); + /* check for function call syntax */ + if (matches(p, '(')) + exp = Apply(exp, expr_list(p, '(', ')')); + } + parse_exit(); + return exp; +} + +static AST* member_access(Parser* p) { + parse_enter(); + AST* exp = parenthesized(p); + if (accept(p, '.')) { + AST* field = identifier(p); + // TODO: convert access to an apply or dedicated AST type + } + parse_exit(); + return exp; +} + +static AST* parenthesized(Parser* p) { + parse_enter(); AST* exp; if (matches(p, '(')) { expect(p, '('); exp = expression(p); expect(p, ')'); - } else if (matches(p, '[')) { + } else { + exp = literal(p); + } + parse_exit(); + return exp; +} + +static AST* literal(Parser* p) { + parse_enter(); + AST* exp; + if (matches(p, '[')) { exp = expr_list(p, '[', ']'); - } else if (matches(p, '{')) { - exp = expression_block(p); - } else if (matches(p, T_IF)) { - exp = if_expression(p); } else if (matches(p, T_ID)) { exp = identifier(p); + // TODO: Struct init here? } else { exp = constant(p); } - - /* check for member reference or UFCS call */ - AST *member = NULL, *args = NULL; - if (accept(p, '.')) - member = identifier(p); - if (matches(p, '(')) - args = expr_list(p, '(', ')'); - - if (member && !args) - exp = exp; // ??? AST for struct reference - else if (member && args) - exp = Apply(member, args); - else if (!member && args) - exp = args; - + parse_exit(); return exp; } static AST* constant(Parser* p) { + parse_enter(); AST* tree = NULL; Tok* tok = peek(p); switch (tok->type) { @@ -200,6 +253,7 @@ static AST* constant(Parser* p) { default: error(p, "expected an expression"); } accept(p, tok->type); + parse_exit(); return tree; } -- 2.52.0