From: Mike D. Lowis Date: Wed, 14 Oct 2015 18:33:50 +0000 (-0400) Subject: Added grammar rule for if statements with optional else branch and optional then... X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=6b5be0914aad4f10dfd313b4928c3419c4e54f43;p=proto%2Fsclpl.git Added grammar rule for if statements with optional else branch and optional then keyword --- diff --git a/build.rb b/build.rb index 1863c86..9f4095d 100755 --- a/build.rb +++ b/build.rb @@ -14,7 +14,7 @@ base_env = BuildEnv.new do |env| env.build_dir('source','build/obj/source') env.build_dir('modules','build/obj/modules') # Compiler options - env["CFLAGS"] += ['-g', '-DLEAK_DETECT_LEVEL=1', '--std=c99', '-Wall', '-Wextra']#, '-Werror'] + env["CFLAGS"] += ['-DLEAK_DETECT_LEVEL=1', '--std=c99', '-Wall', '-Wextra']#, '-Werror'] env["CPPPATH"] += Dir['modules/libcds/source/**/'] + [ 'modules/libopts/source', 'source/', diff --git a/source/ast.c b/source/ast.c index 45120d7..3f92fff 100644 --- a/source/ast.c +++ b/source/ast.c @@ -203,7 +203,7 @@ AST* ifexpr_then(AST* ifexpr) void ifexpr_set_then(AST* ifexpr, AST* bthen) { - ifexpr->value.ifexpr.cond = (AST*)gc_addref(bthen); + ifexpr->value.ifexpr.bthen = (AST*)gc_addref(bthen); } AST* ifexpr_else(AST* ifexpr) @@ -213,26 +213,29 @@ AST* ifexpr_else(AST* ifexpr) void ifexpr_set_else(AST* ifexpr, AST* belse) { - ifexpr->value.ifexpr.cond = (AST*)gc_addref(belse); + ifexpr->value.ifexpr.belse = (AST*)gc_addref(belse); } AST* Block(void) { - return ast(AST_BLOCK); + AST* node = ast(AST_BLOCK); + vec_init(&(node->value.exprs)); + return node; } void block_append(AST* block, AST* expr) { + vec_push_back(&(block->value.exprs), expr); } size_t block_size(AST* block) { - return 0; + return vec_size(&(block->value.exprs)); } AST* block_get(AST* block, size_t index) { - return NULL; + return (AST*)vec_at(&(block->value.exprs), index); } @@ -258,32 +261,6 @@ AST* block_get(AST* block, size_t index) // return NULL; //} // -//AST* IfExpr(AST* cond, AST* bthen, AST* belse) -//{ -// (void)cond; -// (void)bthen; -// (void)belse; -// return NULL; -//} -// -//AST* ifexpr_condition(AST* ifexpr) -//{ -// (void)ifexpr; -// return NULL; -//} -// -//AST* ifexpr_branch_then(AST* ifexpr) -//{ -// (void)ifexpr; -// return NULL; -//} -// -//AST* ifexpr_branch_else(AST* ifexpr) -//{ -// (void)ifexpr; -// return NULL; -//} -// //AST* Func(AST* args, AST* body) //{ // (void)args; diff --git a/source/grammar.c b/source/grammar.c index 83acff6..1025e59 100644 --- a/source/grammar.c +++ b/source/grammar.c @@ -55,13 +55,13 @@ static AST* require(Parser* p) static AST* expression(Parser* p) { - if (match(p, T_ID)) { + if (accept_str(p, T_ID, "if")) { + return if_stmnt(p); + } else if (match(p, T_ID)) { return Ident(expect(p,T_ID)); //if (peek(p)->type == T_LPAR) { // arglist(p); //} - } else if (accept_str(p, T_ID, "if")) { - return if_stmnt(p); } else { return literal(p); } @@ -84,6 +84,7 @@ static AST* if_stmnt(Parser* p) { AST* ifexpr = IfExpr(); ifexpr_set_cond( ifexpr, expression(p) ); + accept_str(p, T_ID, "then"); ifexpr_set_then( ifexpr, expr_block(p) ); if (accept_str(p, T_ID, "else")) ifexpr_set_else( ifexpr, expr_block(p) ); diff --git a/source/main.c b/source/main.c index 19e945f..b6c5ad7 100644 --- a/source/main.c +++ b/source/main.c @@ -100,3 +100,4 @@ int user_main(int argc, char **argv) { } return 1; } + diff --git a/source/pprint.c b/source/pprint.c index 77cff04..53fcad2 100644 --- a/source/pprint.c +++ b/source/pprint.c @@ -116,23 +116,48 @@ static void pprint_literal(FILE* file, AST* tree, int depth) void pprint_tree(FILE* file, AST* tree, int depth) { + if (tree == NULL) + return; print_indent(file, depth); - if (tree->type <= AST_IDENT) { - pprint_literal(file, tree, depth); - } else if (tree->type == AST_REQ) { - printf("(require \"%s\")", require_name(tree)); - } else if (tree->type == AST_DEF) { - printf("(def %s ", def_name(tree)); - pprint_tree(file, def_value(tree), depth); - printf(")"); - } 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); + switch (tree->type) { + case AST_REQ: + printf("(require \"%s\")", require_name(tree)); + break; + + case AST_DEF: + printf("(def %s ", def_name(tree)); + pprint_tree(file, def_value(tree), depth); + printf(")"); + break; + + case AST_IF: + printf("(if "); + pprint_tree(file, ifexpr_cond(tree), depth); + printf(" "); + pprint_tree(file, ifexpr_then(tree), depth); + printf(" "); + pprint_tree(file, ifexpr_else(tree), depth); + printf(")"); + break; + + case AST_BLOCK: + printf("(block "); + for (size_t i = 0; i < block_size(tree); i++) { + printf(" "); + pprint_tree(file, block_get(tree, i), depth); + } + printf(")"); + break; + + case AST_ANN: + break; + + case AST_FUNC: + break; + + default: + pprint_literal(file, tree, depth); + break; } } diff --git a/source/sclpl.h b/source/sclpl.h index b13c4c1..e44782f 100644 --- a/source/sclpl.h +++ b/source/sclpl.h @@ -104,6 +104,8 @@ typedef struct AST { struct AST* args; struct AST* body; } func; + /* Code Block */ + vec_t exprs; /* String, Symbol, Identifier */ char* text; /* Character */ diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 4cc18eb..eb01dcf 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -52,6 +52,24 @@ describe "sclpl grammar" do expect{ast('require foo bar;')}.to raise_error /Error/ end end + + context "if statements" do + it "should parse an if statement with no else clause" do + expect(ast('if 123 321 end')).to eq([ + ["if", "T_INT:123", ["block", "T_INT:321"]]]) + end + + it "should parse an if statement with an optional then keyword" do + expect(ast('if 123 then 321 end')).to eq([ + ["if", "T_INT:123", ["block", "T_INT:321"]]]) + end + + it "should parse an if statement with an else clause " do + expect(ast('if 123 321 else 456 end')).to eq([ + ["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 @@ -174,17 +192,6 @@ describe "sclpl grammar" do # end # end # -# context "if statements" do -# it "should parse an if statement with no else clause" do -# expect(ast('if 123 321 end')).to eq([["T_ID:if", "T_INT:123", "T_INT:321"]]) -# end -# -# it "should parse an if statement with an else clause " do -# expect(ast('if 123 321 else 456 end')).to eq([ -# ["T_ID:if", "T_INT:123", "T_INT:321", "T_ID:else", "T_INT:456"]]) -# 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"]])