From: Michael D. Lowis Date: Sun, 28 Sep 2014 23:02:27 +0000 (-0400) Subject: tweaked tree building mechanism X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=067f90fe5fdb979e3c92b853b18870d3ee19c8ce;p=proto%2Fsclpl.git tweaked tree building mechanism --- diff --git a/Rakefile b/Rakefile index a8db856..89c7d61 100644 --- a/Rakefile +++ b/Rakefile @@ -10,7 +10,7 @@ end # Define the compiler environment base_env = BuildEnv.new(echo: :command) do |env| env.build_dir('source','build/obj/source') - env.set_toolset(:gcc) + env.set_toolset(:clang) env["CFLAGS"] += ['-DLEAK_DETECT_LEVEL=1', '--std=c99', '-Wall', '-Wextra'] #, '-Werror'] env["CPPPATH"] += ['modules/libopts/source'] + Dir['modules/libcds/source/**/'] end diff --git a/source/sclpl/grammar.c b/source/sclpl/grammar.c index 2de905b..535863d 100644 --- a/source/sclpl/grammar.c +++ b/source/sclpl/grammar.c @@ -20,12 +20,15 @@ void grammar_toplevel(parser_t* p_parser) void grammar_import(parser_t* p_parser) { + size_t mark = parser_mark(p_parser); parser_expect(p_parser, T_VAR); parser_expect(p_parser, T_END); + parser_reduce(p_parser, mark); } void grammar_definition(parser_t* p_parser) { + size_t mark = parser_mark(p_parser); parser_expect(p_parser,T_VAR); if (parser_peek(p_parser)->type == T_LPAR) { grammar_fn_stmnt(p_parser); @@ -33,6 +36,7 @@ void grammar_definition(parser_t* p_parser) grammar_expression(p_parser); parser_expect(p_parser,T_END); } + parser_reduce(p_parser, mark); } void grammar_expression(parser_t* p_parser) @@ -74,6 +78,7 @@ void grammar_literal(parser_t* p_parser) void grammar_arglist(parser_t* p_parser) { + 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); @@ -81,28 +86,35 @@ void grammar_arglist(parser_t* p_parser) parser_expect(p_parser, T_COMMA); } parser_expect(p_parser, T_RPAR); + parser_reduce(p_parser, mark); } void grammar_if_stmnt(parser_t* p_parser) { + size_t mark = parser_mark(p_parser); grammar_expression(p_parser); grammar_expression(p_parser); parser_expect_str(p_parser,T_VAR,"else"); grammar_expression(p_parser); parser_expect(p_parser,T_END); + parser_reduce(p_parser, mark); } void grammar_fn_stmnt(parser_t* p_parser) { + 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_VAR); if(parser_peek(p_parser)->type != T_RPAR) parser_expect(p_parser, 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_parser, T_END); + parser_reduce(p_parser, mark1); } diff --git a/source/sclpl/main.c b/source/sclpl/main.c index 8a05361..2dc4904 100644 --- a/source/sclpl/main.c +++ b/source/sclpl/main.c @@ -13,6 +13,28 @@ OptionConfig_T Options_Config[] = { /* SCLPL Parser *****************************************************************************/ + +void print_subtree(tree_t* p_tree, int depth); + +void print_tree(vec_t* p_vec, int depth); + +void print_subtree(tree_t* p_tree, int depth) { + for(int i = 0; i < (4 * depth); i++) printf("%c", ' '); + if (p_tree->tag == ATOM) { + puts("ATOM"); + } else { + puts("TREE"); + print_tree(p_tree->ptr.vec, depth+1); + } +} + +void print_tree(vec_t* p_vec, int depth) { + for(size_t idx = 0; idx < vec_size(p_vec); idx++) { + tree_t* p_tree = vec_at(p_vec, idx); + print_subtree(p_tree, depth); + } +} + /* TODO: * Formalize grammar for parser @@ -27,6 +49,8 @@ int main(int argc, char **argv) { parser_t* p_parser = parser_new(":> ", stdin); while(!parser_eof(p_parser)) { grammar_toplevel(p_parser); + print_tree(p_parser->p_tok_buf, 0); + vec_clear(p_parser->p_tok_buf); puts("OK."); } mem_release(p_parser); diff --git a/source/sclpl/parser.c b/source/sclpl/parser.c index 804284a..c359e02 100644 --- a/source/sclpl/parser.c +++ b/source/sclpl/parser.c @@ -26,6 +26,17 @@ parser_t* parser_new(char* p_prompt, FILE* input) return p_parser; } +static void parser_tree_free(void* p_obj) { + mem_release(((tree_t*)p_obj)->ptr.tok); +} + +static tree_t* parser_tree_new(tree_tag_t tag, void* p_obj) { + tree_t* p_tree = (tree_t*)mem_allocate(sizeof(tree_t), &parser_tree_free); + p_tree->tag = tag; + p_tree->ptr.tok = (lex_tok_t*)p_obj; + return p_tree; +} + void parser_fetch(parser_t* p_parser) { p_parser->p_tok = lexer_read(p_parser->p_lexer); @@ -55,7 +66,7 @@ bool parser_accept(parser_t* p_parser, lex_tok_type_t type) { bool ret = false; if (parser_peek(p_parser)->type == type) { - vec_push_back(p_parser->p_tok_buf, p_parser->p_tok); + vec_push_back(p_parser->p_tok_buf, parser_tree_new(ATOM, p_parser->p_tok)); p_parser->p_tok = NULL; ret = true; } @@ -66,7 +77,7 @@ bool parser_accept_str(parser_t* p_parser, lex_tok_type_t type, const char* p_te { bool ret = false; if ((parser_peek(p_parser)->type == type) && (0 == strcmp((char*)(p_parser->p_tok->value), p_text))) { - vec_push_back(p_parser->p_tok_buf, p_parser->p_tok); + vec_push_back(p_parser->p_tok_buf, parser_tree_new(ATOM, p_parser->p_tok)); p_parser->p_tok = NULL; ret = true; } @@ -94,3 +105,22 @@ bool parser_expect_str(parser_t* p_parser, lex_tok_type_t type, const char* p_te } return ret; } + +size_t parser_mark(parser_t* p_parser) +{ + return (vec_size(p_parser->p_tok_buf) - 1); +} + +void parser_reduce(parser_t* p_parser, size_t mark) +{ + vec_t* p_buf = p_parser->p_tok_buf; + vec_t* p_form = vec_new(0); + for(size_t idx = mark; idx < vec_size(p_buf); idx++) { + tree_tag_t tag = ((tree_t*)vec_at(p_buf, idx))->tag; + tree_t* p_tree = parser_tree_new(tag, mem_retain(vec_at(p_buf, idx))); + vec_push_back(p_form, p_tree); + } + vec_erase(p_parser->p_tok_buf, mark, vec_size(p_parser->p_tok_buf)-1); + vec_push_back(p_parser->p_tok_buf, parser_tree_new(TREE, p_form)); +} + diff --git a/source/sclpl/parser.h b/source/sclpl/parser.h index b427d7f..5733542 100644 --- a/source/sclpl/parser.h +++ b/source/sclpl/parser.h @@ -10,6 +10,16 @@ #include "lexer.h" #include "vec.h" +typedef enum { ATOM, TREE } tree_tag_t; + +typedef struct { + tree_tag_t tag; + union { + lex_tok_t* tok; + vec_t* vec; + } ptr; +} tree_t; + typedef struct { lexer_t* p_lexer; lex_tok_t* p_tok; @@ -34,4 +44,8 @@ bool parser_expect(parser_t* p_parser, lex_tok_type_t type); bool parser_expect_str(parser_t* p_parser, lex_tok_type_t type, const char* p_text); +size_t parser_mark(parser_t* p_parser); + +void parser_reduce(parser_t* p_parser, size_t mark); + #endif /* PARSER_H */