first draft of new parser
This commit is contained in:
+177
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user