Swinging in a different direction, different syntax
This commit is contained in:
240
parse_decl.c
240
parse_decl.c
@@ -1,50 +1,168 @@
|
||||
global Intern_String intern_empty;
|
||||
|
||||
|
||||
function Token *
|
||||
parse__get_name(Parser *p){
|
||||
Token *name = token_next(p);
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
return name;
|
||||
}
|
||||
|
||||
function void
|
||||
parse_note_list(Parser *ctx, AST_Node *parent) {
|
||||
if(token_match(ctx, TK_OpenParen)) {
|
||||
do {
|
||||
Token *name = token_expect(ctx, TK_Identifier);
|
||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
||||
ast_node_push_note(parent, current);
|
||||
parse_note_list(ctx, current);
|
||||
if(token_match(ctx, TK_Assign)) {
|
||||
current->expr = parse_expr(ctx);
|
||||
}
|
||||
} while(token_match(ctx, TK_Comma));
|
||||
token_expect(ctx, TK_CloseParen);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
parse__notes(Parser *ctx, AST_Node *result) {
|
||||
while(token_match(ctx, TK_At)) {
|
||||
Token *name = token_expect(ctx, TK_Identifier);
|
||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
||||
ast_node_push_note(result, current);
|
||||
parse_note_list(ctx, current);
|
||||
if(token_match(ctx, TK_Assign)) {
|
||||
current->expr = parse_expr(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AST_Node
|
||||
parse_notes(Parser *p){
|
||||
AST_Node result = {};
|
||||
parse__notes(p, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_enum(Parser *p){
|
||||
parse_enum(Parser *p, Token *name){
|
||||
AST_Node *result = 0;
|
||||
Token *name = token_match(p, TK_Identifier);
|
||||
if(token_match(p, TK_OpenBrace)){
|
||||
Token *op_close_brace = token_match(p, TK_CloseBrace);
|
||||
|
||||
if(!op_close_brace){
|
||||
|
||||
result = ast_enum(p, name, name->intern_val);
|
||||
do{ // Parse enum members
|
||||
Token *identifier = token_match(p, TK_Identifier);
|
||||
if(identifier){
|
||||
Expr *expr = 0;
|
||||
if(token_match(p, TK_Assign)){
|
||||
expr = parse_expr(p);
|
||||
}
|
||||
AST_Node *child = ast_enum_child(p, identifier, identifier->intern_val, expr);
|
||||
ast_node_push_child(result, child);
|
||||
{
|
||||
// Insert into scope
|
||||
}
|
||||
if(token_expect(p, TK_OpenBrace)){
|
||||
result = ast_enum(p, name, name->intern_val);
|
||||
do{
|
||||
AST_Node notes = parse_notes(p);
|
||||
Token *token = token_match(p, TK_Identifier);
|
||||
if(token){
|
||||
Expr *expr = 0;
|
||||
if(token_match(p, TK_Assign)){
|
||||
expr = parse_expr(p);
|
||||
}
|
||||
else {
|
||||
parser_push_error(p, token_get(p), "invalid syntax of enum member");
|
||||
|
||||
AST_Node *child = ast_enum_child(p, token, token->intern_val, expr);
|
||||
ast_node_pass_note_list(child,¬es);
|
||||
ast_node_push_child(result, child);
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
} while(token_match(p, TK_Comma));
|
||||
token_expect(p, TK_CloseBrace);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_variable(Parser *p, Token *name){
|
||||
AST_Node *result = 0;
|
||||
Token *type_token = token_expect(p, TK_Identifier);
|
||||
if(type_token){
|
||||
AST_Node *type = symbol_require_type(p, type_token);
|
||||
Token *star;
|
||||
while((star = token_match(p, TK_Mul))){
|
||||
type = ast_type_pointer(p, star, type);
|
||||
}
|
||||
while((star = token_match(p, TK_OpenBracket))){
|
||||
Expr *expr = parse_expr(p);
|
||||
type = ast_type_array(p, star, type, expr);
|
||||
token_expect(p, TK_CloseBracket);
|
||||
}
|
||||
Expr *expr = 0;
|
||||
if(token_match(p, TK_Assign)){
|
||||
expr = parse_expr(p);
|
||||
}
|
||||
result = ast_variable(p, name, name->intern_val, type, expr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
|
||||
AST_Node *result = 0;
|
||||
if(token_expect(p, TK_OpenBrace)){
|
||||
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
|
||||
if(is_global) symbol_register(p, result);
|
||||
|
||||
for(;;){
|
||||
AST_Node notes = parse_notes(p);
|
||||
AST_Node *mem = 0;
|
||||
Token *mem_name = token_match(p, TK_Identifier);
|
||||
if(mem_name){
|
||||
if(token_expect(p, TK_Colon)){
|
||||
|
||||
if(token_match_keyword(p, keyword_struct)){
|
||||
mem = parse_struct(p, mem_name, AK_Struct, false);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_union)){
|
||||
mem = parse_struct(p, mem_name, AK_Union, false);
|
||||
}
|
||||
//else if(token_match_keyword(p, keyword_enum)){
|
||||
//mem = parse_enum(p, mem_name);
|
||||
//}
|
||||
else if(token_is(p, TK_Identifier)){
|
||||
mem = parse_variable(p, mem_name);
|
||||
token_expect(p, TK_Semicolon);
|
||||
}
|
||||
else parser_push_error(p, mem_name, "Unrecognized token while parsing struct");
|
||||
|
||||
if(mem){
|
||||
ast_node_pass_note_list(mem, ¬es);
|
||||
ast_node_push_child(result, mem);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
} while(token_match(p, TK_Comma));
|
||||
token_expect(p, TK_CloseBrace);
|
||||
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, op_close_brace, "enum without body");
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_union) &&
|
||||
token_match(p, TK_Colon)){
|
||||
mem = parse_struct(p, 0, AK_Union, false);
|
||||
ast_node_pass_note_list(mem, ¬es);
|
||||
ast_node_push_child(result, mem);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_struct) &&
|
||||
token_match(p, TK_Colon)){
|
||||
mem = parse_struct(p, 0, AK_Struct, false);
|
||||
ast_node_pass_note_list(mem, ¬es);
|
||||
ast_node_push_child(result, mem);
|
||||
}
|
||||
else if(token_expect(p, TK_CloseBrace)){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(name == 0){
|
||||
parser_push_error(p, token_get(p), "enum without name or body is illegal");
|
||||
}
|
||||
}
|
||||
|
||||
if(ast_is_named(result)){
|
||||
// Insert into scope
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_typedef(Parser *p, Token *name){
|
||||
Token *type_token = token_expect(p, TK_Identifier);
|
||||
AST_Node *type = symbol_require_type(p, type_token);
|
||||
AST_Node *result = ast_typedef(p, name, name->intern_val, type);
|
||||
token_expect(p, TK_Semicolon);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -54,6 +172,7 @@ parse(Parser *p){
|
||||
|
||||
for(;;){
|
||||
AST_Node *node = 0;
|
||||
AST_Node notes = parse_notes(p);
|
||||
|
||||
if(token_is(p, TK_End)){
|
||||
break;
|
||||
@@ -61,29 +180,40 @@ parse(Parser *p){
|
||||
else if(token_is(p, TK_Error)){
|
||||
break;
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_struct)){
|
||||
|
||||
else if(token_is(p, TK_Identifier) && // Peeking to be more error averse
|
||||
token_peek_is(p, 1, TK_Colon)){
|
||||
if(token_peek_is_keyword(p, 2, keyword_struct)){
|
||||
node = parse_struct(p, parse__get_name(p), AK_Struct, true);
|
||||
symbol_register(p, node);
|
||||
}
|
||||
else if(token_peek_is_keyword(p, 2, keyword_union)){
|
||||
node = parse_struct(p, parse__get_name(p), AK_Union, true);
|
||||
symbol_register(p, node);
|
||||
}
|
||||
else if(token_peek_is_keyword(p, 2, keyword_enum)){
|
||||
node = parse_enum(p, parse__get_name(p));
|
||||
symbol_register(p, node);
|
||||
}
|
||||
else if(token_peek_is_keyword(p, 2, keyword_typedef)){
|
||||
node = parse_typedef(p, parse__get_name(p));
|
||||
symbol_register(p, node);
|
||||
}
|
||||
else{
|
||||
token_next(p);
|
||||
}
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_union)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_enum)){
|
||||
node = parse_enum(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_function)){
|
||||
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_typedef)){
|
||||
|
||||
}
|
||||
else {
|
||||
else{
|
||||
token_next(p);
|
||||
}
|
||||
|
||||
|
||||
if(node){
|
||||
ast_node_pass_note_list(node, ¬es);
|
||||
ast_node_push_child(result, node);
|
||||
}
|
||||
else if(notes.first_note != 0){
|
||||
parser_push_error(p, token_get(p), "Warning: notes got lost");
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user