Просмотр исходного кода

Error locations are somewhat working now

master
FelixBrendel 7 лет назад
Родитель
Сommit
f179eda6f1
5 измененных файлов: 82 добавлений и 33 удалений
  1. +3
    -1
      bin/test.slime
  2. +15
    -9
      src/ast.c
  3. +6
    -4
      src/helpers.c
  4. +4
    -1
      src/io.c
  5. +54
    -18
      src/parse.c

+ 3
- 1
bin/test.slime Просмотреть файл

@@ -12,4 +12,6 @@
(defun ! (n) (defun ! (n)
(if (< n 2) (if (< n 2)
1 1
(* n (! (- 1 n)))))
(* n (! (- n 1)))))

(erros "alskdj")

+ 15
- 9
src/ast.c Просмотреть файл

@@ -237,22 +237,28 @@ typedef struct {
Ast_Node_Array_List* keyword_values; Ast_Node_Array_List* keyword_values;
} Parsed_Arguments; } Parsed_Arguments;


Ast_Node* create_ast_node_nil() {
Ast_Node* create_ast_node() {
Ast_Node* node = new(Ast_Node); Ast_Node* node = new(Ast_Node);
node->sourceCodeLocation = nullptr;
return node;
}

Ast_Node* create_ast_node_nil() {
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Nil; node->type = Ast_Node_Type_Nil;
node->value.pair = nullptr; node->value.pair = nullptr;
return node; return node;
} }


Ast_Node* create_ast_node_t() { Ast_Node* create_ast_node_t() {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_T; node->type = Ast_Node_Type_T;
node->value.pair = nullptr; node->value.pair = nullptr;
return node; return node;
} }


