Parser working
This commit is contained in:
parent
a75baf7296
commit
b94fa9d49a
@ -11,6 +11,7 @@
|
|||||||
F61910692142A8C5003B8798 /* tokenize.c in Sources */ = {isa = PBXBuildFile; fileRef = F61910682142A8C5003B8798 /* tokenize.c */; };
|
F61910692142A8C5003B8798 /* tokenize.c in Sources */ = {isa = PBXBuildFile; fileRef = F61910682142A8C5003B8798 /* tokenize.c */; };
|
||||||
F65A954E21454B31005FCAF5 /* token.c in Sources */ = {isa = PBXBuildFile; fileRef = F65A954D21454B31005FCAF5 /* token.c */; };
|
F65A954E21454B31005FCAF5 /* token.c in Sources */ = {isa = PBXBuildFile; fileRef = F65A954D21454B31005FCAF5 /* token.c */; };
|
||||||
F661C333214590930021FCCE /* parser.c in Sources */ = {isa = PBXBuildFile; fileRef = F661C332214590930021FCCE /* parser.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 */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
@ -34,6 +35,8 @@
|
|||||||
F65A954D21454B31005FCAF5 /* token.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = token.c; sourceTree = "<group>"; };
|
F65A954D21454B31005FCAF5 /* token.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = token.c; sourceTree = "<group>"; };
|
||||||
F661C331214590930021FCCE /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
|
F661C331214590930021FCCE /* parser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = "<group>"; };
|
||||||
F661C332214590930021FCCE /* parser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = "<group>"; };
|
F661C332214590930021FCCE /* parser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = parser.c; sourceTree = "<group>"; };
|
||||||
|
F661C3342145CE760021FCCE /* ast.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ast.h; sourceTree = "<group>"; };
|
||||||
|
F661C3352145CE760021FCCE /* ast.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ast.c; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -73,6 +76,8 @@
|
|||||||
F65A954C21454B21005FCAF5 /* token.h */,
|
F65A954C21454B21005FCAF5 /* token.h */,
|
||||||
F661C331214590930021FCCE /* parser.h */,
|
F661C331214590930021FCCE /* parser.h */,
|
||||||
F661C332214590930021FCCE /* parser.c */,
|
F661C332214590930021FCCE /* parser.c */,
|
||||||
|
F661C3342145CE760021FCCE /* ast.h */,
|
||||||
|
F661C3352145CE760021FCCE /* ast.c */,
|
||||||
);
|
);
|
||||||
path = cinc;
|
path = cinc;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -134,6 +139,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
F65A954E21454B31005FCAF5 /* token.c in Sources */,
|
F65A954E21454B31005FCAF5 /* token.c in Sources */,
|
||||||
|
F661C3362145CE760021FCCE /* ast.c in Sources */,
|
||||||
F61910692142A8C5003B8798 /* tokenize.c in Sources */,
|
F61910692142A8C5003B8798 /* tokenize.c in Sources */,
|
||||||
F661C333214590930021FCCE /* parser.c in Sources */,
|
F661C333214590930021FCCE /* parser.c in Sources */,
|
||||||
F61910612142A876003B8798 /* main.c in Sources */,
|
F61910612142A876003B8798 /* main.c in Sources */,
|
||||||
|
39
cinc/ast.c
Normal file
39
cinc/ast.c
Normal file
@ -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 <stdlib.h>
|
||||||
|
|
||||||
|
#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);
|
||||||
|
}
|
25
cinc/ast.h
Normal file
25
cinc/ast.h
Normal file
@ -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 */
|
11
cinc/main.c
11
cinc/main.c
@ -10,17 +10,12 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "tokenize.h"
|
#include "tokenize.h"
|
||||||
|
#include "ast.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
int main(int argc, const char * argv[]) {
|
int main(int argc, const char * argv[]) {
|
||||||
char* prgstr="int main() {\nreturn 0;\n}";
|
char* prgstr="int main() {\nreturn 0;\n}";
|
||||||
Token* tokens=tokenize(prgstr);
|
Token* tokens=tokenize(prgstr);
|
||||||
Token* tok=tokens;
|
AstNode* ast=parse(tokens);
|
||||||
while (tok) {
|
|
||||||
print_tok(tok);
|
|
||||||
if (tok->type==TYPE_EOF) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
tok=tok->next;
|
|
||||||
}
|
|
||||||
free_toklist(tokens);
|
free_toklist(tokens);
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,10 @@
|
|||||||
|
|
||||||
#include "parser.h"
|
#include "parser.h"
|
||||||
#include "token.h"
|
#include "token.h"
|
||||||
|
#include "ast.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
static Token lahead;
|
static Token lahead;
|
||||||
|
|
||||||
@ -32,11 +35,11 @@ static const char* getid() {
|
|||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_num() {
|
static const char* get_num() {
|
||||||
if (lahead.type!=TYPE_NUM) {
|
if (lahead.type!=TYPE_NUM) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
int num=lahead.val->intval;
|
const char* num=lahead.val->strval;
|
||||||
advance();
|
advance();
|
||||||
return num;
|
return num;
|
||||||
}
|
}
|
||||||
@ -50,18 +53,52 @@ static const char* gettype() {
|
|||||||
return id;
|
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* type=gettype();
|
||||||
const char* name=getid();
|
const char* name=getid();
|
||||||
match('(');
|
match('(');
|
||||||
match(')');
|
match(')');
|
||||||
match('{');
|
AstNode* func_block=block();
|
||||||
//block code here
|
AstNode* func_root=make_node("func");
|
||||||
match('}');
|
add_child(func_root, make_node(type));
|
||||||
//return ast here
|
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);
|
lahead=*(prg);
|
||||||
return func();
|
return func();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,9 @@
|
|||||||
#ifndef parser_h
|
#ifndef parser_h
|
||||||
#define parser_h
|
#define parser_h
|
||||||
|
|
||||||
#include <stdio.h>
|
#include "token.h"
|
||||||
|
#include "ast.h"
|
||||||
|
|
||||||
|
AstNode* parse(Token* prg);
|
||||||
|
|
||||||
#endif /* parser_h */
|
#endif /* parser_h */
|
||||||
|
@ -44,14 +44,14 @@ Token* next_token(int* strpos, char* prg, Token* prev) {
|
|||||||
}
|
}
|
||||||
return new_token(TYPE_IDENT, val_from_str(id), prev);
|
return new_token(TYPE_IDENT, val_from_str(id), prev);
|
||||||
} else if (isdigit(current)) {
|
} 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;
|
int length=1;
|
||||||
id[0]=current;
|
num[0]=current;
|
||||||
(*strpos)++;
|
(*strpos)++;
|
||||||
while (true) {
|
while (true) {
|
||||||
current=prg[*strpos];
|
current=prg[*strpos];
|
||||||
if (isdigit(current)) {
|
if (isdigit(current)) {
|
||||||
id[length]=current;
|
num[length]=current;
|
||||||
length++;
|
length++;
|
||||||
(*strpos)++;
|
(*strpos)++;
|
||||||
} else {
|
} else {
|
||||||
@ -61,8 +61,8 @@ Token* next_token(int* strpos, char* prg, Token* prev) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
id[length]=0;
|
num[length]=0;
|
||||||
return new_token(TYPE_NUM, val_from_int(atoi(id)), prev);
|
return new_token(TYPE_NUM, val_from_str(num), prev);
|
||||||
} else if (isblank(current) || current=='\n') {
|
} else if (isblank(current) || current=='\n') {
|
||||||
(*strpos)++;
|
(*strpos)++;
|
||||||
current=prg[*strpos];
|
current=prg[*strpos];
|
||||||
|
Loading…
Reference in New Issue
Block a user