#include <sclpl.h>
+
+static void ast_free(void* ptr)
+{
+}
+
+static AST* ast(ASTType type)
+{
+ AST* tree = gc_alloc(sizeof(AST), &ast_free);
+ memset(tree, 0, sizeof(AST));
+ tree->type = type;
+ return tree;
+}
+
+AST* String(char* val)
+{
+ AST* node = ast(AST_STRING);
+ node->value.text = val;
+ return node;
+}
+
+char* string_value(AST* val)
+{
+ assert(val->type == AST_STRING);
+ return val->value.text;
+}
+
+AST* Symbol(char* val)
+{
+ AST* node = ast(AST_SYMBOL);
+ node->value.text = val;
+ return node;
+}
+
+char* symbol_value(AST* val)
+{
+ assert(val->type == AST_SYMBOL);
+ return val->value.text;
+}
+
+AST* Char(uint32_t val)
+{
+ AST* node = ast(AST_CHAR);
+ node->value.character = val;
+ return node;
+}
+
+uint32_t char_value(AST* val)
+{
+ assert(val->type == AST_CHAR);
+ return val->value.character;
+}
+
+AST* Integer(intptr_t val)
+{
+ AST* node = ast(AST_INT);
+ node->value.integer = val;
+ return node;
+}
+
+intptr_t integer_value(AST* val)
+{
+ assert(val->type == AST_INT);
+ return val->value.integer;
+}
+
+AST* Float(double val)
+{
+ AST* node = ast(AST_FLOAT);
+ node->value.floating = val;
+ return node;
+}
+
+double float_value(AST* val)
+{
+ assert(val->type == AST_FLOAT);
+ return val->value.floating;
+}
+
+AST* Bool(bool val)
+{
+ AST* node = ast(AST_BOOL);
+ node->value.boolean = val;
+ return node;
+}
+
+bool bool_value(AST* val)
+{
+ assert(val->type == AST_BOOL);
+ return val->value.boolean;
+}
+
+AST* Ident(char* val)
+{
+ AST* node = ast(AST_IDENT);
+ node->value.text = val;
+ return node;
+}
+
+char* ident_value(AST* val)
+{
+ assert(val->type == AST_IDENT);
+ return val->value.text;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
AST* Require(char* name)
{
return NULL;
}
-AST* String(char* val)
-{
- (void)val;
- return NULL;
-}
-
-char* string_value(AST* val)
-{
- (void)val;
- return NULL;
-}
-
-AST* Symbol(char* val)
-{
- (void)val;
- return NULL;
-}
-
-char* symbol_value(AST* val)
-{
- (void)val;
- return NULL;
-}
-
-AST* Char(uint32_t val)
-{
- (void)val;
- return NULL;
-}
-
-uint32_t char_value(AST* val)
-{
- (void)val;
- return 0;
-}
-
-AST* Integer(intptr_t val)
-{
- (void)val;
- return NULL;
-}
-
-intptr_t integer_value(AST* val)
-{
- (void)val;
- return 0;
-}
-
-AST* Float(double val)
-{
- (void)val;
- return NULL;
-}
-
-double float_value(AST* val)
-{
- (void)val;
- return 0.0;
-}
-
-AST* Bool(bool val)
-{
- (void)val;
- return NULL;
-}
-
-bool bool_value(AST* val)
-{
- (void)val;
- return false;
-}
-
-AST* Ident(char* val)
-{
- (void)val;
- return NULL;
-}
-
-char ident_value(AST* val)
-{
- (void)val;
- return 0;
-}
-
hash_entry_t lookup = {0, 0, 0};
hash_entry_t* entry;
obj_t* obj = ((obj_t*)ptr-1);
- obj->refs++;
- if (obj->refs == 1) {
- lookup.object = obj;
- entry = hash_del(&Zero_Count_Table, &lookup);
- assert(entry != NULL);
- hash_set(&Multi_Ref_Table, entry);
+ if (ptr != NULL) {
+ obj->refs++;
+ if (obj->refs == 1) {
+ lookup.object = obj;
+ entry = hash_del(&Zero_Count_Table, &lookup);
+ assert(entry != NULL);
+ hash_set(&Multi_Ref_Table, entry);
+ }
}
return ptr;
}
hash_entry_t lookup = {0, 0, 0};
hash_entry_t* entry;
obj_t* obj = ((obj_t*)ptr-1);
- obj->refs--;
- if (obj->refs == 0) {
- lookup.object = obj;
- entry = hash_del(&Multi_Ref_Table, &lookup);
- assert(entry != NULL);
- hash_set(&Zero_Count_Table, entry);
+ if (ptr != NULL) {
+ obj->refs--;
+ if (obj->refs == 0) {
+ lookup.object = obj;
+ entry = hash_del(&Multi_Ref_Table, &lookup);
+ assert(entry != NULL);
+ hash_set(&Zero_Count_Table, entry);
+ }
}
}
*/
#include <sclpl.h>
+static AST* expression(Parser* p);
+static AST* ident(Parser* p);
+static AST* literal(Parser* p);
+
+AST* toplevel(Parser* p)
+{
+ AST* ret = NULL;
+ if (peek(p)->type != T_END_FILE) {
+ ret = expression(p);
+ }
+ //if (accept_str(p, T_ID, "require"))
+ // return require(p);
+ //else if (accept_str(p, T_ID, "type"))
+ // return type_definition(p);
+ //else if (accept_str(p, T_ID, "ann"))
+ // return type_annotation(p);
+ //else if (accept_str(p, T_ID, "def"))
+ // return definition(p);
+ //else
+ // return expression(p);
+ return ret;
+}
+
+static AST* expression(Parser* p)
+{
+ if (peek(p)->type == T_ID) {
+ return ident(p);
+ //if (peek(p)->type == T_LPAR) {
+ // arglist(p);
+ //}
+ } else {
+ return literal(p);
+ }
+
+ //if (accept(p, T_LPAR)) {
+ // //size_t mrk = mark(p);
+ // expression(p);
+ // expect(p, T_RPAR);
+ // //reduce(p, mrk);
+ //} else if (accept_str(p, T_ID, "if")) {
+ // if_stmnt(p);
+ //} else if (accept_str(p, T_ID, "fn")) {
+ // fn_stmnt(p);
+ //} else if (peek(p)->type == T_ID) {
+ // expect(p, T_ID);
+ // if (peek(p)->type == T_LPAR) {
+ // arglist(p);
+ // }
+ //} else {
+ // return literal(p);
+ //}
+}
+
+static AST* ident(Parser* p)
+{
+ Tok* tok = peek(p);
+ expect(p, T_ID);
+ return Ident(tok->value.text);
+}
+
+static AST* literal(Parser* p)
+{
+ AST* ret = NULL;
+ Tok* tok = peek(p);
+ switch (tok->type) {
+ case T_BOOL:
+ ret = Bool(tok->value.boolean);
+ accept(p, tok->type);
+ break;
+
+ case T_CHAR:
+ ret = Char(tok->value.character);
+ accept(p, tok->type);
+ break;
+
+ case T_STRING:
+ ret = String(tok->value.text);
+ accept(p, tok->type);
+ break;
+
+ case T_INT:
+ ret = Integer(tok->value.integer);
+ accept(p, tok->type);
+ break;
+
+ case T_FLOAT:
+ ret = Float(tok->value.floating);
+ accept(p, tok->type);
+ break;
+
+ default:
+ error(p, "Expected a literal");
+ }
+ return ret;
+}
+
+
+
+
+#if 0
+
static AST* require(Parser* p);
static AST* type_annotation(Parser* p);
static AST* type_definition(Parser* p);
static AST* function(Parser* p);
static AST* definition(Parser* p);
static AST* expression(Parser* p);
-static AST* literal(Parser* p);
static AST* arglist(Parser* p);
static AST* if_stmnt(Parser* p);
static AST* fn_stmnt(Parser* p);
-AST* toplevel(Parser* p)
-{
- if (accept_str(p, T_ID, "require"))
- return require(p);
- else if (accept_str(p, T_ID, "type"))
- return type_definition(p);
- else if (accept_str(p, T_ID, "ann"))
- return type_annotation(p);
- else if (accept_str(p, T_ID, "def"))
- return definition(p);
- else
- return expression(p);
-}
-
static AST* require(Parser* p)
{
//shifttok(p, T_STRING);
- expect(p, T_END);
+ //expect(p, T_END);
//reduce(Require);
return NULL;
}
static AST* type_annotation(Parser* p)
{
//shifttok(p, T_ID);
- type(p);
- expect(p, T_END);
+ //type(p);
+ //expect(p, T_END);
//reduce(Annotation);
return NULL;
}
static AST* type_definition(Parser* p)
{
- expect(p, T_ID);
- expect_str(p, T_ID, "is");
- type(p);
- expect(p, T_END);
+ //expect(p, T_ID);
+ //expect_str(p, T_ID, "is");
+ //type(p);
+ //expect(p, T_END);
return NULL;
}
static AST* type(Parser* p) {
- if (accept(p, T_LBRACE)) {
- tuple(p);
- } else {
- expect(p, T_ID);
- if (accept(p, T_LPAR)) {
- function(p);
- }
- }
+ //if (accept(p, T_LBRACE)) {
+ // tuple(p);
+ //} else {
+ // expect(p, T_ID);
+ // if (accept(p, T_LPAR)) {
+ // function(p);
+ // }
+ //}
return NULL;
}
static AST* tuple(Parser* p) {
- //size_t mrk = mark(p);
- //insert(p, T_ID, lexer_dup("tuple"));
- do {
- type(p);
- } while (accept(p, T_COMMA));
- expect(p, T_RBRACE);
- //reduce(p, mrk);
+ ////size_t mrk = mark(p);
+ ////insert(p, T_ID, lexer_dup("tuple"));
+ //do {
+ // type(p);
+ //} while (accept(p, T_COMMA));
+ //expect(p, T_RBRACE);
+ ////reduce(p, mrk);
return NULL;
}
static AST* function(Parser* p) {
- //size_t mark1 = mark(p) - 1;
- //size_t mark2 = mark(p);
- while (!accept(p, T_RPAR)) {
- type(p);
- if (T_RPAR != peek(p)->type)
- expect(p, T_COMMA);
- }
- //reduce(p, mark2);
- //reduce(p, mark1);
+ ////size_t mark1 = mark(p) - 1;
+ ////size_t mark2 = mark(p);
+ //while (!accept(p, T_RPAR)) {
+ // type(p);
+ // if (T_RPAR != peek(p)->type)
+ // expect(p, T_COMMA);
+ //}
+ ////reduce(p, mark2);
+ ////reduce(p, mark1);
return NULL;
}
static AST* definition(Parser* p)
{
- //size_t mrk = mark(p);
- expect(p,T_ID);
- if (peek(p)->type == T_LPAR) {
- //insert(p, T_ID, lexer_dup("fn"));
- fn_stmnt(p);
- } else {
- expression(p);
- expect(p,T_END);
- }
- //reduce(p, mrk);
- return NULL;
-}
-
-static AST* expression(Parser* p)
-{
- if (accept(p, T_LPAR)) {
- //size_t mrk = mark(p);
- expression(p);
- expect(p, T_RPAR);
- //reduce(p, mrk);
- } else if (accept_str(p, T_ID, "if")) {
- if_stmnt(p);
- } else if (accept_str(p, T_ID, "fn")) {
- fn_stmnt(p);
- } else if (peek(p)->type == T_ID) {
- expect(p, T_ID);
- if (peek(p)->type == T_LPAR) {
- arglist(p);
- }
- } else {
- literal(p);
- }
- return NULL;
-}
-
-static AST* literal(Parser* p)
-{
- switch (peek(p)->type) {
- case T_BOOL:
- case T_CHAR:
- case T_STRING:
- case T_INT:
- case T_FLOAT:
- accept(p, peek(p)->type);
- break;
-
- default:
- error(p, "Expected a literal");
- }
+ ////size_t mrk = mark(p);
+ //expect(p,T_ID);
+ //if (peek(p)->type == T_LPAR) {
+ // //insert(p, T_ID, lexer_dup("fn"));
+ // fn_stmnt(p);
+ //} else {
+ // expression(p);
+ // expect(p,T_END);
+ //}
+ ////reduce(p, mrk);
return NULL;
}
static AST* arglist(Parser* p)
{
- //size_t mrk = mark(p);
- expect(p, T_LPAR);
- while(peek(p)->type != T_RPAR) {
- expression(p);
- if(peek(p)->type != T_RPAR)
- expect(p, T_COMMA);
- }
- expect(p, T_RPAR);
- //reduce(p, mrk);
+ ////size_t mrk = mark(p);
+ //expect(p, T_LPAR);
+ //while(peek(p)->type != T_RPAR) {
+ // expression(p);
+ // if(peek(p)->type != T_RPAR)
+ // expect(p, T_COMMA);
+ //}
+ //expect(p, T_RPAR);
+ ////reduce(p, mrk);
return NULL;
}
static AST* if_stmnt(Parser* p)
{
- //size_t mrk = mark(p);
- expression(p);
- expression(p);
- if (accept_str(p, T_ID, "else")) {
- expression(p);
- }
- expect(p,T_END);
- //reduce(p, mrk);
+ ////size_t mrk = mark(p);
+ //expression(p);
+ //expression(p);
+ //if (accept_str(p, T_ID, "else")) {
+ // expression(p);
+ //}
+ //expect(p,T_END);
+ ////reduce(p, mrk);
return 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);
+ ////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
/* Driver Modes
*****************************************************************************/
static int emit_tokens(void) {
- Tok* token;
+ Tok* token = NULL;
Parser* ctx = parser_new(NULL, stdin);
while(NULL != (token = gettoken(ctx)))
pprint_token(stdout, token, true);
}
static int emit_tree(void) {
+ AST* tree = NULL;
+ Parser* ctx = parser_new(NULL, stdin);
+ while(NULL != (tree = toplevel(ctx)))
+ pprint_tree(stdout, tree, 0);
return 0;
}
exit(1);
}
-Tok* shifttok(Parser* parser, TokType type)
-{
- Tok* tok = NULL;
- if (peek(parser)->type == type) {
- //vec_push_back(parser->stack, parser->tok);
- parser->tok = NULL;
- } else {
- error(parser, "Unexpected token");
- }
- return tok;
-}
-
bool accept(Parser* parser, TokType type)
{
bool ret = false;
*/
#include <sclpl.h>
-#if 0
static void print_indent(FILE* file, int depth) {
for(int i = 0; i < (2 * depth); i++)
fprintf(file, "%c", ' ');
}
-#endif
static const char* token_type_to_string(TokType type) {
switch(type) {
fprintf(file, "\n");
}
+/*****************************************************************************/
-//void pprint_tree(FILE* file, AST* tree, int depth)
-//{
-// print_indent(file, depth);
-// if (tree->tag == ATOM) {
-// pprint_token(file, tree->ptr.tok, false);
-// } else {
-// fputs("(tree", file);
-// vec_t* p_vec = tree->ptr.vec;
-// for(size_t idx = 0; idx < vec_size(p_vec); idx++) {
-// pprint_tree(file, (AST*)vec_at(p_vec, idx), depth+1);
-// }
-// print_indent(file, depth);
-// fputs(")\n", file);
-// }
-//}
+static const char* tree_type_to_string(ASTType type) {
+ switch(type) {
+ case AST_STRING: return "T_STRING";
+ case AST_SYMBOL: return "T_SYMBOL";
+ case AST_IDENT: return "T_IDENT";
+ case AST_CHAR: return "T_CHAR";
+ case AST_INT: return "T_INT";
+ case AST_FLOAT: return "T_FLOAT";
+ case AST_BOOL: return "T_BOOL";
+ default: return "???";
+ }
+}
+
+static void pprint_literal(FILE* file, AST* tree, int depth)
+{
+ printf("%s:", tree_type_to_string(tree->type));
+ switch(tree->type) {
+ case AST_STRING: printf("\"%s\"", string_value(tree)); break;
+ case AST_SYMBOL: printf("%s", symbol_value(tree)); break;
+ case AST_IDENT: printf("%s", ident_value(tree)); break;
+ case AST_CHAR: printf("%c", char_value(tree)); break;
+ case AST_INT: printf("%ld", integer_value(tree)); break;
+ case AST_FLOAT: printf("%lf", float_value(tree)); break;
+ case AST_BOOL:
+ printf("%s", bool_value(tree) ? "true" : "false");
+ break;
+ default: printf("???");
+ }
+}
+
+void pprint_tree(FILE* file, AST* tree, int depth)
+{
+ print_indent(file, depth);
+ if (tree->type <= AST_IDENT) {
+ pprint_literal(file, tree, depth);
+ } else {
+ //fputs("(tree", file);
+ //vec_t* p_vec = tree->ptr.vec;
+ //for(size_t idx = 0; idx < vec_size(p_vec); idx++) {
+ // pprint_tree(file, (AST*)vec_at(p_vec, idx), depth+1);
+ //}
+ //print_indent(file, depth);
+ //fputs(")\n", file);
+ }
+}
/* Token Types
*****************************************************************************/
typedef enum {
- T_ID, T_CHAR, T_INT, T_FLOAT, T_BOOL, T_STRING, T_LBRACE, T_RBRACE, T_LBRACK,
- T_RBRACK, T_LPAR, T_RPAR, T_COMMA, T_SQUOTE, T_DQUOTE, T_END, T_END_FILE
+ T_ID, T_CHAR, T_INT, T_FLOAT, T_BOOL, T_STRING,
+ T_LBRACE, T_RBRACE, T_LBRACK,
+ T_RBRACK, T_LPAR, T_RPAR, T_COMMA, T_SQUOTE, T_DQUOTE, T_END,
+ T_END_FILE
} TokType;
typedef struct {
/* AST Types
*****************************************************************************/
typedef enum ASTType {
- AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC, AST_STRING, AST_SYMBOL,
- AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT
+ AST_STRING = 0, AST_SYMBOL, AST_CHAR, AST_INT, AST_FLOAT, AST_BOOL, AST_IDENT,
+ AST_REQ, AST_DEF, AST_ANN, AST_IF, AST_FUNC,
} ASTType;
typedef struct AST {
struct AST* args;
struct AST* body;
} func;
- /* Code Block */
- //vec_t block;
- /* String */
- char* stringval;
- /* Symbol */
- char* symbolval;
+ /* String, Symbol, Identifier */
+ char* text;
/* Character */
- uint32_t charval;
+ uint32_t character;
/* Integer */
- intptr_t intval;
+ intptr_t integer;
/* Float */
- double floatval;
+ double floating;
/* Bool */
- bool boolval;
- /* Ident */
- char* idval;
- } data;
+ bool boolean;
+ } value;
} AST;
-/* Require */
-AST* Require(char* name);
-char* require_name(AST* req);
-
-/* Definition */
-AST* Def(char* name, AST* value);
-char* def_name(AST* def);
-AST* def_value(AST* def);
-
-/* Annotation */
-AST* Ann(char* name, AST* value);
-char* ann_name(AST* def);
-AST* ann_value(AST* def);
-
-/* If Expression */
-AST* IfExpr(AST* cond, AST* bthen, AST* belse);
-AST* ifexpr_condition(AST* ifexpr);
-AST* ifexpr_branch_then(AST* ifexpr);
-AST* ifexpr_branch_else(AST* ifexpr);
-
-/* Function */
-AST* Func(AST* args, AST* body);
-AST* func_args(AST* func);
-AST* func_body(AST* func);
-
-/* Code Block */
-AST* Block(void);
-void block_append(AST* expr);
-size_t block_size(AST* block);
-AST* block_get(size_t index);
-
/* String */
AST* String(char* val);
char* string_value(AST* val);
/* Ident */
AST* Ident(char* val);
-char ident_value(AST* val);
-
+char* ident_value(AST* val);
+
+
+
+
+
+
+
+///* Require */
+//AST* Require(char* name);
+//char* require_name(AST* req);
+//
+///* Definition */
+//AST* Def(char* name, AST* value);
+//char* def_name(AST* def);
+//AST* def_value(AST* def);
+//
+///* Annotation */
+//AST* Ann(char* name, AST* value);
+//char* ann_name(AST* def);
+//AST* ann_value(AST* def);
+//
+///* If Expression */
+//AST* IfExpr(AST* cond, AST* bthen, AST* belse);
+//AST* ifexpr_condition(AST* ifexpr);
+//AST* ifexpr_branch_then(AST* ifexpr);
+//AST* ifexpr_branch_else(AST* ifexpr);
+//
+///* Function */
+//AST* Func(AST* args, AST* body);
+//AST* func_args(AST* func);
+//AST* func_body(AST* func);
+//
+///* Code Block */
+//AST* Block(void);
+//void block_append(AST* expr);
+//size_t block_size(AST* block);
+//AST* block_get(size_t index);
+//
/* Lexer and Parser Types
*****************************************************************************/
typedef struct {
void pprint_token_type(FILE* file, Tok* token);
void pprint_token_value(FILE* file, Tok* token);
void pprint_token(FILE* file, Tok* token, bool print_loc);
-//void pprint_tree(FILE* file, AST* tree, int depth);
+void pprint_tree(FILE* file, AST* tree, int depth);
#endif /* SCLPL_H */
require 'open3'
-#describe "sclpl grammar" do
+describe "sclpl grammar" do
+ context "literals" do
+ it "should parse a string" do
+ expect(ast('"foo"')).to eq(['T_STRING:"foo"'])
+ end
+
+ it "should parse a character" do
+ expect(ast('\\c')).to eq(['T_CHAR:c'])
+ end
+
+ it "should parse an integer" do
+ expect(ast('123')).to eq(['T_INT:123'])
+ end
+
+ it "should parse a float" do
+ expect(ast('123.0')).to eq(['T_FLOAT:123.000000'])
+ end
+
+ it "should parse boolean" do
+ expect(ast('true')).to eq(['T_BOOL:true'])
+ end
+
+ it "should parse an identifier" do
+ expect(ast('foo')).to eq(['T_IDENT:foo'])
+ end
+ end
+
# context "requires" do
# it "should parse a require statement" do
# expect(ast('require "foo";')).to eq([ ['T_ID:require', 'T_STRING:"foo"'] ])
# end
# end
#
-# context "literals" do
-# it "should parse a string" do
-# expect(ast('"foo"')).to eq(['T_STRING:"foo"'])
-# end
-#
-# it "should parse a character" do
-# expect(ast('\\c')).to eq(['T_CHAR:\\c'])
-# end
-#
-# it "should parse an integer" do
-# expect(ast('123')).to eq(['T_INT:123'])
-# end
-#
-# it "should parse a float" do
-# expect(ast('123.0')).to eq(['T_FLOAT:123.000000'])
-# end
-#
-# it "should parse boolean" do
-# expect(ast('true')).to eq(['T_BOOL:true'])
-# end
-#
-# it "should parse an identifier" do
-# expect(ast('foo')).to eq(['T_ID:foo'])
-# end
-# end
-#
# context "corner cases" do
# it "an unexpected terminator should error" do
# expect{ast(';')}.to raise_error /Error/
# expect{ast('\'')}.to raise_error /Error/
# end
# end
-#end
+end