From: Michael D. Lowis Date: Mon, 12 Oct 2015 01:42:08 +0000 (-0400) Subject: Parser now recognizes variable references and literals X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=259bb8f2f77abb5317f4c93f08ebed8baedf2580;p=proto%2Fsclpl.git Parser now recognizes variable references and literals --- diff --git a/source/ast.c b/source/ast.c index 2b8769d..71aeeb6 100644 --- a/source/ast.c +++ b/source/ast.c @@ -1,4 +1,130 @@ #include + +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) { @@ -117,87 +243,3 @@ AST* block_get(size_t index) 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; -} - diff --git a/source/gc.c b/source/gc.c index 24ded9a..0e1ebbc 100644 --- a/source/gc.c +++ b/source/gc.c @@ -246,12 +246,14 @@ void* gc_addref(void* ptr) 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; } @@ -261,12 +263,14 @@ void gc_delref(void* 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); + } } } diff --git a/source/grammar.c b/source/grammar.c index 3c8d7f2..41e01fc 100644 --- a/source/grammar.c +++ b/source/grammar.c @@ -6,6 +6,107 @@ */ #include +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); @@ -14,29 +115,14 @@ static AST* tuple(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; } @@ -44,8 +130,8 @@ static AST* require(Parser* p) 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; } @@ -54,147 +140,109 @@ static AST* type_annotation(Parser* p) 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 diff --git a/source/main.c b/source/main.c index 5a53e0d..1f73bd7 100644 --- a/source/main.c +++ b/source/main.c @@ -27,7 +27,7 @@ void print_usage(void) { /* 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); @@ -35,6 +35,10 @@ static int emit_tokens(void) { } 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; } diff --git a/source/parser.c b/source/parser.c index 1875ce7..374948c 100644 --- a/source/parser.c +++ b/source/parser.c @@ -66,18 +66,6 @@ void error(Parser* parser, const char* text) 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; diff --git a/source/pprint.c b/source/pprint.c index 32718ec..eb560e5 100644 --- a/source/pprint.c +++ b/source/pprint.c @@ -6,12 +6,10 @@ */ #include -#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) { @@ -84,20 +82,51 @@ void pprint_token(FILE* file, Tok* token, bool print_loc) 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); + } +} diff --git a/source/sclpl.h b/source/sclpl.h index 9ce9ff0..d7b5135 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -33,8 +33,10 @@ extern int user_main(int argc, char** argv); /* 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 { @@ -54,8 +56,8 @@ 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 { @@ -86,56 +88,19 @@ 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); @@ -162,8 +127,45 @@ bool bool_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 { @@ -199,6 +201,6 @@ AST* toplevel(Parser* p); 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 */ diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index ac424b1..8b4f947 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -1,6 +1,32 @@ 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"'] ]) @@ -188,32 +214,6 @@ require 'open3' # 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/ @@ -223,4 +223,4 @@ require 'open3' # expect{ast('\'')}.to raise_error /Error/ # end # end -#end +end