diff --git a/cinc.xcodeproj/project.pbxproj b/cinc.xcodeproj/project.pbxproj index e854bc5..129f18c 100644 --- a/cinc.xcodeproj/project.pbxproj +++ b/cinc.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ F61910692142A8C5003B8798 /* tokenize.c in Sources */ = {isa = PBXBuildFile; fileRef = F61910682142A8C5003B8798 /* tokenize.c */; }; F65A954E21454B31005FCAF5 /* token.c in Sources */ = {isa = PBXBuildFile; fileRef = F65A954D21454B31005FCAF5 /* token.c */; }; F661C333214590930021FCCE /* parser.c in Sources */ = {isa = PBXBuildFile; fileRef = F661C332214590930021FCCE /* parser.c */; }; + F661C3362145CE760021FCCE /* ast.c in Sources */ = {isa = PBXBuildFile; fileRef = F661C3352145CE760021FCCE /* ast.c */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -34,6 +35,8 @@ F65A954D21454B31005FCAF5 /* token.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = token.c; sourceTree = ""; }; F661C331214590930021FCCE /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; F661C332214590930021FCCE /* parser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = ""; }; + F661C3342145CE760021FCCE /* ast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ast.h; sourceTree = ""; }; + F661C3352145CE760021FCCE /* ast.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ast.c; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,6 +76,8 @@ F65A954C21454B21005FCAF5 /* token.h */, F661C331214590930021FCCE /* parser.h */, F661C332214590930021FCCE /* parser.c */, + F661C3342145CE760021FCCE /* ast.h */, + F661C3352145CE760021FCCE /* ast.c */, ); path = cinc; sourceTree = ""; @@ -134,6 +139,7 @@ buildActionMask = 2147483647; files = ( F65A954E21454B31005FCAF5 /* token.c in Sources */, + F661C3362145CE760021FCCE /* ast.c in Sources */, F61910692142A8C5003B8798 /* tokenize.c in Sources */, F661C333214590930021FCCE /* parser.c in Sources */, F61910612142A876003B8798 /* main.c in Sources */, diff --git a/cinc/ast.c b/cinc/ast.c new file mode 100644 index 0000000..026e865 --- /dev/null +++ b/cinc/ast.c @@ -0,0 +1,39 @@ +// +// ast.c +// cinc +// +// Created by Peter Terpstra on 9/9/18. +// Copyright © 2018 Peter Terpstra. All rights reserved. +// + +#include "ast.h" +#include + +#define AST_CHILDREN_START 10 + +AstNode* make_node(const char* data) { + AstNode* node=malloc(sizeof(AstNode)); + node->data=data; + node->num_children=0; + node->max_children=AST_CHILDREN_START; + node->children=malloc(sizeof(AstNode*)*AST_CHILDREN_START); + return node; +} + +void add_child(AstNode* parent,AstNode* child) { + if (parent->num_children==parent->max_children) { + parent->children=realloc(parent->children, sizeof(AstNode*)*(parent->max_children+10)); + (parent->max_children)+=10; + } + parent->children[parent->num_children]=child; + parent->num_children++; +} + +void free_tree(AstNode* root) { + if (root->children) { + for (int i=0;i<(root->num_children);i++) { + free_tree(root->children[i]); + } + } + free(root); +} diff --git a/cinc/ast.h b/cinc/ast.h new file mode 100644 index 0000000..61e8da6 --- /dev/null +++ b/cinc/ast.h @@ -0,0 +1,25 @@ +// +// ast.h +// cinc +// +// Created by Peter Terpstra on 9/9/18. +// Copyright © 2018 Peter Terpstra. All rights reserved. +// + +#ifndef ast_h +#define ast_h + +struct _astnode { + const char* data; + int num_children; + int max_children; + struct _astnode** children; +}; + +typedef struct _astnode AstNode; + +AstNode* make_node(const char* data); +void add_child(AstNode* parent,AstNode* child); +void free_tree(AstNode* root); + +#endif /* ast_h */ diff --git a/cinc/main.c b/cinc/main.c index 6e912f6..8ea8dfe 100644 --- a/cinc/main.c +++ b/cinc/main.c @@ -10,17 +10,12 @@ #include #include #include "tokenize.h" +#include "ast.h" +#include "parser.h" int main(int argc, const char * argv[]) { char* prgstr="int main() {\nreturn 0;\n}"; Token* tokens=tokenize(prgstr); - Token* tok=tokens; - while (tok) { - print_tok(tok); - if (tok->type==TYPE_EOF) { - break; - } - tok=tok->next; - } + AstNode* ast=parse(tokens); free_toklist(tokens); } diff --git a/cinc/parser.c b/cinc/parser.c index 942048d..c504c24 100644 --- a/cinc/parser.c +++ b/cinc/parser.c @@ -8,7 +8,10 @@ #include "parser.h" #include "token.h" +#include "ast.h" #include +#include +#include static Token lahead; @@ -32,11 +35,11 @@ static const char* getid() { return id; } -static int get_num() { +static const char* get_num() { if (lahead.type!=TYPE_NUM) { exit(1); } - int num=lahead.val->intval; + const char* num=lahead.val->strval; advance(); return num; } @@ -50,18 +53,52 @@ static const char* gettype() { return id; } -static char** func() { +static AstNode* expr() { + AstNode* expr_root=make_node("num"); + add_child(expr_root, make_node(get_num())); + return expr_root; +} + +static AstNode* statement() { + switch (lahead.type) { + case TYPE_RETURN: { + match(TYPE_RETURN); + AstNode* return_root=make_node("return"); + add_child(return_root, expr()); + match(';'); + return return_root; + } + default: + printf("Error: Expected statement"); + exit(1); + } +} + + +static AstNode* block() { + match('{'); + AstNode* block_root=make_node("block"); + while (lahead.type!='}') { + add_child(block_root, statement()); + } + match('}'); + return block_root; +} + +static AstNode* func() { const char* type=gettype(); const char* name=getid(); match('('); match(')'); - match('{'); - //block code here - match('}'); - //return ast here + AstNode* func_block=block(); + AstNode* func_root=make_node("func"); + add_child(func_root, make_node(type)); + add_child(func_root, make_node(name)); + add_child(func_root, func_block); + return func_root; } -char** parse(Token* prg) { +AstNode* parse(Token* prg) { lahead=*(prg); return func(); } diff --git a/cinc/parser.h b/cinc/parser.h index 10a0764..17c744f 100644 --- a/cinc/parser.h +++ b/cinc/parser.h @@ -9,6 +9,9 @@ #ifndef parser_h #define parser_h -#include +#include "token.h" +#include "ast.h" + +AstNode* parse(Token* prg); #endif /* parser_h */ diff --git a/cinc/tokenize.c b/cinc/tokenize.c index ea6e360..e5f82e1 100644 --- a/cinc/tokenize.c +++ b/cinc/tokenize.c @@ -44,14 +44,14 @@ Token* next_token(int* strpos, char* prg, Token* prev) { } return new_token(TYPE_IDENT, val_from_str(id), prev); } else if (isdigit(current)) { - char* id=malloc(sizeof(char)*ID_MAX_SIZE+1); + char* num=malloc(sizeof(char)*ID_MAX_SIZE+1); int length=1; - id[0]=current; + num[0]=current; (*strpos)++; while (true) { current=prg[*strpos]; if (isdigit(current)) { - id[length]=current; + num[length]=current; length++; (*strpos)++; } else { @@ -61,8 +61,8 @@ Token* next_token(int* strpos, char* prg, Token* prev) { break; } } - id[length]=0; - return new_token(TYPE_NUM, val_from_int(atoi(id)), prev); + num[length]=0; + return new_token(TYPE_NUM, val_from_str(num), prev); } else if (isblank(current) || current=='\n') { (*strpos)++; current=prg[*strpos];