Ast_Node* create_ast_node_number(double number) { Ast_Node* create_ast_node_number(double number) {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Number; node->type = Ast_Node_Type_Number;
node->value.number = new(Number); node->value.number = new(Number);
node->value.number->value = number; node->value.number->value = number;
@@ -260,7 +266,7 @@ Ast_Node* create_ast_node_number(double number) {
} }


Ast_Node* create_ast_node_string(char* str, int length) { Ast_Node* create_ast_node_string(char* str, int length) {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_String; node->type = Ast_Node_Type_String;
node->value.string = new(String); node->value.string = new(String);
node->value.string->value = str; node->value.string->value = str;
@@ -269,7 +275,7 @@ Ast_Node* create_ast_node_string(char* str, int length) {
} }


Ast_Node* create_ast_node_symbol(char* identifier) { Ast_Node* create_ast_node_symbol(char* identifier) {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Symbol; node->type = Ast_Node_Type_Symbol;
node->value.symbol = new(Symbol); node->value.symbol = new(Symbol);
node->value.symbol->identifier = identifier; node->value.symbol->identifier = identifier;
@@ -277,7 +283,7 @@ Ast_Node* create_ast_node_symbol(char* identifier) {
} }


Ast_Node* create_ast_node_keyword(char* keyword) { Ast_Node* create_ast_node_keyword(char* keyword) {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Keyword; node->type = Ast_Node_Type_Keyword;
node->value.keyword = new(Keyword); node->value.keyword = new(Keyword);
node->value.keyword->identifier = keyword; node->value.keyword->identifier = keyword;
@@ -326,7 +332,7 @@ Ast_Node* create_ast_node_built_in_function(char* name) {
else if (string_equal(name, "while")) type = Built_In_While; else if (string_equal(name, "while")) type = Built_In_While;
else return nullptr; else return nullptr;


Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Built_In_Function; node->type = Ast_Node_Type_Built_In_Function;
node->value.built_in_function = new(Built_In_Function); node->value.built_in_function = new(Built_In_Function);
node->value.built_in_function->type = type; node->value.built_in_function->type = type;
@@ -334,7 +340,7 @@ Ast_Node* create_ast_node_built_in_function(char* name) {
} }


Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) { Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) {
Ast_Node* node = new(Ast_Node);
Ast_Node* node = create_ast_node();
node->type = Ast_Node_Type_Pair; node->type = Ast_Node_Type_Pair;
node->value.pair = new(Pair); node->value.pair = new(Pair);
node->value.pair->first = first; node->value.pair->first = first;
@@ -343,7 +349,7 @@ Ast_Node* create_ast_node_pair(Ast_Node* first, Ast_Node* rest) {
} }


Ast_Node* copy_ast_node(Ast_Node* n) { Ast_Node* copy_ast_node(Ast_Node* n) {
Ast_Node* target = new(Ast_Node);
Ast_Node* target = create_ast_node();
*target = *n; *target = *n;
return target; return target;
} }

+ 6
- 4
src/helpers.c Просмотреть файл

@@ -227,14 +227,16 @@ char* read_line() {
typedef struct { typedef struct {
char* file; char* file;
int line; int line;
int column;
} Source_Code_Location; } Source_Code_Location;


Source_Code_Location* create_source_code_location(char* file, int line) {
Source_Code_Location* create_source_code_location(char* file, int line, int col) {
if (!file) if (!file)
return nullptr; return nullptr;
Source_Code_Location* ret = new(Source_Code_Location); Source_Code_Location* ret = new(Source_Code_Location);
ret->file = file;
ret->line = line;
ret->file = file;
ret->line = line;
ret->column = col;
return ret; return ret;
} }

+ 4
- 1
src/io.c Просмотреть файл

@@ -98,7 +98,10 @@ void print(Ast_Node* node) {


void print_error_location() { void print_error_location() {
if (error->location) { if (error->location) {
printf("%s: %d", error->location->file, error->location->line);
printf("%s (line %d, position %d)",
error->location->file,
error->location->line,
error->location->column);
} else { } else {
printf("no source code location avaliable"); printf("no source code location avaliable");
} }


+ 54
- 18
src/parse.c Просмотреть файл

@@ -1,5 +1,13 @@
char* parser_file; char* parser_file;
int parser_line; int parser_line;
int parser_col;

#define inject_scl(_ret) \
ret->sourceCodeLocation = new(Source_Code_Location); \
ret->sourceCodeLocation->file = parser_file; \
ret->sourceCodeLocation->line = parser_line; \
ret->sourceCodeLocation->column = parser_col



// TODO(Felix): use the array list macro here? // TODO(Felix): use the array list macro here?
Ast_Node_Array_List* create_Ast_Node_Array_List(int initial_length) { Ast_Node_Array_List* create_Ast_Node_Array_List(int initial_length) {
@@ -30,13 +38,10 @@ void eat_comment_line(char* text, int* index_in_text) {
// eat the comment line // eat the comment line
do { do {
++(*index_in_text); ++(*index_in_text);
++parser_col;
} while (text[(*index_in_text)] != '\n' && } while (text[(*index_in_text)] != '\n' &&
text[(*index_in_text)] != '\r' && text[(*index_in_text)] != '\r' &&
text[(*index_in_text)] != '\0'); text[(*index_in_text)] != '\0');

if (text[(*index_in_text)] == '\n') {
++parser_line;
}
} }


void eat_whitespace(char* text, int* index_in_text) { void eat_whitespace(char* text, int* index_in_text) {
@@ -44,12 +49,16 @@ void eat_whitespace(char* text, int* index_in_text) {
while (text[(*index_in_text)] == ' ' || while (text[(*index_in_text)] == ' ' ||
text[(*index_in_text)] == '\t' || text[(*index_in_text)] == '\t' ||
text[(*index_in_text)] == '\n' || text[(*index_in_text)] == '\n' ||
text[(*index_in_text)] == '\r') {
text[(*index_in_text)] == '\r')
{
if (text[(*index_in_text)] == '\n') {
++parser_line;
parser_col = 0;
}
++parser_col;
++(*index_in_text); ++(*index_in_text);
} }
if (text[(*index_in_text)] == '\n') {
++parser_line;
}

} }


void eat_until_code(char* text, int* index_in_text) { void eat_until_code(char* text, int* index_in_text) {
@@ -98,33 +107,43 @@ Ast_Node* parse_number(char* text, int* index_in_text) {
double number; double number;
char* str_number = read_atom(text, index_in_text); char* str_number = read_atom(text, index_in_text);
sscanf(str_number, "%lf", &number); sscanf(str_number, "%lf", &number);
return create_ast_node_number(number);
Ast_Node* ret = create_ast_node_number(number);
inject_scl(ret);
return ret;
} }




Ast_Node* parse_keyword(char* text, int* index_in_text) { Ast_Node* parse_keyword(char* text, int* index_in_text) {
// we are now on the colon // we are now on the colon
++(*index_in_text); ++(*index_in_text);
++parser_col;
char* str_keyword = read_atom(text, index_in_text); char* str_keyword = read_atom(text, index_in_text);
return create_ast_node_keyword(str_keyword);
Ast_Node* ret = create_ast_node_keyword(str_keyword);
inject_scl(ret);
return ret;
} }


Ast_Node* parse_symbol(char* text, int* index_in_text) { Ast_Node* parse_symbol(char* text, int* index_in_text) {
// we are now at the first char of the symbol // we are now at the first char of the symbol
char* str_symbol = read_atom(text, index_in_text); char* str_symbol = read_atom(text, index_in_text);
return create_ast_node_symbol(str_symbol);
Ast_Node* ret = create_ast_node_symbol(str_symbol);
inject_scl(ret);
return ret;
} }


Ast_Node* parse_string(char* text, int* index_in_text) { Ast_Node* parse_string(char* text, int* index_in_text) {
// the first character is the '"' // the first character is the '"'
++(*index_in_text); ++(*index_in_text);
++parser_col;


// now we are at the first letter, if this is the closing '"' then // now we are at the first letter, if this is the closing '"' then
// it's easy // it's easy
if (text[*index_in_text] == '"') { if (text[*index_in_text] == '"') {
char* str = new(char); char* str = new(char);
*str = '\0'; *str = '\0';
return create_ast_node_string(str, 0);
Ast_Node* ret = create_ast_node_string(str, 0);
inject_scl(ret);
return ret;
} }


// okay so the first letter was not actually closing the string... // okay so the first letter was not actually closing the string...
@@ -143,7 +162,7 @@ Ast_Node* parse_string(char* text, int* index_in_text) {
if (!unescape_string(text+(*index_in_text))) { if (!unescape_string(text+(*index_in_text))) {
create_error( create_error(
Error_Type_Unknown_Error, Error_Type_Unknown_Error,
create_source_code_location(parser_file, parser_line));
create_source_code_location(parser_file, parser_line, parser_col));
return nullptr; return nullptr;
} }
strcpy(string, text+(*index_in_text)); strcpy(string, text+(*index_in_text));
@@ -159,7 +178,9 @@ Ast_Node* parse_string(char* text, int* index_in_text) {
*index_in_text += string_length +1; // plus one because we want to *index_in_text += string_length +1; // plus one because we want to
// go after the quotes // go after the quotes


return create_ast_node_string(string, string_length);
Ast_Node* ret = create_ast_node_string(string, string_length);
inject_scl(ret);
return ret;
} }


Ast_Node* parse_atom(char* text, int* index_in_text) { Ast_Node* parse_atom(char* text, int* index_in_text) {
@@ -193,6 +214,7 @@ Ast_Node* parse_atom(char* text, int* index_in_text) {
Ast_Node* parse_expression(char* text, int* index_in_text) { Ast_Node* parse_expression(char* text, int* index_in_text) {
if (text[*index_in_text] == '\'') { if (text[*index_in_text] == '\'') {
++(*index_in_text); ++(*index_in_text);
++parser_col;
Ast_Node* result; Ast_Node* result;
if (text[*index_in_text] == '(' || text[*index_in_text] == '\'' ) { if (text[*index_in_text] == '(' || text[*index_in_text] == '\'' ) {
try { try {
@@ -208,12 +230,14 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
create_ast_node_pair(result, create_ast_node_nil())); create_ast_node_pair(result, create_ast_node_nil()));
} }
++(*index_in_text); ++(*index_in_text);
++parser_col;


eat_whitespace(text, index_in_text); eat_whitespace(text, index_in_text);


// if there was actually nothing in the list, return nil // if there was actually nothing in the list, return nil
if (text[(*index_in_text)] == ')') { if (text[(*index_in_text)] == ')') {
++(*index_in_text); ++(*index_in_text);
++parser_col;
return create_ast_node_nil(); return create_ast_node_nil();
} }


@@ -236,16 +260,18 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {


eat_until_code(text, index_in_text); eat_until_code(text, index_in_text);
if (text[(*index_in_text)] == '\0') { if (text[(*index_in_text)] == '\0') {
create_error(Error_Type_Unexpected_Eof, create_source_code_location(parser_file, parser_line));
create_error(Error_Type_Unexpected_Eof, create_source_code_location(parser_file, parser_line, parser_col));
return nullptr; return nullptr;
} }




if (text[(*index_in_text)] == ')') { if (text[(*index_in_text)] == ')') {
head->value.pair->rest = create_ast_node_nil(); head->value.pair->rest = create_ast_node_nil();
++parser_col;
++(*index_in_text); ++(*index_in_text);
break; break;
} else if (text[(*index_in_text)] == '.') { } else if (text[(*index_in_text)] == '.') {
++parser_col;
++(*index_in_text); ++(*index_in_text);
eat_until_code(text, index_in_text); eat_until_code(text, index_in_text);


@@ -257,7 +283,8 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
eat_until_code(text, index_in_text); eat_until_code(text, index_in_text);


if (text[(*index_in_text)] != ')') if (text[(*index_in_text)] != ')')
create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line));
create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line, parser_col));
++parser_col;
++(*index_in_text); ++(*index_in_text);
break; break;
} else { } else {
@@ -269,6 +296,10 @@ Ast_Node* parse_expression(char* text, int* index_in_text) {
} }


Ast_Node* parse_single_expression(char* text) { Ast_Node* parse_single_expression(char* text) {
parser_file = "stdin";
parser_line = 1;
parser_col = 1;

int index_in_text = 0; int index_in_text = 0;
Ast_Node* result; Ast_Node* result;
eat_until_code(text, &index_in_text); eat_until_code(text, &index_in_text);
@@ -283,13 +314,16 @@ Ast_Node* parse_single_expression(char* text) {
eat_until_code(text, &index_in_text); eat_until_code(text, &index_in_text);
if (text[(index_in_text)] == '\0') if (text[(index_in_text)] == '\0')
return result; return result;
create_error(Error_Type_Trailing_Garbage, create_source_code_location(parser_file, parser_line));
create_error(Error_Type_Trailing_Garbage, create_source_code_location(parser_file, parser_line, parser_col));
return nullptr; return nullptr;
} }


Ast_Node_Array_List* parse_program(char* file_name, char* text) { Ast_Node_Array_List* parse_program(char* file_name, char* text) {
parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1); parser_file = (char*)malloc(strlen(file_name) * sizeof(char) + 1);
strcpy(parser_file, file_name); strcpy(parser_file, file_name);
parser_line = 1;
parser_col = 0;

Ast_Node_Array_List* program = create_Ast_Node_Array_List(16); Ast_Node_Array_List* program = create_Ast_Node_Array_List(16);


int index_in_text = 0; int index_in_text = 0;
@@ -312,9 +346,11 @@ Ast_Node_Array_List* parse_program(char* file_name, char* text) {
} break; } break;
default: default:
/* syntax error */ /* syntax error */
create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line));
create_error(Error_Type_Syntax_Error, create_source_code_location(parser_file, parser_line, parser_col));
return nullptr; return nullptr;
} }
} }
return program; return program;
} }

#undef inject_scl

Загрузка…
Отмена
Сохранить