]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
attempted handling token parsing with a single token struct instead of heap allocatin...
authorMichael D. Lowis <mike@mdlowis.com>
Mon, 21 May 2018 02:57:07 +0000 (22:57 -0400)
committerMichael D. Lowis <mike@mdlowis.com>
Mon, 21 May 2018 02:57:07 +0000 (22:57 -0400)
Makefile
source/main.c
source/parser.c
spec/parser_spec.rb

index 1924618d41e4bdef29fed9e876d76539975029d2..33845875d82a134fa30b8af98276a1a24081b1e7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -4,13 +4,13 @@
 # Update these variables according to your requirements.
 
 # tools
-CC = c99
+CC = cc
 LD = ${CC}
 
 # completed flags
 INCS      = -Isource/
 CPPFLAGS  =
-CFLAGS   += ${INCS} ${CPPFLAGS}
+CFLAGS   += -O0 -g ${INCS} ${CPPFLAGS}
 LDFLAGS  += ${LIBS}
 ARFLAGS   = rcs
 
index 534ebd26e6ba9583ef1b66b16d22378c5b1cbf2e..18b7d1d6ccb49201c012bd1d411478fe286d1f5d 100644 (file)
@@ -1,7 +1,7 @@
 #include <sclpl.h>
 
 char* ARGV0;
-char* Artifact = "bin";
+char* Artifact = "ast";
 
 /* Driver Modes
  *****************************************************************************/
index bb8672652a4a64efd34a2c611876be7ec75ab08d..a4611860ddd9da09043467638294b05a3b29c402 100644 (file)
@@ -8,20 +8,18 @@
 
 /* Private Declarations
  *****************************************************************************/
-// Sentinel EOF Token
-Tok tok_eof = { NULL, 0, 0, T_END_FILE, {0} };
-
 // Grammar Routines
-static AST* require(Parser* p);
+static AST* const_definition(Parser* p);
+static AST* const_expression(Parser* p);
 static AST* definition(Parser* p);
 static AST* expression(Parser* p);
-static AST* if_stmnt(Parser* p);
 static AST* function(Parser* p);
+static void type_annotation(Parser* p);
 static AST* literal(Parser* p);
 static AST* expr_block(Parser* p);
+static AST* if_stmnt(Parser* p);
 static AST* token_to_tree(Tok* tok);
 static AST* func_app(Parser* p, AST* fn);
-static void type_annotation(Parser* p);
 
 // Parsing Routines
 static void fetch(Parser* parser);
@@ -35,41 +33,59 @@ static Tok* expect(Parser* parser, TokType type);
 
 /* Grammar Definition
  *****************************************************************************/
