implemented arrays, pointers and struct init
This commit is contained in:
parent
b504739d59
commit
6d73af4fbb
5 changed files with 194 additions and 75 deletions
18
lc.c
18
lc.c
|
|
@ -69,13 +69,14 @@ void print_ast(ast_node *node, int depth) {
|
||||||
printf("Identifier: %.*s\n", (int)node->expr.string.len, node->expr.string.start);
|
printf("Identifier: %.*s\n", (int)node->expr.string.len, node->expr.string.start);
|
||||||
break;
|
break;
|
||||||
case NODE_CAST:
|
case NODE_CAST:
|
||||||
printf("Cast: %.*s\n", (int)node->expr.cast.type_len, node->expr.cast.type);
|
printf("Cast:\n");
|
||||||
|
print_ast(node->expr.cast.type, depth);
|
||||||
print_ast(node->expr.cast.value, depth + 1);
|
print_ast(node->expr.cast.value, depth + 1);
|
||||||
break;
|
break;
|
||||||
case NODE_ACCESS:
|
case NODE_ACCESS:
|
||||||
printf("Access:\n");
|
printf("Access:\n");
|
||||||
print_ast(node->expr.access.expr, depth + 1);
|
print_ast(node->expr.access.expr, depth + 1);
|
||||||
print_ast(node->expr.access.member, depth + 1);
|
print_ast(node->expr.access.member, depth + 1);
|
||||||
break;
|
break;
|
||||||
case NODE_LABEL:
|
case NODE_LABEL:
|
||||||
printf("Label: %.*s\n", (int)node->expr.label.name_len, node->expr.label.name);
|
printf("Label: %.*s\n", (int)node->expr.label.name_len, node->expr.label.name);
|
||||||
|
|
@ -134,6 +135,14 @@ void print_ast(ast_node *node, int depth) {
|
||||||
current = current->expr.unit_node.next;
|
current = current->expr.unit_node.next;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NODE_STRUCT_INIT:
|
||||||
|
printf("Struct init:\n");
|
||||||
|
current = node->expr.struct_init.members;
|
||||||
|
while (current && current->type == NODE_UNIT) {
|
||||||
|
print_ast(current->expr.unit_node.expr, depth + 1);
|
||||||
|
current = current->expr.unit_node.next;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case NODE_STRUCT:
|
case NODE_STRUCT:
|
||||||
printf("Struct: %.*s\n", (int)node->expr.structure.name_len, node->expr.structure.name);
|
printf("Struct: %.*s\n", (int)node->expr.structure.name_len, node->expr.structure.name);
|
||||||
member *m = node->expr.structure.members;
|
member *m = node->expr.structure.members;
|
||||||
|
|
@ -164,7 +173,8 @@ void print_ast(ast_node *node, int depth) {
|
||||||
print_ast(node->expr.whle.body, depth + 1);
|
print_ast(node->expr.whle.body, depth + 1);
|
||||||
break;
|
break;
|
||||||
case NODE_VAR_DECL:
|
case NODE_VAR_DECL:
|
||||||
printf("VarDecl: %.*s: %.*s\n", (int)node->expr.var_decl.name_len, node->expr.var_decl.name, (int)node->expr.var_decl.type_len, node->expr.var_decl.type);
|
printf("VarDecl: ");
|
||||||
|
print_ast(node->expr.var_decl.type, 0);
|
||||||
print_ast(node->expr.var_decl.value, depth + 1);
|
print_ast(node->expr.var_decl.value, depth + 1);
|
||||||
break;
|
break;
|
||||||
case NODE_FUNCTION:
|
case NODE_FUNCTION:
|
||||||
|
|
|
||||||
2
lexer.h
2
lexer.h
|
|
@ -16,11 +16,11 @@ typedef enum {
|
||||||
TOKEN_AND, // &
|
TOKEN_AND, // &
|
||||||
TOKEN_HAT, // ^
|
TOKEN_HAT, // ^
|
||||||
TOKEN_PIPE, // |
|
TOKEN_PIPE, // |
|
||||||
TOKEN_EQ, // =
|
|
||||||
TOKEN_ARROW, // ->
|
TOKEN_ARROW, // ->
|
||||||
TOKEN_LSHIFT, // <<
|
TOKEN_LSHIFT, // <<
|
||||||
TOKEN_RSHIFT, // >>
|
TOKEN_RSHIFT, // >>
|
||||||
TOKEN_DOUBLE_EQ, // ==
|
TOKEN_DOUBLE_EQ, // ==
|
||||||
|
TOKEN_EQ, // =
|
||||||
TOKEN_LESS_THAN, // <
|
TOKEN_LESS_THAN, // <
|
||||||
TOKEN_GREATER_THAN, // >
|
TOKEN_GREATER_THAN, // >
|
||||||
TOKEN_LESS_EQ, // <=
|
TOKEN_LESS_EQ, // <=
|
||||||
|
|
|
||||||
217
parser.c
217
parser.c
|
|
@ -8,6 +8,7 @@ bool has_errors = false;
|
||||||
|
|
||||||
ast_node *parse_expression(parser *p);
|
ast_node *parse_expression(parser *p);
|
||||||
static ast_node *parse_statement(parser *p);
|
static ast_node *parse_statement(parser *p);
|
||||||
|
static ast_node *parse_type(parser *p);
|
||||||
|
|
||||||
/* Consume a token in the list. */
|
/* Consume a token in the list. */
|
||||||
static void advance(parser *p)
|
static void advance(parser *p)
|
||||||
|
|
@ -329,8 +330,7 @@ ast_node *parse_unary(parser *p)
|
||||||
advance(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_CAST;
|
node->type = NODE_CAST;
|
||||||
node->expr.cast.type = peek(p)->lexeme;
|
node->expr.cast.type = parse_type(p);
|
||||||
node->expr.cast.type_len = peek(p)->lexeme_len;
|
|
||||||
advance(p);
|
advance(p);
|
||||||
advance(p);
|
advance(p);
|
||||||
node->expr.cast.value = parse_expression(p);
|
node->expr.cast.value = parse_expression(p);
|
||||||
|
|
@ -448,11 +448,86 @@ ast_node *parse_expression(parser *p)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (match(p, TOKEN_LCURLY)) {
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_STRUCT_INIT;
|
||||||
|
|
||||||
|
if (match(p, TOKEN_RCURLY))
|
||||||
|
{
|
||||||
|
node->expr.struct_init.members = NULL;
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
snapshot arena_start = arena_snapshot(p->allocator);
|
||||||
|
node->expr.struct_init.members = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->expr.struct_init.members->type = NODE_UNIT;
|
||||||
|
node->expr.struct_init.members->expr.unit_node.expr = parse_expression(p);
|
||||||
|
ast_node *tail = node->expr.struct_init.members;
|
||||||
|
node->expr.struct_init.members_len = 1;
|
||||||
|
|
||||||
|
/* In this case, there is only one parameter */
|
||||||
|
if (match(p, TOKEN_RCURLY))
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(p, TOKEN_COMMA))
|
||||||
|
{
|
||||||
|
ast_node *expr = parse_expression(p);
|
||||||
|
if (expr)
|
||||||
|
{
|
||||||
|
while (!match(p, TOKEN_RCURLY))
|
||||||
|
{
|
||||||
|
if (!match(p, TOKEN_COMMA))
|
||||||
|
{
|
||||||
|
error(p, "expected `}`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
||||||
|
tail = tail->expr.unit_node.next;
|
||||||
|
tail->type = NODE_UNIT;
|
||||||
|
expr = parse_expression(p);
|
||||||
|
if (!expr)
|
||||||
|
{
|
||||||
|
error(p, "expected `}`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
node->expr.struct_init.members_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tail->expr.unit_node.next = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
tail->expr.unit_node.next->expr.unit_node.expr = expr;
|
||||||
|
tail = tail->expr.unit_node.next;
|
||||||
|
tail->type = NODE_UNIT;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error(p, "expected member initialization.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
error(p, "expected `}`.");
|
||||||
|
arena_reset_to_snapshot(p->allocator, arena_start);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
if (p->tokens && ((p->tokens->type >= TOKEN_DOUBLE_EQ && p->tokens->type <= TOKEN_NOT_EQ) || (p->tokens->type >= TOKEN_LSHIFT_EQ && p->tokens->type <= TOKEN_DOUBLE_AND)))
|
if (p->tokens && ((p->tokens->type >= TOKEN_DOUBLE_EQ && p->tokens->type <= TOKEN_NOT_EQ) || (p->tokens->type >= TOKEN_LSHIFT_EQ && p->tokens->type <= TOKEN_DOUBLE_AND)))
|
||||||
{
|
{
|
||||||
binary_op op;
|
binary_op op;
|
||||||
switch (p->tokens->type)
|
switch (p->tokens->type)
|
||||||
{
|
{
|
||||||
|
case TOKEN_EQ:
|
||||||
|
op = OP_ASSIGN;
|
||||||
|
break;
|
||||||
case TOKEN_DOUBLE_EQ:
|
case TOKEN_DOUBLE_EQ:
|
||||||
op = OP_EQ;
|
op = OP_EQ;
|
||||||
break;
|
break;
|
||||||
|
|
@ -492,6 +567,10 @@ ast_node *parse_expression(parser *p)
|
||||||
node->expr.binary.left = left;
|
node->expr.binary.left = left;
|
||||||
node->expr.binary.operator = op;
|
node->expr.binary.operator = op;
|
||||||
node->expr.binary.right = parse_expression(p);
|
node->expr.binary.right = parse_expression(p);
|
||||||
|
if (!node->expr.binary.right) {
|
||||||
|
error(p, "expected expression.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
@ -688,7 +767,7 @@ static ast_node *parse_if(parser *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
static ast_node *parse_struct(parser *p);
|
static ast_node *parse_struct(parser *p);
|
||||||
static member *parse_member(parser *p)
|
static ast_node *parse_type(parser *p)
|
||||||
{
|
{
|
||||||
ast_node *type = NULL;
|
ast_node *type = NULL;
|
||||||
|
|
||||||
|
|
@ -699,19 +778,53 @@ static member *parse_member(parser *p)
|
||||||
type = parse_struct(p);
|
type = parse_struct(p);
|
||||||
type->type = NODE_UNION;
|
type->type = NODE_UNION;
|
||||||
}
|
}
|
||||||
if (!type) {
|
if (match(p, TOKEN_LSQUARE)) {
|
||||||
type = parse_factor(p);
|
/* Array/slice type */
|
||||||
if (!type) {
|
type = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
error(p, "expected struct definition or identifier.");
|
type->type = NODE_PTR_TYPE;
|
||||||
|
if (match(p, TOKEN_STAR)) {
|
||||||
|
type->expr.ptr_type.flags |= PTR_ARRAY;
|
||||||
|
} else {
|
||||||
|
type->expr.ptr_type.flags |= PTR_SLICE;
|
||||||
|
}
|
||||||
|
type->expr.ptr_type.type = parse_type(p);
|
||||||
|
if (!type->expr.ptr_type.type) {
|
||||||
|
error(p, "expected type.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (type->type != NODE_IDENTIFIER) {
|
if (!match(p, TOKEN_RSQUARE)) {
|
||||||
error(p, "expected struct definition or identifier.");
|
error(p, "expected `]`.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (match(p, TOKEN_STAR)) {
|
||||||
|
type = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
type->type = NODE_PTR_TYPE;
|
||||||
|
type->expr.ptr_type.flags |= PTR_RAW;
|
||||||
|
type->expr.ptr_type.type = parse_type(p);
|
||||||
|
if (!type->expr.ptr_type.type) {
|
||||||
|
error(p, "expected type.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!type) {
|
||||||
|
type = parse_factor(p);
|
||||||
|
if (!type) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (type->type != NODE_IDENTIFIER) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static member *parse_member(parser *p)
|
||||||
|
{
|
||||||
|
ast_node *type = parse_type(p);
|
||||||
|
|
||||||
if (!match_peek(p, TOKEN_IDENTIFIER)) {
|
if (!match_peek(p, TOKEN_IDENTIFIER)) {
|
||||||
error(p, "expected identifier.");
|
error(p, "expected identifier.");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -873,9 +986,7 @@ static ast_node *parse_function(parser *p)
|
||||||
{
|
{
|
||||||
ast_node *fn = arena_alloc(p->allocator, sizeof(ast_node));
|
ast_node *fn = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
fn->type = NODE_FUNCTION;
|
fn->type = NODE_FUNCTION;
|
||||||
fn->expr.function.type = peek(p)->lexeme;
|
fn->expr.function.type = parse_type(p);
|
||||||
fn->expr.function.type_len = peek(p)->lexeme_len;
|
|
||||||
advance(p);
|
|
||||||
fn->expr.function.name = peek(p)->lexeme;
|
fn->expr.function.name = peek(p)->lexeme;
|
||||||
fn->expr.function.name_len = peek(p)->lexeme_len;
|
fn->expr.function.name_len = peek(p)->lexeme_len;
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
@ -883,7 +994,7 @@ static ast_node *parse_function(parser *p)
|
||||||
advance(p);
|
advance(p);
|
||||||
|
|
||||||
if (match(p, TOKEN_RPAREN)) {
|
if (match(p, TOKEN_RPAREN)) {
|
||||||
fn->expr.function.body = parse_compound(p);
|
fn->expr.function.body = parse_compound(p);;
|
||||||
fn->expr.function.parameters = NULL;
|
fn->expr.function.parameters = NULL;
|
||||||
fn->expr.function.parameters_len = 0;
|
fn->expr.function.parameters_len = 0;
|
||||||
return fn;
|
return fn;
|
||||||
|
|
@ -925,6 +1036,39 @@ static ast_node *parse_function(parser *p)
|
||||||
|
|
||||||
static ast_node *parse_statement(parser *p)
|
static ast_node *parse_statement(parser *p)
|
||||||
{
|
{
|
||||||
|
token *current = p->tokens;
|
||||||
|
ast_node *type = parse_type(p);
|
||||||
|
if (type && match_peek(p, TOKEN_IDENTIFIER)) {
|
||||||
|
if (p->tokens->next && p->tokens->next->type == TOKEN_LPAREN) {
|
||||||
|
/* Function definition. */
|
||||||
|
p->tokens = current;
|
||||||
|
return parse_function(p);
|
||||||
|
}
|
||||||
|
p->tokens = current;
|
||||||
|
/* Variable declaration. */
|
||||||
|
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
||||||
|
node->type = NODE_VAR_DECL;
|
||||||
|
node->expr.var_decl.type = parse_type(p);
|
||||||
|
node->expr.var_decl.name = p->tokens->lexeme;
|
||||||
|
node->expr.var_decl.name_len = p->tokens->lexeme_len;
|
||||||
|
advance(p);
|
||||||
|
if (match(p, TOKEN_EQ)) {
|
||||||
|
node->expr.var_decl.value = parse_expression(p);
|
||||||
|
} else {
|
||||||
|
node->expr.var_decl.value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!match(p, TOKEN_SEMICOLON))
|
||||||
|
{
|
||||||
|
error(p, "expected `;` after statement.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
p->tokens = current;
|
||||||
|
}
|
||||||
|
|
||||||
if (match(p, TOKEN_BREAK))
|
if (match(p, TOKEN_BREAK))
|
||||||
{
|
{
|
||||||
if (!match(p, TOKEN_SEMICOLON))
|
if (!match(p, TOKEN_SEMICOLON))
|
||||||
|
|
@ -1027,53 +1171,6 @@ static ast_node *parse_statement(parser *p)
|
||||||
else if (match(p, TOKEN_IF)) {
|
else if (match(p, TOKEN_IF)) {
|
||||||
return parse_if(p);
|
return parse_if(p);
|
||||||
}
|
}
|
||||||
else if (match_peek(p, TOKEN_IDENTIFIER) && p->tokens->next && p->tokens->next->type == TOKEN_EQ)
|
|
||||||
{
|
|
||||||
/* Variable assignment. */
|
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
|
||||||
node->type = NODE_BINARY;
|
|
||||||
node->expr.binary.left = parse_factor(p);
|
|
||||||
advance(p);
|
|
||||||
node->expr.binary.right = parse_expression(p);
|
|
||||||
node->expr.binary.operator = OP_ASSIGN;
|
|
||||||
|
|
||||||
if (!match(p, TOKEN_SEMICOLON))
|
|
||||||
{
|
|
||||||
error(p, "expected `;` after statement.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
else if (match_peek(p, TOKEN_IDENTIFIER) && p->tokens->next && p->tokens->next->type == TOKEN_IDENTIFIER)
|
|
||||||
{
|
|
||||||
if (p->tokens->next->next && p->tokens->next->next->type == TOKEN_LPAREN) {
|
|
||||||
/* Function definition. */
|
|
||||||
return parse_function(p);
|
|
||||||
}
|
|
||||||
/* Variable declaration. */
|
|
||||||
ast_node *node = arena_alloc(p->allocator, sizeof(ast_node));
|
|
||||||
node->type = NODE_VAR_DECL;
|
|
||||||
node->expr.var_decl.type = p->tokens->lexeme;
|
|
||||||
node->expr.var_decl.type_len = p->tokens->lexeme_len;
|
|
||||||
advance(p);
|
|
||||||
node->expr.var_decl.name = p->tokens->lexeme;
|
|
||||||
node->expr.var_decl.name_len = p->tokens->lexeme_len;
|
|
||||||
advance(p);
|
|
||||||
if (match(p, TOKEN_EQ)) {
|
|
||||||
node->expr.var_decl.value = parse_expression(p);
|
|
||||||
} else {
|
|
||||||
node->expr.var_decl.value = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!match(p, TOKEN_SEMICOLON))
|
|
||||||
{
|
|
||||||
error(p, "expected `;` after statement.");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
else if (match(p, TOKEN_STRUCT))
|
else if (match(p, TOKEN_STRUCT))
|
||||||
{
|
{
|
||||||
return parse_struct(p);
|
return parse_struct(p);
|
||||||
|
|
|
||||||
27
parser.h
27
parser.h
|
|
@ -99,14 +99,24 @@ typedef enum {
|
||||||
NODE_UNION,
|
NODE_UNION,
|
||||||
NODE_VAR_DECL,
|
NODE_VAR_DECL,
|
||||||
NODE_FUNCTION,
|
NODE_FUNCTION,
|
||||||
NODE_TERNARY,
|
NODE_PTR_TYPE,
|
||||||
NODE_SWITCH,
|
NODE_TERNARY, /* TODO */
|
||||||
|
NODE_SWITCH, /* TODO */
|
||||||
|
NODE_STRUCT_INIT,
|
||||||
NODE_UNIT,
|
NODE_UNIT,
|
||||||
} node_type;
|
} node_type;
|
||||||
|
|
||||||
|
#define PTR_SLICE 0x0
|
||||||
|
#define PTR_RAW 0x1
|
||||||
|
#define PTR_ARRAY 0x2
|
||||||
|
|
||||||
typedef struct _ast_node {
|
typedef struct _ast_node {
|
||||||
node_type type;
|
node_type type;
|
||||||
union {
|
union {
|
||||||
|
struct {
|
||||||
|
struct _ast_node *type;
|
||||||
|
u8 flags;
|
||||||
|
} ptr_type;
|
||||||
struct {
|
struct {
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
|
|
@ -134,8 +144,7 @@ typedef struct _ast_node {
|
||||||
} ternary;
|
} ternary;
|
||||||
struct {
|
struct {
|
||||||
struct _ast_node *value;
|
struct _ast_node *value;
|
||||||
char *type;
|
struct _ast_node *type;
|
||||||
usize type_len;
|
|
||||||
} cast;
|
} cast;
|
||||||
struct {
|
struct {
|
||||||
struct _ast_node *expr;
|
struct _ast_node *expr;
|
||||||
|
|
@ -183,8 +192,7 @@ typedef struct _ast_node {
|
||||||
struct _ast_node *value;
|
struct _ast_node *value;
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
char *type;
|
struct _ast_node *type;
|
||||||
usize type_len;
|
|
||||||
} var_decl;
|
} var_decl;
|
||||||
struct {
|
struct {
|
||||||
member *members;
|
member *members;
|
||||||
|
|
@ -196,8 +204,7 @@ typedef struct _ast_node {
|
||||||
usize parameters_len;
|
usize parameters_len;
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
char *type;
|
struct _ast_node *type;
|
||||||
usize type_len;
|
|
||||||
struct _ast_node *body;
|
struct _ast_node *body;
|
||||||
} function;
|
} function;
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -205,6 +212,10 @@ typedef struct _ast_node {
|
||||||
char *name;
|
char *name;
|
||||||
usize name_len;
|
usize name_len;
|
||||||
} enm; // enum
|
} enm; // enum
|
||||||
|
struct {
|
||||||
|
struct _ast_node *members;
|
||||||
|
usize members_len;
|
||||||
|
} struct_init;
|
||||||
} expr;
|
} expr;
|
||||||
} ast_node;
|
} ast_node;
|
||||||
|
|
||||||
|
|
|
||||||
5
test.l
5
test.l
|
|
@ -1,4 +1,5 @@
|
||||||
u32 a(u32 a)
|
u32 a()
|
||||||
{
|
{
|
||||||
u32 x = 3;
|
Person v = {x = 3, y = 4, z = 5};
|
||||||
|
return z[0];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue