From: Michael D. Lowis Date: Thu, 9 Oct 2014 01:43:18 +0000 (-0400) Subject: Added parser spec X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=f9434726290bd1820250882e97542f89dfd10a2d;p=proto%2Fsclpl.git Added parser spec --- diff --git a/source/sclpl/grammar.c b/source/sclpl/grammar.c index 5dd497a..a36d394 100644 --- a/source/sclpl/grammar.c +++ b/source/sclpl/grammar.c @@ -5,6 +5,7 @@ $HeadURL$ */ #include "grammar.h" +#include "lexer.h" #include "exn.h" tree_t* grammar_toplevel(parser_t* p_parser) @@ -39,6 +40,7 @@ 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) { + parser_insert(p_parser, T_VAR, lexer_dup("fn")); grammar_fn_stmnt(p_parser); } else { grammar_expression(p_parser); diff --git a/source/sclpl/lexer.c b/source/sclpl/lexer.c index dc0f6ae..19780d5 100644 --- a/source/sclpl/lexer.c +++ b/source/sclpl/lexer.c @@ -21,7 +21,6 @@ static lex_tok_t* lexer_bool(char* text); static lex_tok_t* lexer_var(char* text); static bool lexer_oneof(const char* class, char c); static bool is_float(char* text); -static char* lexer_dup(const char* p_old); static int read_radix(char ch); static void lex_tok_free(void* p_obj) { @@ -30,7 +29,7 @@ static void lex_tok_free(void* p_obj) { mem_release(p_tok->value); } -static lex_tok_t* lex_tok_new(lex_tok_type_t type, void* val) { +lex_tok_t* lex_tok_new(lex_tok_type_t type, void* val) { lex_tok_t* p_tok = (lex_tok_t*)mem_allocate(sizeof(lex_tok_t), &lex_tok_free); p_tok->type = type; p_tok->value = val; @@ -209,7 +208,7 @@ static bool is_float(char* text) { return false; } -static char* lexer_dup(const char* p_old) { +char* lexer_dup(const char* p_old) { size_t length = strlen(p_old); char* p_str = (char*)mem_allocate(length+1, NULL); memcpy(p_str, p_old, length); diff --git a/source/sclpl/lexer.h b/source/sclpl/lexer.h index 40d65fa..8e06e98 100644 --- a/source/sclpl/lexer.h +++ b/source/sclpl/lexer.h @@ -31,10 +31,14 @@ typedef struct { lexer_t* lexer_new(char* p_prompt, FILE* p_input); +lex_tok_t* lex_tok_new(lex_tok_type_t type, void* val); + lex_tok_t* lexer_read(lexer_t* p_lexer); void lexer_skipline(lexer_t* p_lexer); char* lexer_tok_type_str(lex_tok_t* p_tok); +char* lexer_dup(const char* p_old); + #endif /* LEXER_H */ diff --git a/source/sclpl/parser.c b/source/sclpl/parser.c index 804416f..5bbf9e5 100644 --- a/source/sclpl/parser.c +++ b/source/sclpl/parser.c @@ -149,3 +149,9 @@ tree_t* parser_get_tree(parser_t* p_parser) { return p_tree; } +void parser_insert(parser_t* p_parser, lex_tok_type_t type, void* value) { + lex_tok_t* p_tok = lex_tok_new(type, value); + tree_t* p_tree = parser_tree_new(ATOM, p_tok); + vec_push_back(p_parser->p_tok_buf, p_tree); +} + diff --git a/source/sclpl/parser.h b/source/sclpl/parser.h index 2dc1624..cc6d15c 100644 --- a/source/sclpl/parser.h +++ b/source/sclpl/parser.h @@ -57,4 +57,6 @@ void parser_reduce(parser_t* p_parser, size_t mark); tree_t* parser_get_tree(parser_t* p_parser); +void parser_insert(parser_t* p_parser, lex_tok_type_t type, void* value); + #endif /* PARSER_H */ diff --git a/spec/lexer_spec.rb b/spec/lexer_spec.rb index cd7b4fb..0146519 100644 --- a/spec/lexer_spec.rb +++ b/spec/lexer_spec.rb @@ -1,6 +1,6 @@ require 'open3' -def tokens(input) +def lexer(input) out, err, status = Open3.capture3('./build/bin/sclpl-test', '--tokens', :stdin_data => input) raise "Lexer command returned non-zero status" unless status.success? raise "Lexer produced error messages" unless err == "" @@ -9,7 +9,7 @@ end describe "lexer" do it "should recognize punctuation" do - expect(tokens('[](){};\'",')).to eq( + expect(lexer('[](){};\'",')).to eq( ["T_LBRACK", "T_RBRACK", "T_LPAR", "T_RPAR", "T_VAR", "T_VAR", "T_END"]) end end diff --git a/spec/parser_spec.rb b/spec/parser_spec.rb index 8b13789..1c86aff 100644 --- a/spec/parser_spec.rb +++ b/spec/parser_spec.rb @@ -1 +1,34 @@ +require 'open3' +def re_structure( token_array, offset = 0 ) + struct = [] + while( offset < token_array.length ) + if(token_array[offset] == "(") + # Multiple assignment from the array that re_structure() returns + offset, tmp_array = re_structure(token_array, offset + 1) + struct << tmp_array + elsif(token_array[offset] == ")") + break + else + struct << token_array[offset] + end + offset += 1 + end + return [offset, struct] +end + +def parser(input) + out, err, status = Open3.capture3('./build/bin/sclpl-test', '--ast', :stdin_data => input) + raise "Parser command returned non-zero status" unless status.success? + raise "Parser produced error messages" unless err == "" + out.gsub!(//,'\1') + out.gsub!(/([()])|tree/,' \1 ') + off, expr = re_structure(out.split) + expr +end + +describe "parser" do + it "should parse a definition" do + expect(parser('def foo 123;')).to eq([ ['T_VAR', 'T_VAR', 'T_INT'] ]) + end +end