]> git.mdlowis.com Git - proto/obnc.git/commitdiff
added rule macro to automatically add tracing code
authormike lowis <mike@mdlowis.com>
Mon, 19 Apr 2021 01:09:45 +0000 (21:09 -0400)
committermike lowis <mike@mdlowis.com>
Mon, 19 Apr 2021 01:09:45 +0000 (21:09 -0400)
cerise/build.sh
cerise/parser.c

index de92c5040eb5025a696464fee27ba672d92fe31e..b183a1d05fd8bb22384a0bd2766df97abd8a5b6e 100755 (executable)
@@ -3,3 +3,4 @@ ctags -R &
 cc -g -D CERISE_TESTS -Wall -Wextra --std=c99 -o cerisec-test *.c \
   && ./cerisec-test \
   && cc -g -Wall -Wextra -Werror --std=c99 -o cerisec *.c
+[ $? -gt 0 ] && printf "\a"
index 134a50fbaa9ba4e8d9c16f86ffcad44d4e4e3eef..7aecee8327ae70c420af69e45a083ab91302f69e 100644 (file)
@@ -1,17 +1,19 @@
 #include "cerise.h"
 #include <stdarg.h>
 
-//#define TRACE
+#define TRACE
 #ifdef TRACE
-static int Indent = 0;
-#define parse_enter() \
-    (printf("%*c-> %s\n", ++Indent * 2, ' ', __func__))
-#define parse_exit() \
-    Indent--
-//    (printf("%*c<- %s\n", --Indent * 2, ' ', __func__))
+    static int Indent = 0;
+    #define RULE(name) \
+        void name##_actual(Parser* p); \
+        void name(Parser* p) { \
+            printf("%*c-> %s\n", ++Indent * 2, ' ', __func__); \
+            name##_actual(p); \
+            Indent--; } \
+        void name##_actual(Parser* p)
 #else
-#define parse_enter()
-#define parse_exit()
+    #define RULE(name) \
+        void name(Parser* p)
 #endif
 
 /* Precedence Table
@@ -80,17 +82,17 @@ static bool matches(Parser* p, TokType type)
     return (peek(p)->type == type);
 }
 
-//static bool matches_oneof(Parser* p, TokType types[])
-//{
-//    for (int i = 0; types[i] != NONE; i++)
-//    {
-//        if (matches(p, types[i]))
-//        {
-//            return true;
-//        }
-//    }
-//    return false;
-//}
+static bool matches_oneof(Parser* p, TokType types[])
+{
+    for (int i = 0; types[i] != NONE; i++)
+    {
+        if (matches(p, types[i]))
+        {
+            return true;
+        }
+    }
+    return false;
+}
 
 static bool accept(Parser* p, TokType type)
 {
@@ -138,23 +140,20 @@ static int consume(Parser* p)
 /* Grammar Definition
  *****************************************************************************/
 void module(Parser* p);
-static void import_list(Parser* p);
-static void declaration_seq(Parser* p);
-static void statement_seq(Parser* p);
-static void const_decl(Parser* p);
-
-static void expression(Parser* p);
-static void simple_expr(Parser* p);
-static void term(Parser* p);
-static void factor(Parser* p);
-
-//static int RelationOps[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
-//static int AddOps[] = { '+', '-', OR, 0 };
-//static int MulOps[] = { '*', '/', AND, 0 };
-
-void module(Parser* p)
+void import_list(Parser* p);
+void declaration_seq(Parser* p);
+void statement_seq(Parser* p);
+void const_decl(Parser* p);
+void expression(Parser* p);
+void simple_expr(Parser* p);
+void term(Parser* p);
+void factor(Parser* p);
+void designator(Parser* p);
+void qualident(Parser* p);
+void expr_list(Parser* p);
+
+RULE(module)
 {
-    parse_enter();
     expect(p, MODULE);
     char* sname = expect_text(p, IDENT);
         /* TODO: Check that it matches filename here */
@@ -175,12 +174,10 @@ void module(Parser* p)
         error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
     }
     expect(p, ';');
-    parse_exit();
 }
 
-static void import_list(Parser* p)
+RULE(import_list)
 {
-    parse_enter();
     expect(p, IMPORT);
     while (1)
     {
@@ -196,10 +193,9 @@ static void import_list(Parser* p)
         expect(p, ',');
     }
     expect(p, ';');
-    parse_exit();
 }
 
-static void declaration_seq(Parser* p)
+RULE(declaration_seq)
 {
     if (accept(p, CONST))
     {
@@ -218,12 +214,12 @@ static void declaration_seq(Parser* p)
     }
 }
 
-static void statement_seq(Parser* p)
+RULE(statement_seq)
 {
     (void)p;
 }
 
