started parser
This commit is contained in:
parent
759db1ea7a
commit
23f23cd9b6
|
@ -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
|
|
@ -7,6 +7,7 @@
|
||||||
#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",
|
||||||
|
@ -80,5 +81,7 @@ int main(void) {
|
||||||
free(tokens.tokens);
|
free(tokens.tokens);
|
||||||
free(source);
|
free(source);
|
||||||
|
|
||||||
|
printf("Compilation Completed.");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
Loading…
Reference in New Issue