Compare commits
2 Commits
14158ed9f4
...
f7f9797a4a
Author | SHA1 | Date |
---|---|---|
|
f7f9797a4a | |
|
35e4b97575 |
|
@ -35,20 +35,20 @@ typedef enum {
|
||||||
TOKEN_KW_UNION,
|
TOKEN_KW_UNION,
|
||||||
// Control Flow
|
// Control Flow
|
||||||
TOKEN_KW_BREAK,
|
TOKEN_KW_BREAK,
|
||||||
TOKEN_KW_CASE,
|
|
||||||
TOKEN_KW_CONTINUE,
|
TOKEN_KW_CONTINUE,
|
||||||
TOKEN_KW_DEFAULT,
|
|
||||||
TOKEN_KW_DO,
|
TOKEN_KW_DO,
|
||||||
TOKEN_KW_ELSE,
|
TOKEN_KW_ELSE,
|
||||||
TOKEN_KW_FOR,
|
TOKEN_KW_FOR,
|
||||||
TOKEN_KW_IF,
|
TOKEN_KW_IF,
|
||||||
TOKEN_KW_MATCH,
|
|
||||||
TOKEN_KW_RETURN,
|
TOKEN_KW_RETURN,
|
||||||
TOKEN_KW_SWITCH,
|
|
||||||
TOKEN_KW_WHILE,
|
TOKEN_KW_WHILE,
|
||||||
// Values
|
// Values
|
||||||
|
TOKEN_KW_ERROR,
|
||||||
TOKEN_KW_FALSE,
|
TOKEN_KW_FALSE,
|
||||||
|
TOKEN_KW_NONE,
|
||||||
|
TOKEN_KW_SOME,
|
||||||
TOKEN_KW_TRUE,
|
TOKEN_KW_TRUE,
|
||||||
|
TOKEN_KW_VALUE,
|
||||||
// Types
|
// Types
|
||||||
TOKEN_KW_BOOL,
|
TOKEN_KW_BOOL,
|
||||||
TOKEN_KW_F32,
|
TOKEN_KW_F32,
|
||||||
|
@ -57,6 +57,8 @@ typedef enum {
|
||||||
TOKEN_KW_I16,
|
TOKEN_KW_I16,
|
||||||
TOKEN_KW_I32,
|
TOKEN_KW_I32,
|
||||||
TOKEN_KW_I64,
|
TOKEN_KW_I64,
|
||||||
|
TOKEN_KW_OPTION,
|
||||||
|
TOKEN_KW_RESULT,
|
||||||
TOKEN_KW_U8,
|
TOKEN_KW_U8,
|
||||||
TOKEN_KW_U16,
|
TOKEN_KW_U16,
|
||||||
TOKEN_KW_U32,
|
TOKEN_KW_U32,
|
||||||
|
@ -67,6 +69,7 @@ typedef enum {
|
||||||
TOKEN_KW_IMPORT,
|
TOKEN_KW_IMPORT,
|
||||||
// Operators
|
// Operators
|
||||||
TOKEN_KW_AND,
|
TOKEN_KW_AND,
|
||||||
|
TOKEN_KW_CAST,
|
||||||
TOKEN_KW_IS,
|
TOKEN_KW_IS,
|
||||||
TOKEN_KW_NOT,
|
TOKEN_KW_NOT,
|
||||||
TOKEN_KW_OR,
|
TOKEN_KW_OR,
|
||||||
|
|
|
@ -12,7 +12,29 @@
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NODE_FILE,
|
NODE_FILE,
|
||||||
NODE_BLOCK,
|
NODE_BLOCK,
|
||||||
|
|
||||||
NODE_STATEMENT,
|
NODE_STATEMENT,
|
||||||
|
// Definitions and Declarations
|
||||||
|
NODE_ENUM_DEFINITION,
|
||||||
|
NODE_FN_DEFINITION,
|
||||||
|
NODE_LET_STATEMENT,
|
||||||
|
NODE_STRUCT_DEFINITION,
|
||||||
|
NODE_UNION_DEFINITION,
|
||||||
|
// Flow Control
|
||||||
|
NODE_BREAK_STATEMENT,
|
||||||
|
NODE_CASE_STATEMENT,
|
||||||
|
NODE_CONTINUE_STATEMENT,
|
||||||
|
NODE_DEFAULT_STATEMENT,
|
||||||
|
NODE_DO_WHILE_LOOP,
|
||||||
|
NODE_ELSE_STATEMENT,
|
||||||
|
NODE_FOR_LOOP,
|
||||||
|
NODE_IF_STATEMENT,
|
||||||
|
NODE_MATCH_STATEMENT,
|
||||||
|
NODE_RETURN_STATEMENT,
|
||||||
|
NODE_SWITCH_STATEMENT,
|
||||||
|
NODE_WHILE_LOOP,
|
||||||
|
// Modules
|
||||||
|
NODE_IMPORT_STATEMENT,
|
||||||
|
|
||||||
NODE_IDENTIFIER,
|
NODE_IDENTIFIER,
|
||||||
NODE_NUMBER,
|
NODE_NUMBER,
|
||||||
|
|
44
src/lexer.c
44
src/lexer.c
|
@ -32,20 +32,20 @@ const KeywordPair KEYWORDS[] = {
|
||||||
{"union", TOKEN_KW_UNION},
|
{"union", TOKEN_KW_UNION},
|
||||||
// Control Flow
|
// Control Flow
|
||||||
{"break", TOKEN_KW_BREAK},
|
{"break", TOKEN_KW_BREAK},
|
||||||
{"case", TOKEN_KW_CASE},
|
|
||||||
{"continue", TOKEN_KW_CONTINUE},
|
{"continue", TOKEN_KW_CONTINUE},
|
||||||
{"default", TOKEN_KW_DEFAULT},
|
|
||||||
{"do", TOKEN_KW_DO},
|
{"do", TOKEN_KW_DO},
|
||||||
{"else", TOKEN_KW_ELSE},
|
{"else", TOKEN_KW_ELSE},
|
||||||
{"for", TOKEN_KW_FOR},
|
{"for", TOKEN_KW_FOR},
|
||||||
{"if", TOKEN_KW_IF},
|
{"if", TOKEN_KW_IF},
|
||||||
{"match", TOKEN_KW_MATCH},
|
|
||||||
{"return", TOKEN_KW_RETURN},
|
{"return", TOKEN_KW_RETURN},
|
||||||
{"switch", TOKEN_KW_SWITCH},
|
|
||||||
{"while", TOKEN_KW_WHILE},
|
{"while", TOKEN_KW_WHILE},
|
||||||
// Values
|
// Values
|
||||||
|
{"Error", TOKEN_KW_ERROR},
|
||||||
{"False", TOKEN_KW_FALSE},
|
{"False", TOKEN_KW_FALSE},
|
||||||
|
{"None", TOKEN_KW_NONE},
|
||||||
|
{"Some", TOKEN_KW_SOME},
|
||||||
{"True", TOKEN_KW_TRUE},
|
{"True", TOKEN_KW_TRUE},
|
||||||
|
{"Value", TOKEN_KW_VALUE},
|
||||||
// Types
|
// Types
|
||||||
{"bool", TOKEN_KW_BOOL},
|
{"bool", TOKEN_KW_BOOL},
|
||||||
{"f32", TOKEN_KW_F32},
|
{"f32", TOKEN_KW_F32},
|
||||||
|
@ -54,6 +54,8 @@ const KeywordPair KEYWORDS[] = {
|
||||||
{"i16", TOKEN_KW_I16},
|
{"i16", TOKEN_KW_I16},
|
||||||
{"i32", TOKEN_KW_I32},
|
{"i32", TOKEN_KW_I32},
|
||||||
{"i64", TOKEN_KW_I64},
|
{"i64", TOKEN_KW_I64},
|
||||||
|
{"option", TOKEN_KW_OPTION},
|
||||||
|
{"result", TOKEN_KW_RESULT},
|
||||||
{"u8", TOKEN_KW_U8},
|
{"u8", TOKEN_KW_U8},
|
||||||
{"u16", TOKEN_KW_U16},
|
{"u16", TOKEN_KW_U16},
|
||||||
{"u32", TOKEN_KW_U32},
|
{"u32", TOKEN_KW_U32},
|
||||||
|
@ -64,6 +66,7 @@ const KeywordPair KEYWORDS[] = {
|
||||||
{"import", TOKEN_KW_IMPORT},
|
{"import", TOKEN_KW_IMPORT},
|
||||||
// Operators
|
// Operators
|
||||||
{"and", TOKEN_KW_AND},
|
{"and", TOKEN_KW_AND},
|
||||||
|
{"cast", TOKEN_KW_CAST},
|
||||||
{"is", TOKEN_KW_IS},
|
{"is", TOKEN_KW_IS},
|
||||||
{"not", TOKEN_KW_NOT},
|
{"not", TOKEN_KW_NOT},
|
||||||
{"or", TOKEN_KW_OR},
|
{"or", TOKEN_KW_OR},
|
||||||
|
@ -71,9 +74,35 @@ const KeywordPair KEYWORDS[] = {
|
||||||
{"xor", TOKEN_KW_XOR},
|
{"xor", TOKEN_KW_XOR},
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* RESERVED_KEYWORDS[] = {
|
const char *RESERVED_KEYWORDS[] = {
|
||||||
"extern", "f16", "f128", "i128", "impl", "in", "move", "new", "self",
|
"case",
|
||||||
"super", "trait", "tuple", "type", "u128", "use", "where", "yeet",
|
"default",
|
||||||
|
"defer",
|
||||||
|
"del",
|
||||||
|
"extern",
|
||||||
|
"f16",
|
||||||
|
"f128",
|
||||||
|
"handle",
|
||||||
|
"i128",
|
||||||
|
"impl",
|
||||||
|
"in",
|
||||||
|
"match",
|
||||||
|
"move",
|
||||||
|
"new",
|
||||||
|
"pointer",
|
||||||
|
"Pointer",
|
||||||
|
"Result",
|
||||||
|
"self",
|
||||||
|
"super",
|
||||||
|
"switch",
|
||||||
|
"trait",
|
||||||
|
"transform",
|
||||||
|
"tuple",
|
||||||
|
"type",
|
||||||
|
"u128",
|
||||||
|
"use",
|
||||||
|
"where",
|
||||||
|
"yeet",
|
||||||
};
|
};
|
||||||
|
|
||||||
void lexer_init(Lexer* lexer, const char* filename, const char* source) {
|
void lexer_init(Lexer* lexer, const char* filename, const char* source) {
|
||||||
|
@ -311,6 +340,7 @@ static LexerResult lexer_next(Lexer* lexer) {
|
||||||
return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
||||||
case '.': return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
case '.': return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
||||||
case ',': return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
case ',': return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
||||||
|
case ':': return lexer_result(lexer, TOKEN_OPERATOR, start, start_line);
|
||||||
case '(': return lexer_result(lexer, TOKEN_LPAREN, start, start_line);
|
case '(': return lexer_result(lexer, TOKEN_LPAREN, start, start_line);
|
||||||
case ')': return lexer_result(lexer, TOKEN_RPAREN, start, start_line);
|
case ')': return lexer_result(lexer, TOKEN_RPAREN, start, start_line);
|
||||||
case ';': return lexer_result(lexer, TOKEN_SEMICOLON, start, start_line);
|
case ';': return lexer_result(lexer, TOKEN_SEMICOLON, start, start_line);
|
||||||
|
|
146
src/syntax.c
146
src/syntax.c
|
@ -20,7 +20,7 @@ typedef struct Child {
|
||||||
SyntaxNode node;
|
SyntaxNode node;
|
||||||
} Child;
|
} Child;
|
||||||
|
|
||||||
typedef struct ChildrenResult {
|
typedef struct {
|
||||||
SyncResultType type;
|
SyncResultType type;
|
||||||
union {
|
union {
|
||||||
Children result;
|
Children result;
|
||||||
|
@ -28,6 +28,14 @@ typedef struct ChildrenResult {
|
||||||
};
|
};
|
||||||
} ChildrenResult;
|
} ChildrenResult;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SyncResultType type;
|
||||||
|
union {
|
||||||
|
Parser result;
|
||||||
|
SyncError error;
|
||||||
|
};
|
||||||
|
} ParserResult;
|
||||||
|
|
||||||
static GeneralError add_child(Child* list, SyntaxNode node) {
|
static GeneralError add_child(Child* list, SyntaxNode node) {
|
||||||
if (list == NULL) return (GeneralError){"Headless linked list.", 1};
|
if (list == NULL) return (GeneralError){"Headless linked list.", 1};
|
||||||
Child* new_child = (Child*)malloc(sizeof(Child));
|
Child* new_child = (Child*)malloc(sizeof(Child));
|
||||||
|
@ -96,6 +104,19 @@ static SyntaxResult syntax_result(NodeType type, Child* list) {
|
||||||
return aggregate_children(type, result.result);
|
return aggregate_children(type, result.result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static SyntaxResult syntax_simple_result(NodeType type, Token token) {
|
||||||
|
// return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){
|
||||||
|
// .type = SYNC_RESULT,
|
||||||
|
// .result = (SyntaxNode){
|
||||||
|
// .type = type,
|
||||||
|
// .start = token.start,
|
||||||
|
// .length = token.length,
|
||||||
|
// .file_info = token.file_info,
|
||||||
|
// .children = NULL
|
||||||
|
// }
|
||||||
|
// }};
|
||||||
|
// }
|
||||||
|
|
||||||
static SyntaxResult syntax_error(const char* message, Token token) {
|
static SyntaxResult syntax_error(const char* message, Token token) {
|
||||||
return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){
|
return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){
|
||||||
.type = SYNC_ERROR,
|
.type = SYNC_ERROR,
|
||||||
|
@ -105,29 +126,136 @@ static SyntaxResult syntax_error(const char* message, Token token) {
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ParserResult get_to_token(Parser* parser, TokenType type, const char* string, char include_end) {
|
||||||
|
size_t i = parser->pos;
|
||||||
|
while (parser->tokens.tokens[i].type != TOKEN_EOF) {
|
||||||
|
if (parser->tokens.tokens[i].type == type)
|
||||||
|
if (string == NULL || strcmp(parser->tokens.tokens[i].start, string) == 0)
|
||||||
|
return (ParserResult){SYNC_RESULT, .result = (Parser){
|
||||||
|
.tokens.length = i - parser->pos + include_end,
|
||||||
|
.tokens.tokens = parser->tokens.tokens + parser->pos,
|
||||||
|
.pos = 0
|
||||||
|
}};
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return (ParserResult){SYNC_ERROR, .error = (SyncError){
|
||||||
|
.type = SYNC_SYNTACTICAL_ERROR,
|
||||||
|
.message = "Unexpected end of file.",
|
||||||
|
.file_info = parser->tokens.tokens[i].file_info
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
static SyntaxResult parse_expression(Parser* parser) {
|
static SyntaxResult parse_expression(Parser* parser) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static SyntaxResult parse_statement(Parser* parser) {
|
static SyntaxResult parse_enum_definition(Parser* parser) {
|
||||||
Child* children = NULL;
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_function_definition(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_let_statement(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_struct_definition(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_union_definition(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_do_while_loop(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_else_statement(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_for_loop(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_if_statement(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_return_statement(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_while_loop(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_import_statement(Parser* parser) {
|
||||||
|
}
|
||||||
|
|
||||||
|
static SyntaxResult parse_statement(Parser* parser) {
|
||||||
if (
|
if (
|
||||||
parser->tokens.tokens[parser->pos].type == TOKEN_EOF ||
|
parser->tokens.tokens[parser->pos].type == TOKEN_EOF ||
|
||||||
parser->tokens.tokens[parser->pos].type == TOKEN_RBRACE
|
parser->tokens.tokens[parser->pos].type == TOKEN_RBRACE
|
||||||
) return syntax_error("Expected statement", parser->tokens.tokens[parser->pos]);
|
) return syntax_error("Expected statement", parser->tokens.tokens[parser->pos]);
|
||||||
SyntaxResult result = parse_expression(parser);
|
|
||||||
|
// Definitions and Declarations
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_CONST)
|
||||||
|
return syntax_error("const must be in a let statement", parser->tokens.tokens[parser->pos]);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_ENUM)
|
||||||
|
return parse_enum_definition(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_FN)
|
||||||
|
return parse_function_definition(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_LET)
|
||||||
|
return parse_let_statement(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_MUT)
|
||||||
|
return syntax_error("mut must be in a let statement", parser->tokens.tokens[parser->pos]);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_PUBLIC)
|
||||||
|
return syntax_error("public must be in a definition", parser->tokens.tokens[parser->pos]);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_STATIC)
|
||||||
|
return syntax_error("static must be in a definition", parser->tokens.tokens[parser->pos]);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_STRUCT)
|
||||||
|
return parse_struct_definition(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_UNION)
|
||||||
|
return parse_union_definition(parser);
|
||||||
|
|
||||||
|
// Control Flow
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_DO)
|
||||||
|
return parse_do_while_loop(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_ELSE)
|
||||||
|
return parse_else_statement(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_FOR)
|
||||||
|
return parse_for_loop(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_IF)
|
||||||
|
return parse_if_statement(parser);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_WHILE)
|
||||||
|
return parse_while_loop(parser);
|
||||||
|
|
||||||
|
// Types
|
||||||
|
// if (
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_BOOL ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_F32 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_F64 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_I8 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_I16 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_I32 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_I64 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_U8 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_U16 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_U32 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_U64 ||
|
||||||
|
// parser->tokens.tokens[parser->pos].type == TOKEN_KW_VOID
|
||||||
|
// ) return syntax_error("unexpected built in type reference", parser->tokens.tokens[parser->pos]);
|
||||||
|
|
||||||
|
// Modules
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_AS)
|
||||||
|
return syntax_error("as must be in an import statement", parser->tokens.tokens[parser->pos]);
|
||||||
|
if (parser->tokens.tokens[parser->pos].type == TOKEN_KW_IMPORT)
|
||||||
|
return parse_import_statement(parser);
|
||||||
|
|
||||||
|
Child* children = NULL;
|
||||||
|
ParserResult expression_parser = get_to_token(parser, TOKEN_SEMICOLON, NULL, 0);
|
||||||
|
if (expression_parser.type == SYNC_ERROR)
|
||||||
|
return (SyntaxResult){SYNC_RESULT, .result = (NodeResult){SYNC_ERROR, .error = expression_parser.error}};
|
||||||
|
SyntaxResult result = parse_expression(&expression_parser.result);
|
||||||
if (result.type == SYNC_ERROR) return result;
|
if (result.type == SYNC_ERROR) return result;
|
||||||
if (result.result.type == SYNC_ERROR) return result;
|
if (result.result.type == SYNC_ERROR) return result;
|
||||||
if (children == NULL) {
|
|
||||||
children = (Child*)malloc(sizeof(Child));
|
children = (Child*)malloc(sizeof(Child));
|
||||||
if (children == NULL)
|
if (children == NULL)
|
||||||
return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
|
return (SyntaxResult){SYNC_ERROR, .error = (GeneralError){"Failed to allocate memory.", 1}};
|
||||||
children->next = NULL;
|
children->next = NULL;
|
||||||
children->node = result.result.result;
|
children->node = result.result.result;
|
||||||
} else {
|
|
||||||
GeneralError error = add_child(children, result.result.result);
|
|
||||||
if (error.message != NULL) return (SyntaxResult){SYNC_ERROR, .error = error};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parser->tokens.tokens[parser->pos].type != TOKEN_SEMICOLON)
|
if (parser->tokens.tokens[parser->pos].type != TOKEN_SEMICOLON)
|
||||||
return syntax_error("Expected statement", parser->tokens.tokens[parser->pos]);
|
return syntax_error("Expected statement", parser->tokens.tokens[parser->pos]);
|
||||||
|
|
Loading…
Reference in New Issue