added postfix, break and return parsing
This commit is contained in:
parent
37356facc2
commit
1be3bf0659
9 changed files with 115 additions and 13 deletions
4
examples/generics.l
Normal file
4
examples/generics.l
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
u32 sum<T>(T x, T y)
|
||||||
|
{
|
||||||
|
return x + y;
|
||||||
|
}
|
||||||
6
examples/hello_world.l
Normal file
6
examples/hello_world.l
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import test;
|
||||||
|
|
||||||
|
i32 main()
|
||||||
|
{
|
||||||
|
print_msg("Hello world!");
|
||||||
|
}
|
||||||
10
examples/test.l
Normal file
10
examples/test.l
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
import std::io;
|
||||||
|
|
||||||
|
module log {
|
||||||
|
|
||||||
|
void print_msg([u8] msg)
|
||||||
|
{
|
||||||
|
printf("%s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
9
lc.c
9
lc.c
|
|
@ -90,6 +90,13 @@ void print_ast(ast_node *node, int depth) {
|
||||||
printf("UnaryOp (%s)\n", get_uop_str(node->expr.unary.operator));
|
printf("UnaryOp (%s)\n", get_uop_str(node->expr.unary.operator));
|
||||||
print_ast(node->expr.unary.right, depth + 1);
|
print_ast(node->expr.unary.right, depth + 1);
|
||||||
break;
|
break;
|
||||||
|
case NODE_POSTFIX:
|
||||||
|
printf("Postfix (%s)\n", get_uop_str(node->expr.unary.operator));
|
||||||
|
print_ast(node->expr.unary.right, depth + 1);
|
||||||
|
break;
|
||||||
|
case NODE_BREAK:
|
||||||
|
printf("Break\n");
|
||||||
|
break;
|
||||||
case NODE_TERNARY:
|
case NODE_TERNARY:
|
||||||
printf("Ternary (? :)\n");
|
printf("Ternary (? :)\n");
|
||||||
print_indent(depth + 1); printf("Condition:\n");
|
print_indent(depth + 1); printf("Condition:\n");
|
||||||
|
|
@ -125,7 +132,7 @@ void print_ast(ast_node *node, int depth) {
|
||||||
case NODE_VAR_DECL:
|
case NODE_VAR_DECL:
|
||||||
printf("VarDecl (Fields missing in struct)\n");
|
printf("VarDecl (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
case NODE_FUNCTION_DEF:
|
case NODE_FUNCTION:
|
||||||
printf("FunctionDef (Fields missing in struct)\n");
|
printf("FunctionDef (Fields missing in struct)\n");
|
||||||
break;
|
break;
|
||||||
case NODE_RETURN:
|
case NODE_RETURN:
|
||||||
|
|
|
||||||
2
lexer.c
2
lexer.c
|
|
@ -400,7 +400,7 @@ lexer *lexer_init(char *source, usize size, arena *arena)
|
||||||
trie_insert(keywords, lex->allocator, "if", TOKEN_IF);
|
trie_insert(keywords, lex->allocator, "if", TOKEN_IF);
|
||||||
trie_insert(keywords, lex->allocator, "else", TOKEN_ELSE);
|
trie_insert(keywords, lex->allocator, "else", TOKEN_ELSE);
|
||||||
trie_insert(keywords, lex->allocator, "switch", TOKEN_SWITCH);
|
trie_insert(keywords, lex->allocator, "switch", TOKEN_SWITCH);
|
||||||
trie_insert(keywords, lex->allocator, "case", TOKEN_CASE);
|
trie_insert(keywords, lex->allocator, "break", TOKEN_BREAK);
|
||||||
trie_insert(keywords, lex->allocator, "do", TOKEN_DO);
|
trie_insert(keywords, lex->allocator, "do", TOKEN_DO);
|
||||||
trie_insert(keywords, lex->allocator, "defer", TOKEN_DEFER);
|
trie_insert(keywords, lex->allocator, "defer", TOKEN_DEFER);
|
||||||
trie_insert(keywords, lex->allocator, "return", TOKEN_RETURN);
|
trie_insert(keywords, lex->allocator, "return", TOKEN_RETURN);
|
||||||
|
|
|
||||||
2
lexer.h
2
lexer.h
|
|
@ -63,7 +63,7 @@ typedef enum {
|
||||||
TOKEN_IF,
|
TOKEN_IF,
|
||||||
TOKEN_ELSE,
|
TOKEN_ELSE,
|
||||||
TOKEN_SWITCH,
|
TOKEN_SWITCH,
|
||||||
TOKEN_CASE,
|
TOKEN_BREAK,
|
||||||
TOKEN_DO,
|
TOKEN_DO,
|
||||||
TOKEN_DEFER,
|
TOKEN_DEFER,
|
||||||
TOKEN_MODULE,
|
TOKEN_MODULE,
|
||||||
|
|
|
||||||
80
parser.c
80
parser.c
|
|
@ -1,6 +1,9 @@
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
bool has_errors = false;
|
||||||
|
|
||||||
ast_node *parse_expression(parser *p);
|
ast_node *parse_expression(parser *p);
|
||||||
|
|
||||||
|
|
@ -79,6 +82,7 @@ static void parser_sync(parser *p)
|
||||||
static void error(parser *p, char *msg)
|
static void error(parser *p, char *msg)
|
||||||
{
|
{
|
||||||
printf("\x1b[31m\x1b[1merror\x1b[0m\x1b[1m:%ld:%ld:\x1b[0m %s\n", p->previous->position.row, p->previous->position.column, msg);
|
printf("\x1b[31m\x1b[1merror\x1b[0m\x1b[1m:%ld:%ld:\x1b[0m %s\n", p->previous->position.row, p->previous->position.column, msg);
|
||||||
|
has_errors = true;
|
||||||
parser_sync(p);
|
parser_sync(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -169,6 +173,7 @@ static ast_node *parse_factor(parser *p)
|
||||||
if (p->tokens->next && p->tokens->next->type == TOKEN_LPAREN) {
|
if (p->tokens->next && p->tokens->next->type == TOKEN_LPAREN) {
|
||||||
return parse_call(p);
|
return parse_call(p);
|
||||||
}
|
}
|
||||||
|
advance(p);
|
||||||
|
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
node->type = NODE_IDENTIFIER;
|
node->type = NODE_IDENTIFIER;
|
||||||
|
|
@ -343,23 +348,87 @@ ast_node *parse_expression(parser *p)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If after parsing an expression a `++` or a `--`
|
||||||
|
* token is found, it should be a postfix expression.
|
||||||
|
*/
|
||||||
|
if (match(p, TOKEN_PLUS_PLUS) | match(p, TOKEN_MINUS_MINUS)) {
|
||||||
|
unary_op op;
|
||||||
|
switch (p->previous->type) {
|
||||||
|
case TOKEN_PLUS_PLUS:
|
||||||
|
op = UOP_INCR;
|
||||||
|
break;
|
||||||
|
case TOKEN_MINUS_MINUS:
|
||||||
|
op = UOP_DECR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_POSTFIX;
|
||||||
|
node->expr.unary.operator = op;
|
||||||
|
node->expr.unary.right = left;
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ast_node *parse_statement(parser *p)
|
||||||
|
{
|
||||||
|
if (match(p, TOKEN_BREAK)) {
|
||||||
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
|
error(p, "expected `;`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_BREAK;
|
||||||
|
return node;
|
||||||
|
} else if (match(p, TOKEN_RETURN)) {
|
||||||
|
ast_node *expr = parse_expression(p);
|
||||||
|
|
||||||
|
if (!expr) {
|
||||||
|
error(p, "expected expression.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
|
error(p, "expected `;`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_RETURN;
|
||||||
|
node->expr.ret.value = expr;
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
ast_node *expr = parse_expression(p);
|
||||||
|
if (!expr) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!match(p, TOKEN_SEMICOLON)) {
|
||||||
|
error(p, "expected `;`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a list of expressions to form a full AST. */
|
/* Get a list of expressions to form a full AST. */
|
||||||
static void parse(parser *p)
|
static void parse(parser *p)
|
||||||
{
|
{
|
||||||
p->ast = arena_alloc(p->allocator, sizeof(ast_node));
|
p->ast = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
p->ast->type = NODE_UNIT;
|
p->ast->type = NODE_UNIT;
|
||||||
p->ast->expr.unit_node.expr = parse_expression(p);
|
p->ast->expr.unit_node.expr = parse_statement(p);
|
||||||
ast_node *tail = p->ast;
|
ast_node *tail = p->ast;
|
||||||
ast_node *expr = parse_expression(p);
|
ast_node *expr = parse_statement(p);
|
||||||
while (expr) {
|
while (expr) {
|
||||||
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
||||||
tail = tail->expr.unit_node.next;
|
tail = tail->expr.unit_node.next;
|
||||||
tail->type = NODE_UNIT;
|
tail->type = NODE_UNIT;
|
||||||
expr = parse_expression(p);
|
expr = parse_statement(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -371,5 +440,10 @@ parser *parser_init(lexer *l, arena *allocator)
|
||||||
|
|
||||||
parse(p);
|
parse(p);
|
||||||
|
|
||||||
|
if (has_errors) {
|
||||||
|
printf("Compilation failed.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
13
parser.h
13
parser.h
|
|
@ -58,7 +58,7 @@ typedef struct {
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
member *params;
|
member *params;
|
||||||
} function_decl;
|
} function;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NODE_IDENTIFIER,
|
NODE_IDENTIFIER,
|
||||||
|
|
@ -73,23 +73,21 @@ typedef enum {
|
||||||
NODE_ACCESS,
|
NODE_ACCESS,
|
||||||
NODE_CALL,
|
NODE_CALL,
|
||||||
NODE_POSTFIX,
|
NODE_POSTFIX,
|
||||||
NODE_GOTO,
|
|
||||||
NODE_BREAK,
|
NODE_BREAK,
|
||||||
NODE_CASE,
|
NODE_RETURN,
|
||||||
NODE_SWITCH,
|
NODE_SWITCH,
|
||||||
NODE_FOR,
|
NODE_FOR,
|
||||||
NODE_DO,
|
NODE_DO,
|
||||||
NODE_WHILE,
|
NODE_WHILE,
|
||||||
NODE_IF,
|
NODE_IF,
|
||||||
NODE_RETURN,
|
|
||||||
NODE_COMPOUND,
|
NODE_COMPOUND,
|
||||||
NODE_ENUM,
|
NODE_ENUM,
|
||||||
NODE_STRUCT,
|
NODE_STRUCT,
|
||||||
NODE_UNION,
|
NODE_UNION,
|
||||||
NODE_VAR_DECL,
|
NODE_VAR_DECL,
|
||||||
NODE_FUNCTION_DEF,
|
NODE_FUNCTION,
|
||||||
NODE_FUNCTION_DECL,
|
|
||||||
NODE_TERNARY,
|
NODE_TERNARY,
|
||||||
|
NODE_GOTO,
|
||||||
NODE_UNIT,
|
NODE_UNIT,
|
||||||
} node_type;
|
} node_type;
|
||||||
|
|
||||||
|
|
@ -142,6 +140,9 @@ typedef struct _ast_node {
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
} call;
|
} call;
|
||||||
|
struct {
|
||||||
|
struct _ast_node *value;
|
||||||
|
} ret;
|
||||||
} expr;
|
} expr;
|
||||||
} ast_node;
|
} ast_node;
|
||||||
|
|
||||||
|
|
|
||||||
2
test.c
2
test.c
|
|
@ -1 +1 @@
|
||||||
x(4, 5)
|
x[3];
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue