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)
//{
// 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;
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);
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);
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);
}
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) {
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;
}
-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
#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
*****************************************************************************/
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
*/
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;
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:
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);
//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
["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'] ])
# ['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([
# 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
# 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"]])
# 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
# 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