Compare commits

...

3 Commits

Author SHA1 Message Date
Kyler Olsen 23f23cd9b6 started parser 2025-06-19 01:04:46 -06:00
Kyler Olsen 759db1ea7a added add_file_infos function 2025-06-19 00:54:48 -06:00
Kyler Olsen e968058249 added token_result_array function 2025-06-18 23:00:36 -06:00
7 changed files with 326 additions and 1 deletions

View File

@ -52,13 +52,27 @@ typedef struct TokenResult {
typedef struct {
SyncResultType type;
union {
struct TokenResult* result;
TokenResult* result;
GeneralError error;
};
} LexerResult;
typedef struct {
size_t length;
Token* tokens;
} TokenArray;
typedef struct {
SyncResultType type;
union {
TokenArray result;
GeneralError error;
};
} TokenArrayResult;
void lexer_init(Lexer* lexer, const char* filename, const char* source);
LexerResult lexical_analysis(Lexer* lexer);
TokenArrayResult token_result_array(TokenResult* result);
void clean_token_result(TokenResult* head);
#endif // SYNC_LEXER_H

63
include/sync/syntax.h Normal file
View File

@ -0,0 +1,63 @@
// Kyler Olsen
// ZINC Bootstrap compiler
// Syntax Header
// June 2025
#ifndef SYNC_SYNTAX_H
#define SYNC_SYNTAX_H
#include "types.h"
#include "lexer.h"
typedef enum {
NODE_FILE,
NODE_BLOCK,
NODE_STATEMENT,
NODE_IDENTIFIER,
NODE_NUMBER,
NODE_UNARY_OPERATOR,
NODE_BINARY_OPERATOR,
NODE_LPAREN,
NODE_RPAREN,
NODE_SEMICOLON,
NODE_LBRACE,
NODE_RBRACE,
NODE_LBRACKET,
NODE_RBRACKET,
NODE_CHARACTER,
NODE_STRING,
} NodeType;
typedef struct Children {
size_t length;
struct SyntaxNode* nodes;
} Children;
typedef struct SyntaxNode {
NodeType type;
const char *start;
size_t length;
FileInfo file_info;
Children children;
} SyntaxNode;
typedef struct {
SyncResultType type;
union {
SyntaxNode result;
SyncError error;
};
} NodeResult;
typedef struct {
SyncResultType type;
union {
NodeResult result;
GeneralError error;
};
} SyntaxResult;
SyntaxResult syntactical_analysis(TokenArray tokens);
#endif // SYNC_SYNTAX_H

View File

@ -38,4 +38,14 @@ typedef enum {
SYNC_RESULT,
} SyncResultType;
typedef struct {
SyncResultType type;
union {
FileInfo result;
GeneralError error;
};
} FileInfoResult;
FileInfoResult add_file_infos(FileInfo a, FileInfo b, const char* start);
#endif // SYNC_TYPES_H

View File

@ -260,6 +260,28 @@ LexerResult lexical_analysis(Lexer *lexer) {
return (LexerResult){SYNC_RESULT, .result = head};
}
TokenArrayResult token_result_array(TokenResult* result) {
TokenResult* head = result;
size_t length = 0;
while (head != NULL) {
if (head->type == SYNC_ERROR)
return (TokenArrayResult){SYNC_ERROR, .error = (GeneralError){"Invalid Token List.", 1}};
length++;
head = head->next;
}
Token* token_array = (Token*)malloc(length * sizeof(Token));
if (token_array == NULL)
return (TokenArrayResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
head = result;
for (int i = 0; i < length; i++) {
token_array[i] = head->result;
head = head->next;
}
return (TokenArrayResult){SYNC_RESULT, length, .result = (TokenArray){length, token_array}};
}
void clean_token_result(TokenResult* head) {
while (head != NULL) {
TokenResult* temp = head;

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include "sync/types.h"
#include "sync/lexer.h"
#include "sync/syntax.h"
const char* TOKEN_TYPES[] = {
"EOF", "IDENTIFIER", "NUMBER", "OPERATOR",
@ -68,8 +69,19 @@ int main(void) {
token_result = token_result->next;
}
TokenArrayResult array_result = token_result_array(lexer_result.result);
clean_token_result(lexer_result.result);
if (array_result.type == SYNC_ERROR) {
fprintf(stderr, "Error: %s\n", array_result.error.message);
free(source);
return array_result.error.code;
}
TokenArray tokens = array_result.result;
free(tokens.tokens);
free(source);
printf("Compilation Completed.");
return 0;
}

166
src/syntax.c Normal file
View File

@ -0,0 +1,166 @@
// Kyler Olsen
// ZINC Bootstrap compiler
// Syntax
// June 2025
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include "sync/types.h"
#include "sync/lexer.h"
#include "sync/syntax.h"
typedef struct {
const char* filename;
TokenArray tokens;
size_t pos;
} Parser;
typedef struct Child {
struct Child* next;
SyntaxNode node;
} Child;
typedef struct ChildrenResult {
SyncResultType type;
union {
Children result;
GeneralError error;
};
} ChildrenResult;
static GeneralError add_child(Child* list, SyntaxNode node) {
if (list == NULL) return (GeneralError){"Headless linked list.", 1};
Child* new_child = (Child*)malloc(sizeof(Child));
if (new_child == NULL)
return (GeneralError){"Failed to allocate memory.", 1};
new_child->next = NULL;
new_child->node = node;
while (list->next != NULL) list = list->next;
list->next = new_child;
return (GeneralError){NULL, 0};
}
static ChildrenResult children_array(Child* list) {
if (list == NULL)
return (ChildrenResult){SYNC_ERROR, .error = (GeneralError){"Headless linked list.", 1}};
Child* head = list;
size_t length = 0;
while (head != NULL) {
length++;
head = head->next;
}
SyntaxNode* nodes = (SyntaxNode*)malloc(length * sizeof(SyntaxNode));
if (nodes == NULL)
return (ChildrenResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
head = list;
for (int i = 0; i < length; i++) {
nodes[i] = head->node;
head = head->next;
}
while (list != NULL) {
Child* temp = list;
list = list->next;
free(temp);
}
return (ChildrenResult){SYNC_RESULT, .result = (Children){length, nodes}};
}
static SyntaxResult aggregate_children(NodeType type, Children children) {
const char* start = children.nodes[0].start;
size_t length = children.nodes[0].length;
FileInfo file_info = children.nodes[0].file_info;
for (int i = 1; i < children.length; i++) {
for (int j = 0; (j + start + length) <= children.nodes[i].start; j++)
if (*(j + start + length) == '\0')
return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Non-continuous string.", 1}};
length = (children.nodes[i].start + children.nodes[i].length) - start;
FileInfoResult file_info_result = add_file_infos(file_info, children.nodes[i].file_info, start);
if (file_info_result.type == SYNC_ERROR) return (SyntaxResult){SYNC_ERROR, .error = file_info_result.error};
file_info = file_info_result.result;
}
SyntaxNode node = {type, start, length, file_info, children};
return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){SYNC_RESULT, .result = node}};
}
static SyntaxResult syntax_result(NodeType type, Child* list) {
ChildrenResult result = children_array(list);
list = NULL;
if (result.type == SYNC_ERROR) return (SyntaxResult){SYNC_RESULT, .error = result.error};
return aggregate_children(type, result.result);
}
static SyntaxResult syntax_error(const char* message, Token token) {
return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){
.type = SYNC_ERROR,
.error.type = SYNC_SYNTACTICAL_ERROR,
.error.message = message,
.error.file_info = token.file_info,
}};
}
static SyntaxResult parse_statement(Parser* parser) {
}
static SyntaxResult parse_block(Parser* parser) {
Child* children = NULL;
if (parser->tokens.tokens[parser->pos].type == TOKEN_RBRACE) {
parser->pos++;
while (parser->tokens.tokens[parser->pos].type != TOKEN_LBRACE) {
SyntaxResult result = parse_statement(parser);
if (result.type == SYNC_ERROR) return result;
if (result.result.type == SYNC_ERROR) return result;
if (children == NULL) {
children = (Child*)malloc(sizeof(Child));
if (children == NULL) return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
children->next = NULL;
children->node = result.result.result;
} else add_child(children, result.result.result);
if (parser->tokens.tokens[parser->pos].type == TOKEN_EOF)
return syntax_error("Expected '}'", parser->tokens.tokens[parser->pos]);
}
parser->pos++;
} else {
SyntaxResult result = parse_statement(parser);
if (result.type == SYNC_ERROR) return result;
if (result.result.type == SYNC_ERROR) return result;
children = (Child*)malloc(sizeof(Child));
if (children == NULL) return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
children->next = NULL;
children->node = result.result.result;
}
return syntax_result(NODE_BLOCK, children);
}
SyntaxResult syntactical_analysis(TokenArray tokens) {
Parser* parser = (Parser*)malloc(sizeof(Parser));
if (parser == NULL) return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
Child* children = NULL;
while (parser->tokens.tokens[parser->pos].type != TOKEN_EOF) {
SyntaxResult result = parse_block(parser);
if (result.type == SYNC_ERROR) { free(parser); return result; }
if (result.result.type == SYNC_ERROR) { free(parser); return result; }
if (children == NULL) {
children = (Child*)malloc(sizeof(Child));
if (children == NULL) {
free(parser);
return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
}
children->next = NULL;
children->node = result.result.result;
} else add_child(children, result.result.result);
}
free(parser);
return syntax_result(NODE_FILE, children);
}

38
src/types.c Normal file
View File

@ -0,0 +1,38 @@
// Kyler Olsen
// ZINC Bootstrap compiler
// Type helper functions
// June 2025
#include "sync/types.h"
FileInfoResult add_file_infos(FileInfo a, FileInfo b, const char* start) {
if (a.filename != b.filename)
return (FileInfoResult){SYNC_ERROR, .error = (GeneralError){"Cannot add two FileInfo structs from different files.", 1}};
size_t line = a.line;
size_t column = a.column;
size_t length = a.length;
size_t lines = a.lines;
for (int i = a.length; ; i++) {
if (start[i] == '\0')
return (FileInfoResult){SYNC_ERROR, .error = (GeneralError){"Encountered end of string.", 1}};
if (start[i] == '\n') {
column = 1;
line++;
lines++;
} else column++;
length++;
if (line == b.line && column == b.column) {
length += b.length;
lines += b.lines;
break;
}
}
FileInfo file_info = {
.filename = a.filename,
.line = a.line,
.column = a.column,
.length = length,
.lines = lines
};
return (FileInfoResult){SYNC_RESULT, .result = file_info};
}