started parser

This commit is contained in:
Kyler Olsen 2025-06-19 00:55:29 -06:00
parent 759db1ea7a
commit 23f23cd9b6
3 changed files with 232 additions and 0 deletions

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

@ -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",
@ -80,5 +81,7 @@ int main(void) {
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);
}