cleanup
This commit is contained in:
+225
-343
@@ -4,39 +4,6 @@ namespace Parser {
|
||||
int parser_line;
|
||||
int parser_col;
|
||||
|
||||
proc maybe_expand_reader_macro() -> Lisp_Object* {
|
||||
// static Lisp_Object* quote_sym = Memory::get_or_create_lisp_object_symbol("quote");
|
||||
// static Lisp_Object* qquote_sym = Memory::get_or_create_lisp_object_symbol("quasiquote");
|
||||
// static Lisp_Object* unquote_sym = Memory::get_or_create_lisp_object_symbol("unquote");
|
||||
// static Lisp_Object* us_sym = Memory::get_or_create_lisp_object_symbol("unquote-splicing");
|
||||
|
||||
// if (text[*index_in_text] == '\'') {
|
||||
// *index_in_text++;
|
||||
// return quote_sym;
|
||||
// }
|
||||
// if (text[*index_in_text] == '`') {
|
||||
// *index_in_text++;
|
||||
// return qquote_sym;
|
||||
// }
|
||||
// if (text[*index_in_text] == ',') {
|
||||
// *index_in_text++;
|
||||
// return unquote_sym;
|
||||
// }
|
||||
// if (text[*index_in_text] == ',' && text[*index_in_text] == '@') {
|
||||
// *index_in_text += 2;
|
||||
// return us_sym;
|
||||
// }
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
proc inject_scl(Lisp_Object* lo) -> void {
|
||||
lo->sourceCodeLocation = (Source_Code_Location*)malloc(sizeof(Source_Code_Location));
|
||||
lo->sourceCodeLocation->file = parser_file;
|
||||
lo->sourceCodeLocation->line = parser_line;
|
||||
lo->sourceCodeLocation->column = parser_col;
|
||||
}
|
||||
|
||||
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] != ';')
|
||||
@@ -51,13 +18,8 @@ namespace Parser {
|
||||
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')
|
||||
{
|
||||
proc step_char(char* text, int* index_in_text, int steps = 1) {
|
||||
for (int i = 0; i < steps; ++i) {
|
||||
if (text[(*index_in_text)] == '\n') {
|
||||
++parser_line;
|
||||
parser_col = 0;
|
||||
@@ -67,7 +29,19 @@ namespace Parser {
|
||||
}
|
||||
}
|
||||
|
||||
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')
|
||||
{
|
||||
step_char(text, index_in_text);
|
||||
}
|
||||
}
|
||||
|
||||
proc eat_until_code(char* text, int* index_in_text) -> void {
|
||||
profile_this();
|
||||
int position_before;
|
||||
do {
|
||||
position_before = *index_in_text;
|
||||
@@ -76,11 +50,48 @@ namespace Parser {
|
||||
} while (position_before != *index_in_text);
|
||||
}
|
||||
|
||||
proc read_atom(char* text, int* index_in_text) -> String* {
|
||||
proc step_char_and_eat_until_code(char* text, int* index_in_text) {
|
||||
step_char(text, 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* {
|
||||
profile_this();
|
||||
if (text[*index_in_text] != l_delimiter) {
|
||||
create_parsing_error("a fancy cannot be parsed here");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Lisp_Object* ret;
|
||||
Lisp_Object* head;
|
||||
try ret = Memory::create_lisp_object_pair(first_elem, Memory::nil);
|
||||
head = ret;
|
||||
|
||||
step_char(text, index_in_text);
|
||||
|
||||
eat_until_code(text, index_in_text);
|
||||
while (text[*index_in_text] != r_delimiter) {
|
||||
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;
|
||||
eat_until_code(text, index_in_text);
|
||||
}
|
||||
|
||||
step_char(text, index_in_text);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc get_atom_text_length(char* text, int* index_in_text) -> int {
|
||||
int atom_length = 0;
|
||||
while (text[*index_in_text+atom_length] != ' ' &&
|
||||
text[*index_in_text+atom_length] != ')' &&
|
||||
text[*index_in_text+atom_length] != '(' &&
|
||||
text[*index_in_text+atom_length] != '[' &&
|
||||
text[*index_in_text+atom_length] != ']' &&
|
||||
text[*index_in_text+atom_length] != '{' &&
|
||||
text[*index_in_text+atom_length] != '}' &&
|
||||
text[*index_in_text+atom_length] != '\0' &&
|
||||
text[*index_in_text+atom_length] != '\n' &&
|
||||
text[*index_in_text+atom_length] != '\r' &&
|
||||
@@ -88,79 +99,64 @@ namespace Parser {
|
||||
{
|
||||
++atom_length;
|
||||
}
|
||||
|
||||
// let's mark the end of the atom there quickly, so the string can
|
||||
// be copied from there easily and then put the char that was
|
||||
// before there back
|
||||
char before = text[*index_in_text+atom_length];
|
||||
text[*index_in_text+atom_length] = '\0';
|
||||
|
||||
// get the atom
|
||||
String* ret = Memory::create_string("", atom_length);
|
||||
strcpy(&ret->data, text+(*index_in_text));
|
||||
|
||||
// restore the original string
|
||||
text[*index_in_text+atom_length] = before;
|
||||
|
||||
// update the index to point to the character after the atom
|
||||
// ended
|
||||
*index_in_text += atom_length;
|
||||
parser_col += atom_length;
|
||||
|
||||
return ret;
|
||||
return atom_length;
|
||||
}
|
||||
|
||||
proc parse_number(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
double number;
|
||||
// TODO(Felix): parse the number direcrly from the string and
|
||||
// dont create a String first
|
||||
String* str_number = read_atom(text, index_in_text);
|
||||
sscanf(Memory::get_c_str(str_number), "%lf", &number);
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_number(number);
|
||||
try ret = Memory::create_lisp_object(0.0);
|
||||
|
||||
sscanf(text+*index_in_text, "%lf", &ret->value.number);
|
||||
|
||||
int atom_length = get_atom_text_length(text, index_in_text);
|
||||
step_char(text, index_in_text, atom_length);
|
||||
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_keyword(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
// we are now on the colon
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
String* str_keyword = read_atom(text, index_in_text);
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::get_or_create_lisp_object_keyword(str_keyword);
|
||||
proc parse_symbol_or_keyword(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
bool keyword = false;
|
||||
if (text[*index_in_text] == ':') {
|
||||
keyword = true;
|
||||
step_char(text, index_in_text);
|
||||
}
|
||||
|
||||
int atom_length = get_atom_text_length(text, index_in_text);
|
||||
char orig = text[*index_in_text+atom_length];
|
||||
text[*index_in_text+atom_length] = '\0';
|
||||
|
||||
|
||||
String* str_keyword;
|
||||
Lisp_Object* ret;
|
||||
try str_keyword = Memory::create_string("", atom_length);
|
||||
strcpy(&str_keyword->data, text+*index_in_text);
|
||||
|
||||
if (keyword) {
|
||||
try ret = Memory::get_keyword(str_keyword);
|
||||
} else {
|
||||
try ret = Memory::get_symbol(str_keyword);
|
||||
}
|
||||
|
||||
|
||||
text[*index_in_text+atom_length] = orig;
|
||||
step_char(text, index_in_text, atom_length);
|
||||
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_symbol(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
// we are now at the first char of the symbol
|
||||
String* str_symbol = read_atom(text, index_in_text);
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::get_or_create_lisp_object_symbol(str_symbol);
|
||||
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_string(char* text, int* index_in_text) -> Lisp_Object*{
|
||||
proc parse_string(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
// the first character is the '"'
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
step_char(text, index_in_text);
|
||||
|
||||
// now we are at the first letter, if this is the closing '"' then
|
||||
// it's easy
|
||||
if (text[*index_in_text] == '"') {
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_string(
|
||||
Memory::create_string("", 0));
|
||||
try ret = Memory::create_lisp_object(Memory::create_string("", 0));
|
||||
// inject_scl(ret);
|
||||
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += 1;
|
||||
++parser_col;
|
||||
step_char(text, index_in_text);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -190,40 +186,24 @@ namespace Parser {
|
||||
|
||||
String* string = Memory::create_string("", new_len);
|
||||
|
||||
// TODO(Felix): manually copy to parse control sequences
|
||||
// correctly without the need to unescape the string, also
|
||||
// better for keeping track of the encountered new lines and
|
||||
// characters since last new line so we can update the parser
|
||||
// location more easily
|
||||
strcpy(&string->data, text+(*index_in_text));
|
||||
// printf("------ %s\n", &string->data);
|
||||
|
||||
text[*index_in_text+string_length] = '"';
|
||||
|
||||
// plus one because we want to go after the quotes
|
||||
*index_in_text += string_length +1;
|
||||
|
||||
// NOTE(Felix): this only has to be done until we manually
|
||||
// copy the string and we can do some bookeeping:
|
||||
/* recalculate the parser cursors position: */
|
||||
/* new col = (count chars since last \n) + 1 */
|
||||
for (int i = 0; i < string->length; ++i) {
|
||||
if (*((&string->data)+i) == '\n') {
|
||||
++parser_line;
|
||||
parser_col = 0;
|
||||
} else {
|
||||
++parser_col;
|
||||
}
|
||||
}
|
||||
step_char(text, index_in_text, string_length+1);
|
||||
|
||||
Lisp_Object* ret;
|
||||
try ret = Memory::create_lisp_object_string(string);
|
||||
try ret = Memory::create_lisp_object(string);
|
||||
|
||||
// inject_scl(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_atom(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
profile_this();
|
||||
Lisp_Object* ret;
|
||||
// numbers
|
||||
if ((text[*index_in_text] <= 57 && // if number
|
||||
text[*index_in_text] >= 48)
|
||||
@@ -238,137 +218,143 @@ namespace Parser {
|
||||
&&
|
||||
(text[*index_in_text +1] <= 57 &&
|
||||
text[*index_in_text +1] >= 48)))
|
||||
return parse_number(text, index_in_text);
|
||||
|
||||
// keywords
|
||||
if (text[*index_in_text] == ':')
|
||||
return parse_keyword(text, index_in_text);
|
||||
|
||||
// strings
|
||||
if (text[*index_in_text] == '"')
|
||||
return parse_string(text, index_in_text);
|
||||
|
||||
return parse_symbol(text, index_in_text);
|
||||
}
|
||||
|
||||
proc parse_expression(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
|
||||
// if it is quoted
|
||||
// TODO(Felix): This looks totally broken..
|
||||
if (text[*index_in_text] == '\'' ||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == '@' ||
|
||||
text[*index_in_text] == ',')
|
||||
{
|
||||
char quoteType = text[*index_in_text];
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
Lisp_Object* result;
|
||||
if (text[*index_in_text] == '(' ||
|
||||
text[*index_in_text] == '\'' ||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == '@' ||
|
||||
text[*index_in_text] == ',')
|
||||
{
|
||||
try result = parse_expression(text, index_in_text);
|
||||
} else {
|
||||
try result = parse_atom(text, index_in_text);
|
||||
}
|
||||
|
||||
Lisp_Object* ret = nullptr;
|
||||
if (quoteType == '\'')
|
||||
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("quote"), result);
|
||||
else if (quoteType == '`')
|
||||
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("quasiquote"), result);
|
||||
else if (quoteType == ',')
|
||||
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("unquote"), result);
|
||||
else if (quoteType == '@') {
|
||||
try ret = Memory::create_list(Memory::get_or_create_lisp_object_symbol("unquote-splicing"), result);
|
||||
}
|
||||
|
||||
// if (ret && ret != Memory::nil && ret != Memory::t)
|
||||
// inject_scl(ret);
|
||||
|
||||
return ret;
|
||||
try ret = parse_number(text, index_in_text);
|
||||
}
|
||||
|
||||
else if (text[*index_in_text] == '"')
|
||||
try ret = parse_string(text, index_in_text);
|
||||
else
|
||||
try ret = parse_symbol_or_keyword(text, index_in_text);
|
||||
|
||||
// if it is not quoted
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
return ret;
|
||||
}
|
||||
|
||||
eat_whitespace(text, index_in_text);
|
||||
|
||||
// if there was actually nothing in the list, we define here,
|
||||
// that that means nil
|
||||
if (text[(*index_in_text)] == ')') {
|
||||
++(*index_in_text);
|
||||
++parser_col;
|
||||
|
||||
proc parse_list(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
profile_this();
|
||||
if (text[*index_in_text] != '(') {
|
||||
create_parsing_error("a list cannot be parsed here");
|
||||
return nullptr;
|
||||
}
|
||||
step_char_and_eat_until_code(text, index_in_text);
|
||||
|
||||
if (text[*index_in_text] == ')') {
|
||||
step_char(text, index_in_text);
|
||||
return Memory::nil;
|
||||
}
|
||||
|
||||
// okay there is something
|
||||
Lisp_Object* first_elem;
|
||||
Lisp_Object* ret;
|
||||
Lisp_Object* head;
|
||||
try head = Memory::create_lisp_object();
|
||||
Memory::set_type(head, Lisp_Object_Type::Pair);
|
||||
// head->value.pair = new(Pair);
|
||||
Lisp_Object* expression = head;
|
||||
|
||||
while (true) {
|
||||
// inject_scl(head);
|
||||
if (text[*index_in_text] == '(' ||
|
||||
text[*index_in_text] == '\''||
|
||||
text[*index_in_text] == '`' ||
|
||||
text[*index_in_text] == '@' ||
|
||||
text[*index_in_text] == ',')
|
||||
|
||||
try first_elem = parse_expression(text, index_in_text);
|
||||
try ret = Memory::create_lisp_object_pair(first_elem, Memory::nil);
|
||||
head = ret;
|
||||
|
||||
eat_until_code(text, index_in_text);
|
||||
while (text[*index_in_text] != ')') {
|
||||
Lisp_Object* element;
|
||||
|
||||
if (text[*index_in_text+0] == '.' &&
|
||||
text[*index_in_text+1] == ' ')
|
||||
{
|
||||
try head->value.pair.first = parse_expression(text, index_in_text);
|
||||
} else {
|
||||
try head->value.pair.first = parse_atom(text, index_in_text);
|
||||
step_char(text, index_in_text, 2);
|
||||
try element = parse_expression(text, index_in_text);
|
||||
head->value.pair.rest = element;
|
||||
|
||||
eat_until_code(text, index_in_text);
|
||||
if (text[*index_in_text] != ')') {
|
||||
create_parsing_error("expected the list to end after the dotted end.");
|
||||
return nullptr;
|
||||
}
|
||||
step_char(text, index_in_text);
|
||||
return ret;
|
||||
}
|
||||
|
||||
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;
|
||||
eat_until_code(text, index_in_text);
|
||||
if (text[(*index_in_text)] == '\0') {
|
||||
create_parsing_error(
|
||||
"Unexpected EOF in %s:%d:%d",
|
||||
parser_file, parser_line, parser_col);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
if (text[(*index_in_text)] == ')') {
|
||||
head->value.pair.rest = Memory::nil;
|
||||
++parser_col;
|
||||
++(*index_in_text);
|
||||
break;
|
||||
} else if (text[(*index_in_text) ] == '.' &&
|
||||
text[(*index_in_text)+1] == ' ')
|
||||
{
|
||||
++parser_col;
|
||||
++(*index_in_text);
|
||||
eat_until_code(text, index_in_text);
|
||||
|
||||
if (text[(*index_in_text)] == '(')
|
||||
head->value.pair.rest = parse_expression(text, index_in_text);
|
||||
else
|
||||
head->value.pair.rest = parse_atom(text, index_in_text);
|
||||
|
||||
eat_until_code(text, index_in_text);
|
||||
|
||||
if (text[(*index_in_text)] != ')')
|
||||
create_parsing_error(
|
||||
"Expected ')' after the element after the '.' in %s:%d:%d",
|
||||
create_source_code_location(parser_file, parser_line, parser_col));
|
||||
++parser_col;
|
||||
++(*index_in_text);
|
||||
break;
|
||||
} else {
|
||||
try head->value.pair.rest = Memory::create_lisp_object_pair(Memory::nil, Memory::nil);
|
||||
head = head->value.pair.rest;
|
||||
// inject_scl(head);
|
||||
}
|
||||
}
|
||||
return expression;
|
||||
step_char(text, index_in_text);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc maybe_expand_short_form(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
profile_this();
|
||||
Lisp_Object* vector_sym = Memory::get_symbol("vector");
|
||||
Lisp_Object* hash_map_sym = Memory::get_symbol("hash-map");
|
||||
|
||||
Lisp_Object* quote_sym = Memory::get_symbol("quote");
|
||||
Lisp_Object* quasiquote_sym = Memory::get_symbol("quasiquote");
|
||||
Lisp_Object* unquote_sym = Memory::get_symbol("unquote");
|
||||
Lisp_Object* unquote_splicing_sym = Memory::get_symbol("unquote-splicing");
|
||||
|
||||
Lisp_Object* ret = nullptr;
|
||||
Lisp_Object* expr;
|
||||
|
||||
switch (text[*index_in_text]) {
|
||||
case '\'': {
|
||||
// quote
|
||||
step_char_and_eat_until_code(text, index_in_text);
|
||||
try expr = parse_expression(text, index_in_text);
|
||||
try ret = Memory::create_lisp_object_pair(expr, Memory::nil);
|
||||
try ret = Memory::create_lisp_object_pair(quote_sym, ret);
|
||||
} break;
|
||||
case '`': {
|
||||
// quasiquote
|
||||
step_char_and_eat_until_code(text, index_in_text);
|
||||
try expr = parse_expression(text, index_in_text);
|
||||
try ret = Memory::create_lisp_object_pair(expr, Memory::nil);
|
||||
try ret = Memory::create_lisp_object_pair(quasiquote_sym, ret);
|
||||
} break;
|
||||
case ',': {
|
||||
step_char_and_eat_until_code(text, index_in_text);
|
||||
if (text[*index_in_text] == '@') {
|
||||
// unquote-splicing
|
||||
step_char_and_eat_until_code(text, index_in_text);
|
||||
try expr = parse_expression(text, index_in_text);
|
||||
try ret = Memory::create_lisp_object_pair(expr, Memory::nil);
|
||||
try ret = Memory::create_lisp_object_pair(unquote_splicing_sym, ret);
|
||||
} else {
|
||||
// unquote
|
||||
try expr = parse_expression(text, index_in_text);
|
||||
try ret = Memory::create_lisp_object_pair(expr, Memory::nil);
|
||||
try ret = Memory::create_lisp_object_pair(unquote_sym, ret);
|
||||
}
|
||||
} 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);
|
||||
} break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_expression(char* text, int* index_in_text) -> Lisp_Object* {
|
||||
profile_this();
|
||||
Lisp_Object* ret;
|
||||
eat_until_code(text, index_in_text);
|
||||
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);
|
||||
} else {
|
||||
try ret = parse_atom(text, index_in_text);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_single_expression(wchar_t* text) -> Lisp_Object* {
|
||||
@@ -376,107 +362,21 @@ namespace Parser {
|
||||
defer {free(res);};
|
||||
return parse_single_expression(res);
|
||||
}
|
||||
|
||||
proc parse_single_expression(char* text) -> Lisp_Object* {
|
||||
parser_file = standard_in;
|
||||
parser_line = 1;
|
||||
parser_col = 1;
|
||||
|
||||
int index_in_text = 0;
|
||||
Lisp_Object* result;
|
||||
eat_until_code(text, &index_in_text);
|
||||
if (text[(index_in_text)] == '\0')
|
||||
return Memory::nil;
|
||||
if (text[index_in_text] == '(' ||
|
||||
text[index_in_text] == '\'' ||
|
||||
text[index_in_text] == '@' ||
|
||||
text[index_in_text] == '`' ||
|
||||
text[index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
result = parse_expression(text, &index_in_text);
|
||||
}
|
||||
}
|
||||
else
|
||||
try {
|
||||
result = parse_atom(text, &index_in_text);
|
||||
}
|
||||
eat_until_code(text, &index_in_text);
|
||||
if (text[(index_in_text)] == '\0')
|
||||
return result;
|
||||
|
||||
create_parsing_error("Trainling garbage after expression at %s:%d:%d",
|
||||
parser_file, parser_line, parser_col);
|
||||
return nullptr;
|
||||
Lisp_Object* ret;
|
||||
try ret = parse_expression(text, &index_in_text);
|
||||
return ret;
|
||||
}
|
||||
|
||||
proc parse_single_expression_or_bare_words(char* text, char* bare) -> Lisp_Object* {
|
||||
parser_file = standard_in;
|
||||
parser_line = 1;
|
||||
parser_col = 1;
|
||||
|
||||
int index_in_text = 0;
|
||||
Lisp_Object* result;
|
||||
eat_until_code(text, &index_in_text);
|
||||
if (text[(index_in_text)] == '\0')
|
||||
return Memory::nil;
|
||||
if (text[index_in_text] == '(' ||
|
||||
text[index_in_text] == '\'' ||
|
||||
text[index_in_text] == '@' ||
|
||||
text[index_in_text] == '`' ||
|
||||
text[index_in_text] == ',')
|
||||
{
|
||||
try {
|
||||
result = parse_expression(text, &index_in_text);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
// TODO(Felix): What is going on, why do we not have to
|
||||
// increase the index_in_text
|
||||
|
||||
int end_pos = index_in_text;
|
||||
while (text[end_pos] != '\n')
|
||||
++end_pos;
|
||||
|
||||
text[end_pos] = '\0';
|
||||
Lisp_Object* str;
|
||||
try str = Memory::create_lisp_object_string(
|
||||
Memory::create_string(text+index_in_text));
|
||||
text[end_pos] = '\n';
|
||||
|
||||
return Memory::create_list(Memory::get_or_create_lisp_object_symbol(bare), str);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
proc write_expanded_file(String* file_name, Array_List<Lisp_Object*>* program) -> void {
|
||||
const char* ext = ".expanded";
|
||||
char* newName = (char*)calloc(10 + file_name->length, sizeof(char));
|
||||
strcpy(newName, Memory::get_c_str(file_name));
|
||||
strcat(newName, ext);
|
||||
|
||||
FILE *f = fopen(newName, "w");
|
||||
defer {
|
||||
fclose(f);
|
||||
free(newName);
|
||||
};
|
||||
|
||||
if (f == NULL) {
|
||||
printf("Error opening .expanded file for writing!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (int i = 0; i < program->next_index; ++i) {
|
||||
// a macro will parse as nil for now, so we skip those
|
||||
if (program->data[i] == Memory::nil)
|
||||
continue;
|
||||
print(program->data[i], true, f);
|
||||
fprintf(f, "\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
proc parse_program(String* file_name, char* text) -> Array_List<Lisp_Object*>* {
|
||||
profile_this();
|
||||
parser_file = file_name;
|
||||
parser_line = 1;
|
||||
parser_col = 0;
|
||||
@@ -484,33 +384,15 @@ namespace Parser {
|
||||
Array_List<Lisp_Object*>* program = new Array_List<Lisp_Object*>;
|
||||
|
||||
int index_in_text = 0;
|
||||
Lisp_Object* parsed;
|
||||
|
||||
eat_until_code(text, &index_in_text);
|
||||
while (text[index_in_text] != '\0') {
|
||||
switch (text[index_in_text]) {
|
||||
case '(': {
|
||||
Lisp_Object* parsed;
|
||||
try_struct {
|
||||
parsed = parse_expression(text, &index_in_text);
|
||||
}
|
||||
program->append(parsed);
|
||||
} break;
|
||||
case ';':
|
||||
case ' ':
|
||||
case '\t':
|
||||
case '\n':
|
||||
case '\r': {
|
||||
eat_until_code(text, &index_in_text);
|
||||
} break;
|
||||
default:
|
||||
/* syntax error */
|
||||
create_parsing_error("Garbage in file scope at %s:%d:%d",
|
||||
parser_file, parser_line, parser_col);
|
||||
return {};
|
||||
}
|
||||
try parsed = parse_expression(text, &index_in_text);
|
||||
program->append(parsed);
|
||||
eat_until_code(text, &index_in_text);
|
||||
}
|
||||
|
||||
write_expanded_file(file_name, program);
|
||||
|
||||
return program;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user