-static void const_decl(Parser* p)
+RULE(const_decl)
 {
     while (1)
     {
@@ -238,65 +234,68 @@ static void const_decl(Parser* p)
     (void)p;
 }
 
-static void expression(Parser* p)
+RULE(expression)
 {
+    // expression = SimpleExpression [relation SimpleExpression].
+    //     relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
+
+    int ops[] = { EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0 };
     simple_expr(p);
-//    int operators[] = {EQ, NEQ, '<', LTEQ, '>', GTEQ, IS, 0};
-//    simple_expr(p);
-//    if (matches_oneof(p, operators))
-//    {
-//        consume(p);
-//        simple_expr(p);
-//    }
-
-// expression = SimpleExpression [relation SimpleExpression].
-// relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
-// SimpleExpression = ["+" | "-"] term {AddOperator term}.
+    if (matches_oneof(p, ops))
+    {
+        consume(p);
+        simple_expr(p);
+    }
 }
 
-/*
-
-expression = SimpleExpression [relation SimpleExpression].
-    relation = "=" | "!=" | "<" | "<=" | ">" | ">=" | "is".
-
-SimpleExpression = ["+" | "-"] term {AddOperator term}.
-    AddOperator = "+" | "-" | "or".
-
-term = factor {MulOperator factor}.
-    MulOperator = "*" | "/" | "div" | "mod" | "and".
-
-factor = number | string | "nil" | "true" | "false" | designator [ActualParameters] | "(" expression ")" | "not" factor.
-designator [ActualParameters]
-designator = qualident {selector}.
-    selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
-ExpList = expression {"," expression}.
-ActualParameters = "(" [ExpList] ")" .
-
-*/
+RULE(simple_expr)
+{
+    // SimpleExpression = ["+" | "-"] term {AddOperator term}.
+    //     AddOperator = "+" | "-" | "or".
 
+    /* first term and +/- */
+    if (matches_oneof(p, (int[]){'+', '-', 0}))
+    {
+        consume(p); // OP
+        term(p);
+    }
+    else
+    {
+        term(p);
+    }
 
-static void simple_expr(Parser* p)
-{
-//    if (matches_oneof(p, (int[]){ '+', '-', 0 }))
-//    {
-//        consume(p);
-////        term(p);
-//    }
-    term(p);
+    /* optional second term and op */
+    while (matches_oneof(p, (int[]){'+', '-', OR, 0}))
+    {
+        consume(p);
+        term(p);
+    }
 }
 
-static void term(Parser* p)
+RULE(term)
 {
+    // term = factor {MulOperator factor}.
+    //     MulOperator = "*" | "/" | "and".
     factor(p);
+    while (matches_oneof(p, (int[]){'*', '/', AND, 0}))
+    {
+        consume(p);
+        factor(p);
+    }
 }
 
-// designator [ActualParameters]
-// designator = qualident {selector}.
-//     selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
-// ExpList = expression {"," expression}.
-// ActualParameters = "(" [ExpList] ")" .
+/*
+factor = number 
+       | string 
+       | "nil" 
+       | "true" 
+       | "false" 
+       | designator [ActualParameters] 
+       | "(" expression ")" 
+       | "not" factor.
+*/
 
-static void factor(Parser* p)
+RULE(factor)
 {
     switch ((int)peek(p)->type)
     {
@@ -319,12 +318,68 @@ static void factor(Parser* p)
             factor(p);
             break;
 
-        default:
-            error(p, "not a valid literal/expression");
+        case IDENT:
+            designator(p);
+//            actual_params(p);
+            break;
+    }
+}
+
+/*
+    designator = qualident {selector}.
+    selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
+    ExpList = expression {"," expression}.
+    qualident = [ident "."] ident.
+
+    ActualParameters = "(" [ExpList] ")" .
+*/
+RULE(designator)
+{
+    qualident(p);
+    /* selector */
+    switch ((int)peek(p)->type)
+    {
+        case '.':
+            expect(p, IDENT);
+            break;
+
+        case '[':
+            expr_list(p);
+            expect(p, ']');
+            break;
+
+        case '^':
+            expect(p, '^');
+            break;
+
+        case '(':
+            qualident(p);
+            expect(p, ')');
             break;
     }
 }
 
+RULE(qualident)
+{
+    expect(p, IDENT);
+    if (accept(p, '.'))
+    {
+        expect(p, IDENT);
+    }
+}
+
+RULE(expr_list)
+{
+    while (1)
+    {
+        expression(p);
+        if (!accept(p, ','))
+        {
+            break;
+        }
+    }
+}
+
 /* Grammar Unit Tests
  *****************************************************************************/
 #ifdef CERISE_TESTS
@@ -394,6 +449,14 @@ TEST_SUITE(Grammar)
             "FOO = not true");
         parse_rule(const_decl,
             "FOO = (not true)");
+        parse_rule(const_decl,
+            "FOO = +1");
+        parse_rule(const_decl,
+            "FOO = -1");
+        parse_rule(const_decl,
+            "FOO = 1 + 1");
+        parse_rule(const_decl,
+            "FOO = 1 + 2 * 4");
     }
 }
 #endif