#include "lexer.h"
#include "exn.h"
-tree_t* grammar_toplevel(parser_t* p_parser)
+tree_t* grammar_toplevel(parser_t* p)
{
tree_t* p_tree = NULL;
try {
- if (parser_accept_str(p_parser, T_ID, "require"))
- grammar_require(p_parser);
- else if (parser_accept_str(p_parser, T_ID, "def"))
- grammar_definition(p_parser);
+ if (parser_accept_str(p, T_ID, "require"))
+ grammar_require(p);
+ else if (parser_accept_str(p, T_ID, "type"))
+ grammar_type_definition(p);
+ else if (parser_accept_str(p, T_ID, "ann"))
+ grammar_type_annotation(p);
+ else if (parser_accept_str(p, T_ID, "def"))
+ grammar_definition(p);
else
- grammar_expression(p_parser);
- p_tree = parser_get_tree(p_parser);
+ grammar_expression(p);
+ p_tree = parser_get_tree(p);
} catch(ParseException) {
fprintf(stderr, "Invalid Syntax\n");
}
return p_tree;
}
-void grammar_require(parser_t* p_parser)
+void grammar_require(parser_t* p)
{
- size_t mark = parser_mark(p_parser);
- parser_expect(p_parser, T_STRING);
- parser_expect(p_parser, T_END);
- parser_reduce(p_parser, mark);
+ size_t mark = parser_mark(p);
+ parser_expect(p, T_STRING);
+ parser_expect(p, T_END);
+ parser_reduce(p, mark);
}
-void grammar_definition(parser_t* p_parser)
+void grammar_type_annotation(parser_t* p)
{
- size_t mark = parser_mark(p_parser);
- parser_expect(p_parser,T_ID);
- if (parser_peek(p_parser)->type == T_LPAR) {
- parser_insert(p_parser, T_ID, lexer_dup("fn"));
- grammar_fn_stmnt(p_parser);
+ size_t mark = parser_mark(p);
+ parser_expect(p, T_ID);
+ grammar_type(p);
+ parser_expect(p, T_END);
+ parser_reduce(p, mark);
+}
+
+void grammar_type_definition(parser_t* p)
+{
+ size_t mark = parser_mark(p);
+ parser_expect(p, T_ID);
+ parser_expect_str(p, T_ID, "is");
+ grammar_type(p);
+ parser_expect(p, T_END);
+ parser_reduce(p, mark);
+}
+
+void grammar_type(parser_t* p) {
+ if (parser_accept(p, T_LBRACE)) {
+ grammar_tuple(p);
} else {
- grammar_expression(p_parser);
- parser_expect(p_parser,T_END);
+ parser_expect(p, T_ID);
+ if (parser_accept(p, T_LPAR)) {
+ grammar_function(p);
+ }
}
- parser_reduce(p_parser, mark);
}
-void grammar_expression(parser_t* p_parser)
+void grammar_tuple(parser_t* p) {
+ size_t mark = parser_mark(p);
+ parser_insert(p, T_ID, lexer_dup("tuple"));
+ do {
+ grammar_type(p);
+ } while (parser_accept(p, T_COMMA));
+ parser_expect(p, T_RBRACE);
+ parser_reduce(p, mark);
+}
+
+void grammar_function(parser_t* p) {
+ size_t mark1 = parser_mark(p) - 1;
+ size_t mark2 = parser_mark(p);
+ while (!parser_accept(p, T_RPAR)) {
+ grammar_type(p);
+ if (T_RPAR != parser_peek(p)->type)
+ parser_expect(p, T_COMMA);
+ }
+ parser_reduce(p, mark2);
+ parser_reduce(p, mark1);
+}
+
+void grammar_definition(parser_t* p)
+{
+ size_t mark = parser_mark(p);
+ parser_expect(p,T_ID);
+ if (parser_peek(p)->type == T_LPAR) {
+ parser_insert(p, T_ID, lexer_dup("fn"));
+ grammar_fn_stmnt(p);
+ } else {
+ grammar_expression(p);
+ parser_expect(p,T_END);
+ }
+ parser_reduce(p, mark);
+}
+
+void grammar_expression(parser_t* p)
{
- if (parser_accept(p_parser, T_LPAR)) {
- size_t mark = parser_mark(p_parser);
- grammar_expression(p_parser);
- parser_expect(p_parser, T_RPAR);
- parser_reduce(p_parser, mark);
- } else if (parser_accept_str(p_parser, T_ID, "if")) {
- grammar_if_stmnt(p_parser);
- } else if (parser_accept_str(p_parser, T_ID, "fn")) {
- grammar_fn_stmnt(p_parser);
- } else if (parser_peek(p_parser)->type == T_ID) {
- parser_expect(p_parser, T_ID);
- if (parser_peek(p_parser)->type == T_LPAR) {
- grammar_arglist(p_parser);
+ if (parser_accept(p, T_LPAR)) {
+ size_t mark = parser_mark(p);
+ grammar_expression(p);
+ parser_expect(p, T_RPAR);
+ parser_reduce(p, mark);
+ } else if (parser_accept_str(p, T_ID, "if")) {
+ grammar_if_stmnt(p);
+ } else if (parser_accept_str(p, T_ID, "fn")) {
+ grammar_fn_stmnt(p);
+ } else if (parser_peek(p)->type == T_ID) {
+ parser_expect(p, T_ID);
+ if (parser_peek(p)->type == T_LPAR) {
+ grammar_arglist(p);
}
} else {
- grammar_literal(p_parser);
+ grammar_literal(p);
}
}
-void grammar_literal(parser_t* p_parser)
+void grammar_literal(parser_t* p)
{
- switch (parser_peek(p_parser)->type) {
+ switch (parser_peek(p)->type) {
case T_BOOL:
case T_CHAR:
case T_STRING:
case T_INT:
case T_FLOAT:
- parser_accept(p_parser, parser_peek(p_parser)->type);
+ parser_accept(p, parser_peek(p)->type);
break;
default:
- parser_error(p_parser, "Not a valid expression");
+ parser_error(p, "Not a valid expression");
}
}
-void grammar_arglist(parser_t* p_parser)
+void grammar_arglist(parser_t* p)
{
- size_t mark = parser_mark(p_parser);
- parser_expect(p_parser, T_LPAR);
- while(parser_peek(p_parser)->type != T_RPAR) {
- grammar_expression(p_parser);
- if(parser_peek(p_parser)->type != T_RPAR)
- parser_expect(p_parser, T_COMMA);
+ size_t mark = parser_mark(p);
+ parser_expect(p, T_LPAR);
+ while(parser_peek(p)->type != T_RPAR) {
+ grammar_expression(p);
+ if(parser_peek(p)->type != T_RPAR)
+ parser_expect(p, T_COMMA);
}
- parser_expect(p_parser, T_RPAR);
- parser_reduce(p_parser, mark);
+ parser_expect(p, T_RPAR);
+ parser_reduce(p, mark);
}
-void grammar_if_stmnt(parser_t* p_parser)
+void grammar_if_stmnt(parser_t* p)
{
- size_t mark = parser_mark(p_parser);
- grammar_expression(p_parser);
- grammar_expression(p_parser);
- if (parser_accept_str(p_parser, T_ID, "else")) {
- grammar_expression(p_parser);
+ size_t mark = parser_mark(p);
+ grammar_expression(p);
+ grammar_expression(p);
+ if (parser_accept_str(p, T_ID, "else")) {
+ grammar_expression(p);
}
- parser_expect(p_parser,T_END);
- parser_reduce(p_parser, mark);
+ parser_expect(p,T_END);
+ parser_reduce(p, mark);
}
-void grammar_fn_stmnt(parser_t* p_parser)
+void grammar_fn_stmnt(parser_t* p)
{
- size_t mark1 = parser_mark(p_parser);
- parser_expect(p_parser, T_LPAR);
- size_t mark2 = parser_mark(p_parser);
- while(parser_peek(p_parser)->type != T_RPAR) {
- parser_expect(p_parser, T_ID);
- if(parser_peek(p_parser)->type != T_RPAR)
- parser_expect(p_parser, T_COMMA);
+ size_t mark1 = parser_mark(p);
+ parser_expect(p, T_LPAR);
+ size_t mark2 = parser_mark(p);
+ while(parser_peek(p)->type != T_RPAR) {
+ parser_expect(p, T_ID);
+ if(parser_peek(p)->type != T_RPAR)
+ parser_expect(p, T_COMMA);
}
- parser_expect(p_parser, T_RPAR);
- parser_reduce(p_parser, mark2);
- while(parser_peek(p_parser)->type != T_END) {
- grammar_expression(p_parser);
+ parser_expect(p, T_RPAR);
+ parser_reduce(p, mark2);
+ while(parser_peek(p)->type != T_END) {
+ grammar_expression(p);
}
- parser_expect(p_parser, T_END);
- parser_reduce(p_parser, mark1);
+ parser_expect(p, T_END);
+ parser_reduce(p, mark1);
}
+
context "type definitions" do
it "should parse a simple type definition" do
- pending "Type annotations have not been implemented yet"
- expect(ast('type foo is int;')).to eq([ ['T_ID:type', 'T_ID:foo', 'T_ID:int'] ])
+ expect(ast('type foo is int;')).to eq([ ['T_ID:type', 'T_ID:foo', 'T_ID:is', 'T_ID:int'] ])
end
it "should parse a function type definition with no args" do
- pending "Type annotations have not been implemented yet"
- expect(ast('type foo is (-> int ());')).to eq([
- ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:->', 'T_ID:int', []]] ])
+ expect(ast('type foo is int();')).to eq([
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:int', []]] ])
end
it "should parse a function type definition with one arg" do
- pending "Type annotations have not been implemented yet"
- expect(ast('type foo is (-> int (int));')).to eq([
- ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:->', 'T_ID:int', ['T_ID:int']]] ])
+ expect(ast('type foo is int(int);')).to eq([
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:int', ['T_ID:int']]] ])
end
it "should parse a function type definition with two args" do
- pending "Type annotations have not been implemented yet"
- expect(ast('type foo is (-> int (int, int));')).to eq([
- ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:->', 'T_ID:int', ['T_ID:int', 'T_ID:int']]] ])
+ expect(ast('type foo is int(int,int);')).to eq([
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:int', ['T_ID:int', 'T_ID:int']]] ])
end
it "should parse a function type definition with three args" do
- pending "Type annotations have not been implemented yet"
- expect(ast('type foo is (-> int (int, int, int));')).to eq([
- ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:->', 'T_ID:int', ['T_ID:int', 'T_ID:int', 'T_ID:int']]] ])
+ expect(ast('type foo is int(int,int,int);')).to eq([
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:int', ['T_ID:int', 'T_ID:int', 'T_ID:int']]] ])
end
it "should parse a tuple type definition with one field" do
- pending "Type annotations have not been implemented yet"
expect(ast('type foo is {int};')).to eq([
- ['T_ID:type', 'T_ID:foo', ['T_ID:tuple', 'T_ID:int']] ])
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:tuple', 'T_ID:int']] ])
end
it "should parse a tuple type definition with two fields" do
- pending "Type annotations have not been implemented yet"
expect(ast('type foo is {int,int};')).to eq([
- ['T_ID:type', 'T_ID:foo', ['T_ID:tuple', 'T_ID:int', 'T_ID:int']] ])
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:tuple', 'T_ID:int', 'T_ID:int']] ])
end
it "should parse a tuple type definition with three fields" do
- pending "Type annotations have not been implemented yet"
expect(ast('type foo is {int,int,int};')).to eq([
- ['T_ID:type', 'T_ID:foo', ['T_ID:tuple', 'T_ID:int', 'T_ID:int', 'T_ID:int']] ])
+ ['T_ID:type', 'T_ID:foo', 'T_ID:is', ['T_ID:tuple', 'T_ID:int', 'T_ID:int', 'T_ID:int']] ])
end
it "should parse a record type definition with one field" do
expect(ast('type foo is { int a, int b };')).to eq([
['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
end
context "annotations" do
- it "should parse a type annotation" do
- pending "Type annotations have not been implemented yet"
+ it "should parse a type annotation for a simple type" do
expect(ast('ann foo int;')).to eq([ ['T_ID:ann', 'T_ID:foo', 'T_ID:int'] ])
end
+ it "should parse a type annotation for a function type" do
+ expect(ast('ann foo int();')).to eq([ ['T_ID:ann', 'T_ID:foo', ['T_ID:int', []]] ])
+ end
+
+ it "should parse a type annotation for a tuple type" do
+ expect(ast('ann foo {int, int};')).to eq([ ['T_ID:ann', 'T_ID:foo', ['T_ID:tuple', 'T_ID:int', 'T_ID:int']] ])
+ end
+
it "should parse a type annotation with a generic type" do
pending "Type annotations have not been implemented yet"
expect(ast('ann foo Pair[int,int];')).to eq([