]> git.mdlowis.com Git - proto/sclpl.git/commitdiff
Implemented function syntax for functions with no arguments
authorMichael D. Lowis <mike@mdlowis.com>
Sat, 12 Dec 2015 05:05:27 +0000 (00:05 -0500)
committerMichael D. Lowis <mike@mdlowis.com>
Sat, 12 Dec 2015 05:05:27 +0000 (00:05 -0500)
source/ast.c
source/grammar.c
source/main.c
source/pprint.c
source/sclpl.h
spec/parser_spec.rb

index 3f92fff924f40ff07d70a5071681d32749d97d0d..2497c9130605966b2fd78a0ffcd52185928418a3 100644 (file)
@@ -238,9 +238,23 @@ AST* block_get(AST* block, size_t index)
     return (AST*)vec_at(&(block->value.exprs), index);
 }
 
+AST* Func(AST* args, AST* body)
+{
+    AST* node = ast(AST_FUNC);
+    node->value.func.args = args;
+    node->value.func.body = body;
+    return node;
+}
 
+AST* func_args(AST* func)
+{
+    return func->value.func.args;
+}
 
-
+AST* func_body(AST* func)
+{
+    return func->value.func.body;
+}
 
 //AST* Ann(char* name, AST* value)
 //{
@@ -261,25 +275,6 @@ AST* block_get(AST* block, size_t index)
 //    return NULL;
 //}
 //
-//AST* Func(AST* args, AST* body)
-//{
-//    (void)args;
-//    (void)body;
-//    return NULL;
-//}
-//
-//AST* func_args(AST* func)
-//{
-//    (void)func;
-//    return NULL;
-//}
-//
-//AST* func_body(AST* func)
-//{
-//    (void)func;
-//    return NULL;
-//}
-//
 //AST* Block(void)
 //{
 //    return NULL;
index 38d35a62995a2066649651d3ccb3f67faa3f94f2..f70a25cb93a66cfe22bbac81a086493437b4ddf1 100644 (file)
@@ -10,6 +10,7 @@ static AST* require(Parser* p);
 static AST* definition(Parser* p);
 static AST* expression(Parser* p);
 static AST* if_stmnt(Parser* p);
+static AST* function(Parser* p);
 static AST* literal(Parser* p);
 static AST* expr_block(Parser* p);
 static AST* token_to_tree(Tok* tok);
@@ -20,9 +21,9 @@ AST* toplevel(Parser* p)
     if (!match(p, T_END_FILE)) {
         if (accept_str(p, T_ID, "require"))
             ret = require(p);
-        else if (accept_str(p, T_ID, "def"))
+        else if (accept_str(p, T_ID, "def")) {
             ret = definition(p);
-        else
+        else
             ret = expression(p);
     }
     //printf("%p\n", ret);
@@ -35,13 +36,14 @@ AST* toplevel(Parser* p)
 
 static AST* definition(Parser* p)
 {
-    Tok* id = expect(p, T_ID);//expect_lit(p, T_ID);
+    Tok* id = expect(p, T_ID);
     AST* expr;
-    //if (peek(p)->type == T_LPAR)
-    //    expr = function(p);
-    //else
+    if (peek(p)->type == T_LPAR) {
+        expr = function(p);
+    } else {
         expr = expression(p);
-    expect(p, T_END);
+        expect(p, T_END);
+    }
     return Def(id, expr);
 }
 
@@ -62,8 +64,8 @@ static AST* expression(Parser* p)
         return expr;
     } else if (accept_str(p, T_ID, "if")) {
         return if_stmnt(p);
-    //} else if (accept_str(p, T_ID, "fn")) {
-    //    return fn_stmnt(p);
+    } else if (accept_str(p, T_ID, "fn")) {
+        return function(p);
     } else if (match(p, T_ID)) {
         return Ident(expect(p,T_ID));
         //if (peek(p)->type == T_LPAR) {
@@ -87,6 +89,20 @@ static AST* if_stmnt(Parser* p)
     return ifexpr;
 }
 
+static AST* function(Parser* p)
+{
+    expect(p, T_LPAR);
+    //while(peek(p)->type != T_RPAR) {
+    //    expect(p, T_ID);
+    //    if(peek(p)->type != T_RPAR)
+    //        expect(p, T_COMMA);
+    //}
+    expect(p, T_RPAR);
+    AST* body = expr_block(p);
+    expect(p, T_END);
+    return Func(NULL,body);
+}
+
 static AST* literal(Parser* p)
 {
     AST* ret = NULL;
@@ -216,24 +232,5 @@ static AST* arglist(Parser* p)
 }
 
 
-static AST* fn_stmnt(Parser* p)
-{
-    ////size_t mark1 = mark(p);
-    //expect(p, T_LPAR);
-    ////size_t mark2 = mark(p);
-    //while(peek(p)->type != T_RPAR) {
-    //    expect(p, T_ID);
-    //    if(peek(p)->type != T_RPAR)
-    //        expect(p, T_COMMA);
-    //}
-    //expect(p, T_RPAR);
-    ////reduce(p, mark2);
-    //while(peek(p)->type != T_END) {
-    //    expression(p);
-    //}
-    //expect(p, T_END);
-    ////reduce(p, mark1);
-    return NULL;
-}
 
 #endif
