Compare commits
No commits in common. "23f23cd9b69c05a0cee8f410b23407e0b65861f0" and "f7b1436f87cdd92bbd1be2d3cb7a42aebe79eef7" have entirely different histories.
23f23cd9b6
...
f7b1436f87
|
@ -52,27 +52,13 @@ typedef struct TokenResult {
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SyncResultType type;
|
SyncResultType type;
|
||||||
union {
|
union {
|
||||||
TokenResult* result;
|
struct TokenResult* result;
|
||||||
GeneralError error;
|
GeneralError error;
|
||||||
};
|
};
|
||||||
} LexerResult;
|
} 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);
|
void lexer_init(Lexer* lexer, const char* filename, const char* source);
|
||||||
LexerResult lexical_analysis(Lexer* lexer);
|
LexerResult lexical_analysis(Lexer* lexer);
|
||||||
TokenArrayResult token_result_array(TokenResult* result);
|
|
||||||
void clean_token_result(TokenResult* head);
|
void clean_token_result(TokenResult* head);
|
||||||
|
|
||||||
#endif // SYNC_LEXER_H
|
#endif // SYNC_LEXER_H
|
||||||
|
|
|
@ -1,63 +0,0 @@
|
||||||
// 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
|
|
|
@ -38,14 +38,4 @@ typedef enum {
|
||||||
SYNC_RESULT,
|
SYNC_RESULT,
|
||||||
} SyncResultType;
|
} 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
|
#endif // SYNC_TYPES_H
|
||||||
|
|
22
src/lexer.c
22
src/lexer.c
|
@ -260,28 +260,6 @@ LexerResult lexical_analysis(Lexer *lexer) {
|
||||||
return (LexerResult){SYNC_RESULT, .result = head};
|
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) {
|
void clean_token_result(TokenResult* head) {
|
||||||
while (head != NULL) {
|
while (head != NULL) {
|
||||||
TokenResult* temp = head;
|
TokenResult* temp = head;
|
||||||
|
|
12
src/main.c
12
src/main.c
|
@ -7,7 +7,6 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "sync/types.h"
|
#include "sync/types.h"
|
||||||
#include "sync/lexer.h"
|
#include "sync/lexer.h"
|
||||||
#include "sync/syntax.h"
|
|
||||||
|
|
||||||
const char* TOKEN_TYPES[] = {
|
const char* TOKEN_TYPES[] = {
|
||||||
"EOF", "IDENTIFIER", "NUMBER", "OPERATOR",
|
"EOF", "IDENTIFIER", "NUMBER", "OPERATOR",
|
||||||
|
@ -69,19 +68,8 @@ int main(void) {
|
||||||
token_result = token_result->next;
|
token_result = token_result->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenArrayResult array_result = token_result_array(lexer_result.result);
|
|
||||||
clean_token_result(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);
|
free(source);
|
||||||
return array_result.error.code;
|
|
||||||
}
|
|
||||||
TokenArray tokens = array_result.result;
|
|
||||||
|
|
||||||
free(tokens.tokens);
|
|
||||||
free(source);
|
|
||||||
|
|
||||||
printf("Compilation Completed.");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
166
src/syntax.c
166
src/syntax.c
|
@ -1,166 +0,0 @@
|
||||||
// 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
38
src/types.c
|
@ -1,38 +0,0 @@
|
||||||
// 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};
|
|
||||||
}
|
|
Loading…
Reference in New Issue