-AST* toplevel(Parser* p)
-{
+AST* toplevel(Parser* p) {
     AST* ret = NULL;
     if (!match(p, T_END_FILE)) {
         if (accept(p, T_DEF))
-            ret = definition(p);
+            ret = const_definition(p);
         else
             error(p, "only definitions are allowed at the toplevel");
     }
     return ret;
 }
 
-static AST* definition(Parser* p)
-{
+static AST* const_definition(Parser* p) {
     AST* expr;
     Tok* id = expect(p, T_ID);
     if (peek(p)->type == T_LPAR) {
         expr = function(p);
     } else {
         type_annotation(p);
-        expr = expression(p);
+        expr = const_expression(p);
         expect(p, T_END);
     }
     return Def(id, expr);
 }
 
-static AST* require(Parser* p)
-{
-    AST* ast = Require(expect(p, T_STRING));
-    expect(p, T_END);
-    return ast;
+static AST* const_expression(Parser* p) {
+    AST* expr = NULL;
+    if (accept(p, T_LPAR)) {
+        expr = const_expression(p);
+        expect(p, T_RPAR);
+    } else if (accept(p, T_FN)) {
+        expr = function(p);
+    } else if (match(p, T_ID)) {
+        expr = Ident(expect(p,T_ID));
+    } else {
+        expr = literal(p);
+    }
+    return expr;
 }
 
-static AST* expression(Parser* p)
-{
+static AST* definition(Parser* p) {
+    AST* expr;
+    Tok* id = expect(p, T_ID);
+    if (peek(p)->type == T_LPAR) {
+        expr = function(p);
+    } else {
+        type_annotation(p);
+        expr = expression(p);
+        expect(p, T_END);
+    }
+    return Def(id, expr);
+}
+
+static AST* expression(Parser* p) {
     AST* expr = NULL;
     if (accept(p, T_LPAR)) {
         expr = expression(p);
@@ -89,20 +105,7 @@ static AST* expression(Parser* p)
     return expr;
 }
 
-static AST* if_stmnt(Parser* p)
-{
-    AST* ifexpr = IfExpr();
-    ifexpr_set_cond( ifexpr, expression(p) );
-    accept(p, T_THEN);
-    ifexpr_set_then( ifexpr, expr_block(p) );
-    if (accept(p, T_ELSE))
-        ifexpr_set_else( ifexpr, expr_block(p) );
-    expect(p,T_END);
-    return ifexpr;
-}
-
-static AST* function(Parser* p)
-{
+static AST* function(Parser* p) {
     AST* func = Func();
     expect(p, T_LPAR);
     while(peek(p)->type != T_RPAR) {
@@ -118,8 +121,19 @@ static AST* function(Parser* p)
     return func;
 }
 
-static AST* literal(Parser* p)
-{
+static void type_annotation(Parser* p) {
+    expect(p, T_ID);
+    /* array type */
+    if (accept(p,T_LBRACK)) {
+        accept(p, T_INT);
+        expect(p, T_RBRACK);
+    /* reference type */
+    } else if (accept(p, T_AMP)) {
+        // TODO: implement reference types
+    }
+}
+
+static AST* literal(Parser* p) {
     AST* ret = NULL;
     Tok* tok = peek(p);
     switch (tok->type) {
@@ -136,8 +150,7 @@ static AST* literal(Parser* p)
     return ret;
 }
 
-static AST* expr_block(Parser* p)
-{
+static AST* expr_block(Parser* p) {
     AST* block = NULL;
     vec_t exprs;
     vec_init(&exprs);
@@ -175,8 +188,18 @@ static AST* token_to_tree(Tok* tok)
     }
 }
 
-static AST* func_app(Parser* p, AST* fn)
-{
+static AST* if_stmnt(Parser* p) {
+    AST* ifexpr = IfExpr();
+    ifexpr_set_cond( ifexpr, expression(p) );
+    accept(p, T_THEN);
+    ifexpr_set_then( ifexpr, expr_block(p) );
+    if (accept(p, T_ELSE))
+        ifexpr_set_else( ifexpr, expr_block(p) );
+    expect(p,T_END);
+    return ifexpr;
+}
+
+static AST* func_app(Parser* p, AST* fn) {
     AST* app = FnApp(fn);
     expect(p,T_LPAR);
     while (peek(p)->type != T_RPAR) {
@@ -188,19 +211,6 @@ static AST* func_app(Parser* p, AST* fn)
     return app;
 }
 
-static void type_annotation(Parser* p)
-{
-    expect(p, T_ID);
-    /* array type */
-    if (accept(p,T_LBRACK)) {
-        accept(p, T_INT);
-        expect(p, T_RBRACK);
-    /* reference type */
-    } else if (accept(p, T_AMP)) {
-
-    }
-}
-
 /* Parsing Routines
  *****************************************************************************/
 Parser* parser_new(char* prompt, FILE* input)
@@ -217,11 +227,11 @@ static void fetch(Parser* parser)
     gettoken(parser, &(parser->tok));
 }
 
-static Tok* peek(Parser* parser)
+static Tok* peek(Parser* p)
 {
-    if (T_NONE == parser->tok.type)
-        fetch(parser);
-    return &(parser->tok);
+    if (T_NONE == p->tok.type)
+        gettoken(p, &(p->tok));
+    return &(p->tok);
 }
 
 static bool parser_eof(Parser* parser)
@@ -265,4 +275,3 @@ static Tok* expect(Parser* parser, TokType type)
         error(parser, "Unexpected token");
     return tok;
 }
-
index 7e6f34877ed6a06879949c4dcf4649d33f752935..0452253fafbae53075caa218fe275c2e1704266d 100644 (file)
@@ -1,81 +1,55 @@
 require 'open3'
 
 describe "sclpl grammar" do
-  context "requires" do
-    it "should parse a require statement" do
-      expect(ast('require "foo";')).to eq([ ['require', '"foo"'] ])
-    end
-
-    it "should parse a require statement using end keyword" do
-        expect(ast('require "foo" end')).to eq([ ['require', '"foo"'] ])
-    end
-
-    it "should error on missing semicolon" do
-      expect{ast('require "foo"')}.to raise_error /Error/
-    end
-
-    it "should error on missing filename" do
-      expect{ast('require ;')}.to raise_error /Error/
-    end
-
-    it "should error on invalid filename type" do
-      expect{ast('require 123;')}.to raise_error /Error/
-    end
-
-    it "should error on too many parameters" do
-      expect{ast('require foo bar;')}.to raise_error /Error/
-    end
-  end
-
-  context "definitions" do
-    it "should parse a value definition with type annotation" do
-      expect(ast('def foo int 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
-    end
-
-    it "should parse a function definition with return type annotation" do
-      expect(ast('def foo() int 123;')).to eq([
-        ['def', 'foo', ['fn', [],
-          ["let", ["$:0", "T_INT:123"], "$:0"]]] ])
-    end
-
-    it "should error on a function definition with missing return type" do
-      pending("TODO: fix the error message here")
-      expect(ast('def foo() 123;')).to raise_error /Error/
-    end
-
-    it "should parse a function definition  with multiple expressions in the body" do
-      expect(ast('def foo() int 123 321;')).to eq([
-        ['def', 'foo', ['fn', [],
-          ["let", ["$:0", "T_INT:123"],
-            ["let", ["$:1", "T_INT:321"], "$:1"]]]]])
-    end
-
-    it "should parse a function definition with one definition and expression" do
-      expect(ast('def foo() int def bar int 123; add(bar,321);')).to eq([
-        ['def', 'foo', ['fn', [],
-          ["let", ["T_ID:bar", "T_INT:123"],
-            ["let", ["$:0", ["T_ID:add", "T_ID:bar", "T_INT:321"]], "$:0"]]]]])
-    end
-
-    it "should parse a function definition with one argument" do
-      expect(ast('def foo(a int) int 123;')).to eq([
-        ['def', 'foo', ['fn', ['T_ID:a'],
-          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
-    end
-
-    it "should parse a function definition with two arguments" do
-      expect(ast('def foo(a int, b int) int 123;')).to eq([
-        ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b'],
-          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
-    end
-
-    it "should parse a function definition with three arguments" do
-      expect(ast('def foo(a int, b int, c int) int 123;')).to eq([
-        ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'],
-          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
-    end
-  end
-
+#  context "definitions" do
+#    it "should parse a value definition with type annotation" do
+#      expect(ast('def foo int 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
+#    end
+#
+#    it "should parse a function definition with return type annotation" do
+#      expect(ast('def foo() int 123;')).to eq([
+#        ['def', 'foo', ['fn', [],
+#          ["let", ["$:0", "T_INT:123"], "$:0"]]] ])
+#    end
+#
+#    it "should error on a function definition with missing return type" do
+#      pending("TODO: fix the error message here")
+#      expect(ast('def foo() 123;')).to raise_error /Error/
+#    end
+#
+#    it "should parse a function definition  with multiple expressions in the body" do
+#      expect(ast('def foo() int 123 321;')).to eq([
+#        ['def', 'foo', ['fn', [],
+#          ["let", ["$:0", "T_INT:123"],
+#            ["let", ["$:1", "T_INT:321"], "$:1"]]]]])
+#    end
+#
+#    it "should parse a function definition with one definition and expression" do
+#      expect(ast('def foo() int def bar int 123; add(bar,321);')).to eq([
+#        ['def', 'foo', ['fn', [],
+#          ["let", ["T_ID:bar", "T_INT:123"],
+#            ["let", ["$:0", ["T_ID:add", "T_ID:bar", "T_INT:321"]], "$:0"]]]]])
+#    end
+#
+#    it "should parse a function definition with one argument" do
+#      expect(ast('def foo(a int) int 123;')).to eq([
+#        ['def', 'foo', ['fn', ['T_ID:a'],
+#          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
+#    end
+#
+#    it "should parse a function definition with two arguments" do
+#      expect(ast('def foo(a int, b int) int 123;')).to eq([
+#        ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b'],
+#          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
+#    end
+#
+#    it "should parse a function definition with three arguments" do
+#      expect(ast('def foo(a int, b int, c int) int 123;')).to eq([
+#        ['def', 'foo', ['fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'],
+#          ["let", ["$:0", "T_INT:123"], "$:0"]]]])
+#    end
+#  end
+#
 #  context "literals" do
 #    it "should parse a string" do
 #      expect(ast('"foo"')).to eq(['T_STRING:"foo"'])