index 39c20ba6f5158254dac472fb547836ed9e4c7f54..b9bf557291858357f1ac7f16d630ac9b9dd5091d 100644 (file)
@@ -1,23 +1,8 @@
 #include <sclpl.h>
 
 char* ARGV0;
-bool verbose   = false;
-char* artifact = "bin";
-
-/* Command Line Options
- *****************************************************************************/
-const char Usage[] =
-    "Usage: sclpl [OPTION]... MODE [FILE]...\n"
-    "\n-A<type>   Emit the given type of artifact"
-    "\n-h         Print help information"
-    "\n-v         Enable verbose status messages"
-    "\n"
-;
-
-void usage(void) {
-    fprintf(stderr, "%s", Usage);
-    exit(1);
-}
+bool Verbose   = false;
+char* Artifact = "bin";
 
 /* Driver Modes
  *****************************************************************************/
@@ -53,6 +38,17 @@ static int emit_program(void) {
     return 0;
 }
 
+/* Main Routine and Usage
+ *****************************************************************************/
+void usage(void) {
+    fprintf(stderr, "%s\n",
+        "Usage: sclpl [OPTION]... MODE [FILE]...\n"
+        "\n-A<type>   Emit the given type of artifact"
+        "\n-h         Print help information"
+        "\n-v         Enable verbose status messages");
+    exit(1);
+}
+
 /* TODO:
 
     * Formalize grammar for parser
@@ -62,25 +58,26 @@ static int emit_program(void) {
 
 */
 int user_main(int argc, char **argv) {
+    /* Option parsing */
     OPTBEGIN {
-        case 'A': artifact = EOPTARG(usage()); break;
-        case 'v': verbose = true; break;
+        case 'A': Artifact = EOPTARG(usage()); break;
+        case 'v': Verbose = true; break;
         default:  usage();
     } OPTEND;
 
     /* Execute the main compiler process */
-    if (0 == strcmp("bin", artifact)) {
+    if (0 == strcmp("bin", Artifact)) {
         return emit_program();
-    } else if (0 == strcmp("lib", artifact)) {
+    } else if (0 == strcmp("lib", Artifact)) {
         return emit_staticlib();
-    } else if (0 == strcmp("src", artifact)) {
+    } else if (0 == strcmp("src", Artifact)) {
         return emit_csource();
-    } else if (0 == strcmp("ast", artifact)) {
+    } else if (0 == strcmp("ast", Artifact)) {
         return emit_tree();
-    } else if (0 == strcmp("tok", artifact)) {
+    } else if (0 == strcmp("tok", Artifact)) {
         return emit_tokens();
     } else {
-        fprintf(stderr, "Unknonwn artifact type: '%s'\n\n", artifact);
+        fprintf(stderr, "Unknonwn artifact type: '%s'\n\n", Artifact);
         usage();
     }
     return 1;
index 53fcad2f2ae83407c30c86db48009e0ad5f4325f..52721e3a12de1129b60751b9ba20a7749c8759eb 100644 (file)
@@ -153,6 +153,12 @@ void pprint_tree(FILE* file, AST* tree, int depth)
             break;
 
         case AST_FUNC:
+            printf("(fn ()");
+            for (size_t i = 0; i < block_size(func_body(tree)); i++) {
+                printf(" ");
+                pprint_tree(file, block_get(func_body(tree), i), depth);
+            }
+            printf(")");
             break;
 
         default:
index 296c30ccd2a88a79ccaa8f8ec1c00ee41de75a3d..14a5700320753b029c5b1c8dd5239cebc557c715 100644 (file)
@@ -171,7 +171,10 @@ void block_append(AST* block, AST* expr);
 size_t block_size(AST* block);
 AST* block_get(AST* block, size_t index);
 
-
+/* Function */
+AST* Func(AST* args, AST* body);
+AST* func_args(AST* func);
+AST* func_body(AST* func);
 
 ///* Annotation */
 //AST* Ann(char* name, AST* value);
@@ -179,10 +182,6 @@ AST* block_get(AST* block, size_t index);
 //AST* ann_value(AST* def);
 //
 //
-///* Function */
-//AST* Func(AST* args, AST* body);
-//AST* func_args(AST* func);
-//AST* func_body(AST* func);
 //
 //
 /* Lexer and Parser Types
index eb01dcfd2b2b88d879632a1e1f044e8b6fb99def..545e4c61767e494c619375385d848bbca12dbb85 100644 (file)
@@ -69,8 +69,7 @@ describe "sclpl grammar" do
         ["if", "T_INT:123", ["block", "T_INT:321"], ["block", "T_INT:456"]]])
     end
   end
-#
-#
+
 #  context "type definitions" do
 #    it "should parse a simple type definition" do
 #      expect(ast('type foo is int;')).to eq([ ['T_ID:type', 'T_ID:foo', 'T_ID:is', 'T_ID:int'] ])
@@ -129,21 +128,21 @@ describe "sclpl grammar" do
 #          ['T_ID:type', 'T_ID:foo', ['T_ID:record', ['T_ID:int', 'T_ID:a'], ['T_ID:int', 'T_ID:b'], ['T_ID:int', 'T_ID:c']]] ])
 #    end
 #  end
-#
-#  context "definitions" do
-#    it "should parse a value definition" do
-#      expect(ast('def foo 123;')).to eq([ ['T_ID:def', 'T_ID:foo', 'T_INT:123'] ])
-#    end
-#
-#    it "should parse a function definition" do
-#      expect(ast('def foo() 123;')).to eq([
-#        ['T_ID:def', 'T_ID:foo', ['T_ID:fn', [], 'T_INT:123']] ])
-#    end
-#
-#    it "should parse a function definition  with multiple expressions in the body" do
-#      expect(ast('def foo() 123 321;')).to eq([
-#        ['T_ID:def', 'T_ID:foo', ['T_ID:fn', [], 'T_INT:123', 'T_INT:321']] ])
-#    end
+
+  context "definitions" do
+    it "should parse a value definition" do
+      expect(ast('def foo 123;')).to eq([ ['def', 'foo', 'T_INT:123'] ])
+    end
+
+    it "should parse a function definition" do
+      expect(ast('def foo() 123;')).to eq([
+        ['def', 'foo', ['fn', [], 'T_INT:123']] ])
+    end
+
+    it "should parse a function definition  with multiple expressions in the body" do
+      expect(ast('def foo() 123 321;')).to eq([
+        ['def', 'foo', ['fn', [], 'T_INT:123', 'T_INT:321']] ])
+    end
 #
 #    it "should parse a function definition with one argument" do
 #      expect(ast('def foo(a) 123;')).to eq([
@@ -159,7 +158,7 @@ describe "sclpl grammar" do
 #      expect(ast('def foo(a,b,c) 123;')).to eq([
 #        ['T_ID:def', 'T_ID:foo', ['T_ID:fn', ['T_ID:a', 'T_ID:b', 'T_ID:c'], 'T_INT:123']] ])
 #    end
-#  end
+  end
 #
 #  context "annotations" do
 #    it "should parse a type annotation for a simple type" do
@@ -181,21 +180,21 @@ describe "sclpl grammar" do
 #    end
 #  end
 #
-#  context "expressions" do
-#    context "parenthese grouping" do
-#      it "should parse a parenthesized expression" do
-#        expect(ast('(123)')).to eq([['T_INT:123']])
-#      end
-#
-#      it "should parse a nested parenthesized expression" do
-#        expect(ast('((123))')).to eq([[['T_INT:123']]])
-#      end
-#    end
-#
-#    context "function literals" do
-#      it "should parse a function with no params" do
-#        expect(ast('fn() 123;')).to eq([["T_ID:fn", [], "T_INT:123"]])
-#      end
+  context "expressions" do
+    context "parenthese grouping" do
+      it "should parse a parenthesized expression" do
+        expect(ast('(123)')).to eq(['T_INT:123'])
+      end
+
+      it "should parse a nested parenthesized expression" do
+        expect(ast('((123))')).to eq(['T_INT:123'])
+      end
+    end
+
+    context "function literals" do
+      it "should parse a function with no params" do
+        expect(ast('fn() 123;')).to eq([["fn", [], "T_INT:123"]])
+      end
 #
 #      it "should parse a function with one param" do
 #        expect(ast('fn(a) 123;')).to eq([["T_ID:fn", ["T_ID:a"], "T_INT:123"]])
@@ -204,7 +203,7 @@ describe "sclpl grammar" do
 #      it "should parse a function with two params" do
 #        expect(ast('fn(a,b) 123;')).to eq([["T_ID:fn", ["T_ID:a", "T_ID:b"], "T_INT:123"]])
 #      end
-#    end
+    end
 #
 #    context "function application" do
 #      it "should parse an application with no params " do
@@ -219,15 +218,15 @@ describe "sclpl grammar" do
 #        expect(ast('foo(a,b)')).to eq([["T_ID:foo", "T_ID:a", "T_ID:b"]])
 #      end
 #    end
-#  end
-#
-#  context "corner cases" do
-#    it "an unexpected terminator should error" do
-#      expect{ast(';')}.to raise_error /Error/
-#    end
-#
-#    it "an invalid literal should error" do
-#      expect{ast('\'')}.to raise_error /Error/
-#    end
-#  end
+  end
+
+  context "corner cases" do
+    it "an unexpected terminator should error" do
+      expect{ast(';')}.to raise_error /Error/
+    end
+
+    it "an invalid literal should error" do
+      expect{ast('\'')}.to raise_error /Error/
+    end
+  end
 end