parsing variable declaration
This commit is contained in:
parent
ffc2c9225f
commit
c89f77dd8e
@ -114,7 +114,7 @@ Statement : NonBlockExpression token(Semicolon) | BlockExpression
|
|||||||
|
|
||||||
Expression : BlockExpression | NonBlockExpression
|
Expression : BlockExpression | NonBlockExpression
|
||||||
|
|
||||||
NonBlockExpression : BoolOrExpression | ReturnExpression
|
NonBlockExpression : ReturnExpression | VariableDeclaration | BoolOrExpression
|
||||||
|
|
||||||
BlockExpression : IfExpression | Block
|
BlockExpression : IfExpression | Block
|
||||||
|
|
||||||
@ -122,6 +122,8 @@ BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndEx
|
|||||||
|
|
||||||
ReturnExpression : token(Return) option(Expression)
|
ReturnExpression : token(Return) option(Expression)
|
||||||
|
|
||||||
|
VariableDeclaration : token(Let) token(Symbole) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
|
||||||
|
|
||||||
IfExpression : token(If) Expression Block option(Else | ElseIf)
|
IfExpression : token(If) Expression Block option(Else | ElseIf)
|
||||||
|
|
||||||
ElseIf : token(Else) IfExpression
|
ElseIf : token(Else) IfExpression
|
||||||
|
14
example/expressions/expressions.zig
Normal file
14
example/expressions/expressions.zig
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#link("c")
|
||||||
|
extern {
|
||||||
|
fn puts(s: *const u8) -> i32;
|
||||||
|
fn exit(code: i32) -> unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
export fn _start() -> unreachable {
|
||||||
|
let a : i32 = 1;
|
||||||
|
let b = 2;
|
||||||
|
let c : i32;
|
||||||
|
// let d; // compile error
|
||||||
|
puts("Hello, world!");
|
||||||
|
exit(a + b);
|
||||||
|
}
|
@ -277,6 +277,7 @@ static void preview_function_declarations(CodeGen *g, ImportTableEntry *import,
|
|||||||
case NodeTypeType:
|
case NodeTypeType:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeBlock:
|
case NodeTypeBlock:
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
@ -373,6 +374,14 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
{
|
||||||
|
zig_panic("TODO: analyze variable declaration");
|
||||||
|
|
||||||
|
return_type = g->builtin_types.entry_void;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
{
|
{
|
||||||
switch (node->data.bin_op_expr.bin_op) {
|
switch (node->data.bin_op_expr.bin_op) {
|
||||||
@ -630,6 +639,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
|||||||
case NodeTypeType:
|
case NodeTypeType:
|
||||||
case NodeTypeFnDecl:
|
case NodeTypeFnDecl:
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
case NodeTypeRoot:
|
case NodeTypeRoot:
|
||||||
case NodeTypeBlock:
|
case NodeTypeBlock:
|
||||||
case NodeTypeBinOpExpr:
|
case NodeTypeBinOpExpr:
|
||||||
|
@ -477,6 +477,8 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *node) {
|
|||||||
return gen_bin_op_expr(g, node);
|
return gen_bin_op_expr(g, node);
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
return gen_return_expr(g, node);
|
return gen_return_expr(g, node);
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
zig_panic("TODO: variable declaration code gen");
|
||||||
case NodeTypeCastExpr:
|
case NodeTypeCastExpr:
|
||||||
return gen_cast_expr(g, node);
|
return gen_cast_expr(g, node);
|
||||||
case NodeTypePrefixOpExpr:
|
case NodeTypePrefixOpExpr:
|
||||||
|
@ -75,6 +75,8 @@ const char *node_type_str(NodeType node_type) {
|
|||||||
return "Directive";
|
return "Directive";
|
||||||
case NodeTypeReturnExpr:
|
case NodeTypeReturnExpr:
|
||||||
return "ReturnExpr";
|
return "ReturnExpr";
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
return "VariableDeclaration";
|
||||||
case NodeTypeCastExpr:
|
case NodeTypeCastExpr:
|
||||||
return "CastExpr";
|
return "CastExpr";
|
||||||
case NodeTypeNumberLiteral:
|
case NodeTypeNumberLiteral:
|
||||||
@ -178,6 +180,16 @@ void ast_print(AstNode *node, int indent) {
|
|||||||
if (node->data.return_expr.expr)
|
if (node->data.return_expr.expr)
|
||||||
ast_print(node->data.return_expr.expr, indent + 2);
|
ast_print(node->data.return_expr.expr, indent + 2);
|
||||||
break;
|
break;
|
||||||
|
case NodeTypeVariableDeclaration:
|
||||||
|
{
|
||||||
|
Buf *name_buf = &node->data.variable_declaration.symbol;
|
||||||
|
fprintf(stderr, "%s '%s'\n", node_type_str(node->type), buf_ptr(name_buf));
|
||||||
|
if (node->data.variable_declaration.type)
|
||||||
|
ast_print(node->data.variable_declaration.type, indent + 2);
|
||||||
|
if (node->data.variable_declaration.expr)
|
||||||
|
ast_print(node->data.variable_declaration.expr, indent + 2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case NodeTypeExternBlock:
|
case NodeTypeExternBlock:
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s\n", node_type_str(node->type));
|
fprintf(stderr, "%s\n", node_type_str(node->type));
|
||||||
@ -1042,6 +1054,45 @@ static AstNode *ast_parse_return_expr(ParseContext *pc, int *token_index, bool m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
VariableDeclaration : token(Let) token(Symbole) (token(Eq) Expression | token(Colon) Type option(token(Eq) Expression))
|
||||||
|
*/
|
||||||
|
static AstNode *ast_parse_variable_declaration_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
|
Token *let_tok = &pc->tokens->at(*token_index);
|
||||||
|
if (let_tok->id == TokenIdKeywordLet) {
|
||||||
|
*token_index += 1;
|
||||||
|
AstNode *node = ast_create_node(pc, NodeTypeVariableDeclaration, let_tok);
|
||||||
|
|
||||||
|
Token *name_token = &pc->tokens->at(*token_index);
|
||||||
|
*token_index += 1;
|
||||||
|
ast_expect_token(pc, name_token, TokenIdSymbol);
|
||||||
|
ast_buf_from_token(pc, name_token, &node->data.variable_declaration.symbol);
|
||||||
|
|
||||||
|
Token *eq_or_colon = &pc->tokens->at(*token_index);
|
||||||
|
*token_index += 1;
|
||||||
|
if (eq_or_colon->id == TokenIdEq) {
|
||||||
|
node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
|
||||||
|
return node;
|
||||||
|
} else if (eq_or_colon->id == TokenIdColon) {
|
||||||
|
node->data.variable_declaration.type = ast_parse_type(pc, *token_index, token_index);
|
||||||
|
|
||||||
|
Token *eq_token = &pc->tokens->at(*token_index);
|
||||||
|
if (eq_token->id == TokenIdEq) {
|
||||||
|
*token_index += 1;
|
||||||
|
|
||||||
|
node->data.variable_declaration.expr = ast_parse_expression(pc, token_index, true);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
ast_invalid_token_error(pc, eq_or_colon);
|
||||||
|
}
|
||||||
|
} else if (mandatory) {
|
||||||
|
ast_invalid_token_error(pc, let_tok);
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression
|
BoolOrExpression : BoolAndExpression token(BoolOr) BoolAndExpression | BoolAndExpression
|
||||||
*/
|
*/
|
||||||
@ -1086,19 +1137,23 @@ static AstNode *ast_parse_block_expr(ParseContext *pc, int *token_index, bool ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
NonBlockExpression : BoolOrExpression | ReturnExpression
|
NonBlockExpression : ReturnExpression | VariableDeclaration | BoolOrExpression
|
||||||
*/
|
*/
|
||||||
static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
static AstNode *ast_parse_non_block_expr(ParseContext *pc, int *token_index, bool mandatory) {
|
||||||
Token *token = &pc->tokens->at(*token_index);
|
Token *token = &pc->tokens->at(*token_index);
|
||||||
|
|
||||||
AstNode *bool_or_expr = ast_parse_bool_or_expr(pc, token_index, false);
|
|
||||||
if (bool_or_expr)
|
|
||||||
return bool_or_expr;
|
|
||||||
|
|
||||||
AstNode *return_expr = ast_parse_return_expr(pc, token_index, false);
|
AstNode *return_expr = ast_parse_return_expr(pc, token_index, false);
|
||||||
if (return_expr)
|
if (return_expr)
|
||||||
return return_expr;
|
return return_expr;
|
||||||
|
|
||||||
|
AstNode *variable_declaration_expr = ast_parse_variable_declaration_expr(pc, token_index, false);
|
||||||
|
if (variable_declaration_expr)
|
||||||
|
return variable_declaration_expr;
|
||||||
|
|
||||||
|
AstNode *bool_or_expr = ast_parse_bool_or_expr(pc, token_index, false);
|
||||||
|
if (bool_or_expr)
|
||||||
|
return bool_or_expr;
|
||||||
|
|
||||||
if (mandatory)
|
if (mandatory)
|
||||||
ast_invalid_token_error(pc, token);
|
ast_invalid_token_error(pc, token);
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ enum NodeType {
|
|||||||
NodeTypeExternBlock,
|
NodeTypeExternBlock,
|
||||||
NodeTypeDirective,
|
NodeTypeDirective,
|
||||||
NodeTypeReturnExpr,
|
NodeTypeReturnExpr,
|
||||||
|
NodeTypeVariableDeclaration,
|
||||||
NodeTypeBinOpExpr,
|
NodeTypeBinOpExpr,
|
||||||
NodeTypeCastExpr,
|
NodeTypeCastExpr,
|
||||||
NodeTypeNumberLiteral,
|
NodeTypeNumberLiteral,
|
||||||
@ -95,6 +96,13 @@ struct AstNodeReturnExpr {
|
|||||||
AstNode *expr;
|
AstNode *expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AstNodeVariableDeclaration {
|
||||||
|
Buf symbol;
|
||||||
|
// one or both of type and expr will be non null
|
||||||
|
AstNode *type;
|
||||||
|
AstNode *expr;
|
||||||
|
};
|
||||||
|
|
||||||
enum BinOpType {
|
enum BinOpType {
|
||||||
BinOpTypeInvalid,
|
BinOpTypeInvalid,
|
||||||
// TODO: include assignment?
|
// TODO: include assignment?
|
||||||
@ -190,6 +198,7 @@ struct AstNode {
|
|||||||
AstNodeParamDecl param_decl;
|
AstNodeParamDecl param_decl;
|
||||||
AstNodeBlock block;
|
AstNodeBlock block;
|
||||||
AstNodeReturnExpr return_expr;
|
AstNodeReturnExpr return_expr;
|
||||||
|
AstNodeVariableDeclaration variable_declaration;
|
||||||
AstNodeBinOpExpr bin_op_expr;
|
AstNodeBinOpExpr bin_op_expr;
|
||||||
AstNodeExternBlock extern_block;
|
AstNodeExternBlock extern_block;
|
||||||
AstNodeDirective directive;
|
AstNodeDirective directive;
|
||||||
|
@ -165,6 +165,8 @@ static void end_token(Tokenize *t) {
|
|||||||
t->cur_tok->id = TokenIdKeywordFn;
|
t->cur_tok->id = TokenIdKeywordFn;
|
||||||
} else if (mem_eql_str(token_mem, token_len, "return")) {
|
} else if (mem_eql_str(token_mem, token_len, "return")) {
|
||||||
t->cur_tok->id = TokenIdKeywordReturn;
|
t->cur_tok->id = TokenIdKeywordReturn;
|
||||||
|
} else if (mem_eql_str(token_mem, token_len, "let")) {
|
||||||
|
t->cur_tok->id = TokenIdKeywordLet;
|
||||||
} else if (mem_eql_str(token_mem, token_len, "mut")) {
|
} else if (mem_eql_str(token_mem, token_len, "mut")) {
|
||||||
t->cur_tok->id = TokenIdKeywordMut;
|
t->cur_tok->id = TokenIdKeywordMut;
|
||||||
} else if (mem_eql_str(token_mem, token_len, "const")) {
|
} else if (mem_eql_str(token_mem, token_len, "const")) {
|
||||||
@ -574,6 +576,7 @@ static const char * token_name(Token *token) {
|
|||||||
case TokenIdKeywordConst: return "Const";
|
case TokenIdKeywordConst: return "Const";
|
||||||
case TokenIdKeywordMut: return "Mut";
|
case TokenIdKeywordMut: return "Mut";
|
||||||
case TokenIdKeywordReturn: return "Return";
|
case TokenIdKeywordReturn: return "Return";
|
||||||
|
case TokenIdKeywordLet: return "Let";
|
||||||
case TokenIdKeywordExtern: return "Extern";
|
case TokenIdKeywordExtern: return "Extern";
|
||||||
case TokenIdKeywordUnreachable: return "Unreachable";
|
case TokenIdKeywordUnreachable: return "Unreachable";
|
||||||
case TokenIdKeywordPub: return "Pub";
|
case TokenIdKeywordPub: return "Pub";
|
||||||
|
@ -15,6 +15,7 @@ enum TokenId {
|
|||||||
TokenIdSymbol,
|
TokenIdSymbol,
|
||||||
TokenIdKeywordFn,
|
TokenIdKeywordFn,
|
||||||
TokenIdKeywordReturn,
|
TokenIdKeywordReturn,
|
||||||
|
TokenIdKeywordLet,
|
||||||
TokenIdKeywordMut,
|
TokenIdKeywordMut,
|
||||||
TokenIdKeywordConst,
|
TokenIdKeywordConst,
|
||||||
TokenIdKeywordExtern,
|
TokenIdKeywordExtern,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user