]> git.mdlowis.com Git - proto/obnc.git/commitdiff
added parser scaffolding ofr expressions
authormike lowis <mike@mdlowis.com>
Sat, 17 Apr 2021 04:00:27 +0000 (00:00 -0400)
committermike lowis <mike@mdlowis.com>
Sat, 17 Apr 2021 04:00:27 +0000 (00:00 -0400)
cerise/cerise.h
cerise/lex.c
cerise/parser.c
cerise/tests/tokens.txt

index 714213d4ffcd1c4f06cf04ade38b0c131fad56b9..af6cc558f0481644513a42b99b1b7106c08cf917 100644 (file)
@@ -20,6 +20,7 @@ typedef enum {
     INT,
     STRING,
     BOOL,
+    REAL,
     EQ,
     NEQ,
     LTEQ,
@@ -36,7 +37,6 @@ typedef enum {
     ELSE,
     ELSIF,
     END,
-    FALSE,
     FOR,
     IF,
     IMPORT,
@@ -54,7 +54,6 @@ typedef enum {
     RETURN,
     THEN,
     TO,
-    TRUE,
     TYPE,
     UNTIL,
     VAR,
index 5de2cc891e4a54b66adc3c4c132411c6ef3feb83..2f47a530da9006993bafb80ed342837896d2a0cd 100644 (file)
@@ -72,7 +72,7 @@ KeywordDef Keywords[] = {
     { "else",      ELSE      },
     { "elsif",     ELSIF     },
     { "end",       END       },
-    { "false",     FALSE     },
+    { "false",     BOOL      },
     { "for",       FOR       },
     { "if",        IF        },
     { "import",    IMPORT    },
@@ -90,7 +90,7 @@ KeywordDef Keywords[] = {
     { "return",    RETURN    },
     { "then",      THEN      },
     { "to",        TO        },
-    { "true",      TRUE      },
+    { "true",      BOOL      },
     { "type",      TYPE      },
     { "until",     UNTIL     },
     { "var",       VAR       },
@@ -141,6 +141,12 @@ static inline void convert_value(Tok* tok)
             break;
         }
 
+        case REAL:
+        {
+            tok->value.floating = strtod(tok->text, 0);
+            break;
+        }
+
         case IDENT:
         {
             KeywordDef key = { .keyword = tok->text };
@@ -232,6 +238,12 @@ static inline void readtok(Parser* ctx)
         case DIGITS:
             tok->type = INT;
             for (; Chars[(int)*curr] == DIGITS; curr++);
+            if (*curr == '.')
+            {
+                tok->type = REAL;
+                curr++;
+                for (; Chars[(int)*curr] == DIGITS; curr++);
+            }
             break;
 
         case ALPHA_:
@@ -379,7 +391,7 @@ TEST_SUITE(Lexer)
         { "else",      ELSE      },
         { "elsif",     ELSIF     },
         { "end",       END       },
-        { "false",     FALSE     },
+        { "false",     BOOL      },
         { "for",       FOR       },
         { "if",        IF        },
         { "import",    IMPORT    },
@@ -397,13 +409,14 @@ TEST_SUITE(Lexer)
         { "return",    RETURN    },
         { "then",      THEN      },
         { "to",        TO        },
-        { "true",      TRUE      },
+        { "true",      BOOL      },
         { "type",      TYPE      },
         { "until",     UNTIL     },
         { "var",       VAR       },
         { "while",     WHILE     },
         { "foo",       IDENT     },
         { "123",       INT       },
+        { "123.123",   REAL      },
         { "",          STRING    },
         { "",          END_FILE  },
     };
index 9eb79a6a5c4d5a428182f19a8657ff694b02a5bf..134a50fbaa9ba4e8d9c16f86ffcad44d4e4e3eef 100644 (file)
@@ -80,6 +80,18 @@ 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 accept(Parser* p, TokType type)
 {
     if (matches(p, type)) {
@@ -113,15 +125,58 @@ static char* expect_text(Parser* p, TokType type)
     return strdup(expect_val(p, type)->text);
 }
 
-//static int consume(Parser* p) {
-//    int type = peek(p)->type;
-//    if (!accept(p, type))
-//        error(p, "Unexpected token");
-//    return type;
-//}
+static int consume(Parser* p) 
+{
+    int type = peek(p)->type;
+    if (!accept(p, type))
+    {
+        error(p, "Unexpected token");
+    }
+    return type;
+}
 
 /* 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)
+{
+    parse_enter();
+    expect(p, MODULE);
+    char* sname = expect_text(p, IDENT);
+        /* TODO: Check that it matches filename here */
+    expect(p, ';');
+    if (matches(p, IMPORT))
+    {
+        import_list(p);
+    }
+    declaration_seq(p);
+    if (accept(p, BEGIN))
+    {
+        statement_seq(p);
+    }
+    expect(p, END);
+    char* ename = expect_text(p, IDENT);
+    if (strcmp(sname, ename))
+    {
+        error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+    }
+    expect(p, ';');
+    parse_exit();
+}
 
 static void import_list(Parser* p)
 {
@@ -146,7 +201,21 @@ static void import_list(Parser* p)
 
 static void declaration_seq(Parser* p)
 {
-    (void)p;
+    if (accept(p, CONST))
+    {
+        const_decl(p);
+        expect(p, ';');
+    }
+    if (accept(p, TYPE))
+    {
+//        type_decl(p);
+        expect(p, ';');
+    }
+    if (accept(p, VAR))
+    {
+//        var_decl(p);
+        expect(p, ';');
+    }
 }
 
 static void statement_seq(Parser* p)
@@ -154,30 +223,106 @@ static void statement_seq(Parser* p)
     (void)p;
 }
 
-void module(Parser* p)
+static void const_decl(Parser* p)
 {
-    parse_enter();
-    expect(p, MODULE);
-    char* sname = expect_text(p, IDENT);
-        /* TODO: Check that it matches filename here */
-    expect(p, ';');
-    if (matches(p, IMPORT))
-    {
-        import_list(p);
-    }
-    declaration_seq(p);
-    if (accept(p, BEGIN))
+    while (1)
     {
-        statement_seq(p);
+        /*char* name =*/ expect_text(p, IDENT);
+        expect(p, '=');
+        expression(p);
+        if (!accept(p, ','))
+        {
+            break;
+        }
     }
-    expect(p, END);
-    char* ename = expect_text(p, IDENT);
-    if (strcmp(sname, ename))
+    (void)p;
+}
+
+static void expression(Parser* p)
+{
+    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}.
+}
+
+/*
+
+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] ")" .
+
+*/
+
+
+static void simple_expr(Parser* p)
+{
+//    if (matches_oneof(p, (int[]){ '+', '-', 0 }))
+//    {
+//        consume(p);
+////        term(p);
+//    }
+    term(p);
+}
+
+static void term(Parser* p)
+{
+    factor(p);
+}
+
+// designator [ActualParameters]
+// designator = qualident {selector}.
+//     selector = "." ident | "[" ExpList "]" | "^" | "(" qualident ")".
+// ExpList = expression {"," expression}.
+// ActualParameters = "(" [ExpList] ")" .
+
+static void factor(Parser* p)
+{
+    switch ((int)peek(p)->type)
     {
-        error(p, "Expected module name '%s', recieved '%s' instead", sname, ename);
+        case INT:
+        case REAL:
+        case STRING:
+        case NIL:
+        case BOOL:
+            consume(p);
+            break;
+
+        case '(':
+            expect(p, '(');
+            expression(p);
+            expect(p, ')');
+            break;
+
+        case NOT:
+            consume(p);
+            factor(p);
+            break;
+
+        default:
+            error(p, "not a valid literal/expression");
+            break;
     }
-    expect(p, ';');
-    parse_exit();
 }
 
 /* Grammar Unit Tests
@@ -230,5 +375,25 @@ TEST_SUITE(Grammar)
         parse_rule(import_list,
             "import A, B = ModB, C;");
     }
+
+    TEST(Should parse constant declarations)
+    {
+        parse_rule(const_decl,
+            "FOO = 123");
+        parse_rule(const_decl,
+            "FOO = 123.123");
+        parse_rule(const_decl,
+            "FOO = \"\"");
+        parse_rule(const_decl,
+            "FOO = true");
+        parse_rule(const_decl,
+            "FOO = false");
+        parse_rule(const_decl,
+            "FOO = nil");
+        parse_rule(const_decl,
+            "FOO = not true");
+        parse_rule(const_decl,
+            "FOO = (not true)");
+    }
 }
 #endif
index d8a921a8c45afcaf1eaa44c22c006cbf7d29f628..f9165fbdd2e494165261d56063b703d35ceafa34 100644 (file)
@@ -59,4 +59,5 @@ var
 while
 foo
 123
+123.123
 ""