]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
started structuring parser to support inheritance and instrumented tracing for debug
authorMichael D. Lowis <mike.lowis@gentex.com>
Fri, 29 Mar 2019 19:15:27 +0000 (15:15 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Fri, 29 Mar 2019 19:15:27 +0000 (15:15 -0400)
example.src
source/parser.c

index b60c809b2f5bfc773adf48ba83dc74c226eb15d0..ef80023392aa55f753fb2c1a9c802eb0577f042e 100644 (file)
@@ -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
 }
index 9192190d37bc75fb6afeb6abc550ce3dcc686664..96dd223a9ee1b8e22e63c37d5826c113f4893b8b 100644 (file)
@@ -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;
 }