diff --git a/src/parse2.cpp b/src/parse2.cpp new file mode 100644 index 0000000..4aa0e76 --- /dev/null +++ b/src/parse2.cpp @@ -0,0 +1,177 @@ +namespace Parser { + + + proc eat_comment_line(char* text, int* index_in_text) -> void { + // safety check if we are actually starting a comment here + if (text[*index_in_text] != ';') + return; + + // eat the comment line + do { + ++(*index_in_text); + ++parser_col; + } while (text[(*index_in_text)] != '\n' && + text[(*index_in_text)] != '\r' && + text[(*index_in_text)] != '\0'); + } + + proc eat_whitespace(char* text, int* index_in_text) -> void { + // skip whitespaces + while (text[(*index_in_text)] == ' ' || + text[(*index_in_text)] == '\t' || + text[(*index_in_text)] == '\n' || + text[(*index_in_text)] == '\r') + { + if (text[(*index_in_text)] == '\n') { + ++parser_line; + parser_col = 0; + } + ++parser_col; + ++(*index_in_text); + } + } + + proc eat_until_code(char* text, int* index_in_text) -> void { + int position_before; + do { + position_before = *index_in_text; + eat_comment_line(text, index_in_text); + eat_whitespace(text, index_in_text); + } while (position_before != *index_in_text); + } + + proc step_char(int* index_in_text) { + ++(*index_in_text); + ++parser_col; + } + + proc step_char_and_eat_until_code(char* text, int* index_in_text) { + step_char(index_in_text); + eat_until_code(text, index_in_text); + } + + proc parse_fancy_delimiter(char* text, int* index_in_text, char l_delimiter, char r_delimiter, Lisp_Object* first_elem) -> Lisp_Object* { + if (text[*index_in_text] != l_delimiter) { + create_parsing_error("a fancy cannot be parsed here"); + return nullptr; + } + + Lisp_Objcet* ret; + Lisp_Objcet* head; + try ret = Memory::create_lisp_object_pair(first_elem, Memory::nil); + head = ret; + + step_char(index_in_text); + + while (text[*index_in_text] != r_delimiter) { + eat_until_code(text, index_in_text); + Lisp_Object* element; + try element = parse_expression(text, index_in_text); + try head.value.pair.rest = Memory::create_lisp_object_pair(element, Memory::nil); + head = head.value.pair.rest; + } + + ++*index_in_text; + + return ret; + } + + proc parse_list(char* text, int* index_in_text) -> Lisp_Object* { + + if (text[*index_in_text] != '(') { + create_parsing_error("a list cannot be parsed here"); + return nullptr; + } + step_char_and_eat_until_code(); + + if (text[*index_in_text] == ')') { + return meory::nil; + } + + Lisp_Object* first_elem; + Lisp_Objcet* ret; + Lisp_Objcet* head; + + + try first_elem = parse_epression(text, index_in_text); + try ret = Memory::create_lisp_object_pair(first_elem, Memory::nil); + head = ret; + + while (text[*index_in_text] != r_delimiter) { + eat_until_code(text, index_in_text); + Lisp_Object* element; + try element = parse_expression(text, index_in_text); + try head.value.pair.rest = Memory::create_lisp_object_pair(element, Memory::nil); + head = head.value.pair.rest; + } + + + + } + + proc maybe_expand_short_form(char* text, int* index_in_text) -> Lisp_Object* { + Lisp_Object* vector_sym = Memory::get_or_create_lisp_object_symbol("vector"); + Lisp_Object* hash_map_sym = Memory::get_or_create_lisp_object_symbol("hash-map"); + + Lisp_Object* quote_sym = Memory::get_or_create_lisp_object_symbol("quote"); + Lisp_Object* quasiquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote"); + Lisp_Object* unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote"); + Lisp_Object* unquote_splicing_sym = Memory::get_or_create_lisp_object_symbol("unquote-splicing"); + + Lisp_Object* ret; + Lisp_Object* expr; + + switch (text[*index_in_text]) { + case '\'': { + // quote + step_char_and_eat_until_code(text, index_in_text); + expr = parse_expresion(text, index_in_text); + try ret = Memory::create_lisp_object_pair(quote_sym, expr); + } break; + case '`': { + // quasiquote + step_char_and_eat_until_code(text, index_in_text); + expr = parse_expresion(text, index_in_text); + try ret = Memory::create_lisp_object_pair(quasiquote_sym, expr); + } break; + case ',': { + if (text[*index_in_text+1] == '@') { + // unquote-splicing + step_char(text, index_in_text); + step_char_and_eat_until_code(itext, index_in_text); + expr = parse_expresion(text, index_in_text); + try ret = Memory::create_lisp_object_pair(unquote_splicing_sym, expr); + } else { + // unquote + expr = parse_expresion(text, index_in_text); + try ret = Memory::create_lisp_object_pair(unquote_sym, expr); + step_char_and_eat_until_code(text, index_in_text); + } + } break; + case '[': { + // vector + try ret = parse_fancy_delimiter(text, index_in_text, '[', ']', vector_sym); + } break; + case '{': { + // hashmap + try ret = parse_fancy_delimiter(text, index_in_text, '{', '}', hash_map_sym); + try parse_hash_map(text, index_in_text); + } break; + default: break; + } + + return ret; + } + + proc parse_expression(char* text, int* index_in_text) -> Lisp_Object* { + Lisp_Object* ret; + try ret = maybe_expand_short_form(text, index_in_text); + if (ret) + return ret; + + if (text[*index_in_text] == '(') { + try ret = parse_list(text, index_in_text); + } + + } +}