Compare commits

..

No commits in common. "9bc67d4268d0e94327523670cd133803d0a145a3" and "68c114ce1d022bbec450dcdd85ed60e24cd04aba" have entirely different histories.

5 changed files with 70 additions and 141 deletions

View File

@ -35,25 +35,15 @@ typedef struct {
size_t line; size_t line;
} Lexer; } Lexer;
typedef struct TokenResult { typedef struct {
SyncResultType type; SyncResultType type;
union { union {
Token result; Token result;
SyncError error; SyncError error;
}; };
struct TokenResult* next;
} TokenResult; } TokenResult;
typedef struct {
SyncResultType type;
union {
struct TokenResult* result;
GeneralError error;
};
} LexerResult;
void lexer_init(Lexer* lexer, const char* filename, const char* source); void lexer_init(Lexer* lexer, const char* filename, const char* source);
LexerResult lexical_analysis(Lexer* lexer); TokenResult lexer_next(Lexer* lexer);
void clean_token_result(TokenResult* head);
#endif // SYNC_LEXER_H #endif // SYNC_LEXER_H

View File

@ -3,11 +3,6 @@
#include <stddef.h> #include <stddef.h>
typedef struct {
const char *message;
int code;
} GeneralError;
typedef struct { typedef struct {
const char *filename; const char *filename;
size_t line; size_t line;
@ -17,9 +12,9 @@ typedef struct {
} FileInfo; } FileInfo;
typedef enum { typedef enum {
SYNC_LEXICAL_ERROR, SYNC_LEXER_ERROR,
SYNC_SYNTACTICAL_ERROR, SYNC_PARSER_ERROR,
SYNC_SEMANTICAL_ERROR SYNC_RUNTIME_ERROR
} SyncErrorType; } SyncErrorType;
typedef struct { typedef struct {
@ -29,8 +24,16 @@ typedef struct {
} SyncError; } SyncError;
typedef enum { typedef enum {
SYNC_ERROR,
SYNC_RESULT, SYNC_RESULT,
SYNC_ERROR,
} SyncResultType; } SyncResultType;
// typedef struct {
// SyncResultType type;
// union {
// void *result;
// SyncError error;
// };
// } SyncResult;
#endif // SYNC_TYPES_H #endif // SYNC_TYPES_H

View File

@ -1,6 +1,5 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <stdlib.h>
#include "sync/types.h" #include "sync/types.h"
#include "sync/lexer.h" #include "sync/lexer.h"
@ -79,32 +78,20 @@ static char is_identifier_char(char c) {
return isalnum(c) || c == '_'; return isalnum(c) || c == '_';
} }
static LexerResult lexer_result(Lexer* lexer, TokenType type, size_t start, size_t start_line) { static TokenResult lexer_result(Lexer* lexer, TokenType type, size_t start, size_t start_line) {
TokenResult* result = (TokenResult*)malloc(sizeof(TokenResult)); return (TokenResult){SYNC_RESULT, .result = (Token){
if (result == NULL) type,
return (LexerResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}}; &lexer->source[start],
result->type = SYNC_RESULT; lexer->pos - start,
result->result.type = type; get_file_info(lexer, start, start_line)
result->result.start = &lexer->source[start]; }};
result->result.length = lexer->pos - start;
result->result.file_info = get_file_info(lexer, start, start_line);
result->next = NULL;
return (LexerResult){SYNC_RESULT, .result = result};
} }
static LexerResult lexer_error(Lexer* lexer, const char* message, size_t start, size_t start_line) { static TokenResult lexer_error(Lexer* lexer, const char* message, size_t start, size_t start_line) {
TokenResult* result = (TokenResult*)malloc(sizeof(TokenResult)); return (TokenResult){SYNC_ERROR, .error = (SyncError){SYNC_LEXER_ERROR, message, get_file_info(lexer, start, start_line)}};
if (result == NULL)
return (LexerResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
result->type = SYNC_ERROR;
result->error.type = SYNC_LEXICAL_ERROR;
result->error.message = message;
result->error.file_info = get_file_info(lexer, start, start_line);
result->next = NULL;
return (LexerResult){SYNC_RESULT, .result = result};
} }
static LexerResult lexer_next(Lexer* lexer) { TokenResult lexer_next(Lexer* lexer) {
// Gets the next token from the source // Gets the next token from the source
while (isspace(peek(lexer)) || peek(lexer) == '/') { while (isspace(peek(lexer)) || peek(lexer) == '/') {
@ -203,7 +190,7 @@ static LexerResult lexer_next(Lexer* lexer) {
if (peek(lexer) == '=') advance(lexer); if (peek(lexer) == '=') advance(lexer);
return lexer_result(lexer, TOKEN_OPERATOR, start, start_line); return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
case '-': case '-':
if (peek(lexer) == '=' || peek(lexer) == '>') advance(lexer); if (peek(lexer) == '=') advance(lexer);
return lexer_result(lexer, TOKEN_OPERATOR, start, start_line); return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
case '*': case '*':
if (peek(lexer) == '=') advance(lexer); if (peek(lexer) == '=') advance(lexer);
@ -223,42 +210,3 @@ static LexerResult lexer_next(Lexer* lexer) {
default: return lexer_error(lexer, "Unknown token", start, start_line); default: return lexer_error(lexer, "Unknown token", start, start_line);
} }
} }
LexerResult lexical_analysis(Lexer *lexer) {
LexerResult result;
TokenResult* head = NULL;
TokenResult* current = NULL;
do {
if (head == NULL) {
result = lexer_next(lexer);
if (result.type == SYNC_ERROR) {
clean_token_result(head);
return result;
}
head = result.result;
current = head;
} else {
result = lexer_next(lexer);
if (result.type == SYNC_ERROR) {
clean_token_result(head);
return result;
}
current->next = result.result;
current = current->next;
}
if (current == NULL) {
clean_token_result(head);
return (LexerResult){SYNC_ERROR, .error = (GeneralError){"Unknown Error.", 1}};
}
} while (current->type != SYNC_ERROR && current->result.type != TOKEN_EOF);
return (LexerResult){SYNC_RESULT, .result = head};
}
void clean_token_result(TokenResult* head) {
while (head != NULL) {
TokenResult* temp = head;
head = head->next;
free(temp);
}
}

View File

@ -40,31 +40,21 @@ int main(void) {
Lexer lexer; Lexer lexer;
lexer_init(&lexer, filename, source); lexer_init(&lexer, filename, source);
LexerResult lexer_result = lexical_analysis(&lexer); TokenResult result;
if (lexer_result.type == SYNC_ERROR) { do {
fprintf(stderr, "Error: %s\n", lexer_result.error.message); result = lexer_next(&lexer);
free(source); if (result.type == SYNC_RESULT) {
return lexer_result.error.code; print_token(result.result);
} } else {
fprintf(stderr, "Error: %s\n", result.error.message);
TokenResult* token_result = lexer_result.result; fprintf(stderr, "\tFilename: %s\n", result.error.file_info.filename);
int error_count = 0; fprintf(stderr, "\tLine: %zi\n", result.error.file_info.line);
while (token_result != NULL) { fprintf(stderr, "\tColumn: %zi\n", result.error.file_info.column);
if (token_result->type == SYNC_ERROR) {
fprintf(stderr, "Error: %s\n", token_result->error.message);
fprintf(stderr, "\tFilename: %s\n", token_result->error.file_info.filename);
fprintf(stderr, "\tLn: %zi, Col: %zi\n", token_result->error.file_info.line, token_result->error.file_info.column);
clean_token_result(lexer_result.result);
free(source); free(source);
return 1; return 1;
} else {
print_token(token_result->result);
}
token_result = token_result->next;
} }
} while (result.type != SYNC_ERROR && result.result.type != TOKEN_EOF);
clean_token_result(lexer_result.result);
free(source); free(source);
return 0; return 0;
} }

View File

@ -4,56 +4,54 @@
#include "../include/sync/types.h" #include "../include/sync/types.h"
#include "../include/sync/lexer.h" #include "../include/sync/lexer.h"
// TODO: Update Tests void test_tokenize_simple_assignment(void) {
const char* src = "x = 42;";
Lexer lexer;
lexer_init(&lexer, "<stdin>", src);
// void test_tokenize_simple_assignment(void) { TokenResult t = lexer_next(&lexer);
// const char* src = "x = 42;"; assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "x", t.result.length) == 0);
// Lexer lexer;
// lexer_init(&lexer, "<stdin>", src);
// TokenResult t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "x", t.result.length) == 0); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_OPERATOR && strncmp(t.result.start, "=", t.result.length) == 0);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_OPERATOR && strncmp(t.result.start, "=", t.result.length) == 0); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_NUMBER && strncmp(t.result.start, "42", t.result.length) == 0);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_NUMBER && strncmp(t.result.start, "42", t.result.length) == 0); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_SEMICOLON);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_SEMICOLON); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_EOF);
}
// t = lexer_next(&lexer); void test_tokenize_function_call(void) {
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_EOF); const char* src = "print(x);";
// } Lexer lexer;
lexer_init(&lexer, "<stdin>", src);
// void test_tokenize_function_call(void) { TokenResult t = lexer_next(&lexer);
// const char* src = "print(x);"; assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "print", t.result.length) == 0);
// Lexer lexer;
// lexer_init(&lexer, "<stdin>", src);
// TokenResult t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "print", t.result.length) == 0); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_LPAREN);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_LPAREN); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "x", t.result.length) == 0);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_IDENTIFIER && strncmp(t.result.start, "x", t.result.length) == 0); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_RPAREN);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_RPAREN); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_SEMICOLON);
// t = lexer_next(&lexer); t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_SEMICOLON); assert(t.type == SYNC_RESULT && t.result.type == TOKEN_EOF);
}
// t = lexer_next(&lexer);
// assert(t.type == SYNC_RESULT && t.result.type == TOKEN_EOF);
// }
int main(void) { int main(void) {
// test_tokenize_simple_assignment(); test_tokenize_simple_assignment();
// test_tokenize_function_call(); test_tokenize_function_call();
printf("All lexer tests passed.\n"); printf("All lexer tests passed.\n");
return 0; return 0;