aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTeddy <[email protected]>2014-03-24 20:54:55 +0800
committerTeddy <[email protected]>2014-03-24 20:54:55 +0800
commitf218a80d6ca8a69ba0b22cb87f99e8b82162bbee (patch)
tree796058d507c602ce76b91b862acb6fdf9912863f
parentccab148f1310b3cadffb99005941e39fa932d295 (diff)
AST Construction: almost done
-rw-r--r--Makefile9
-rw-r--r--ast.c336
-rw-r--r--ast.h61
-rw-r--r--cibic.y201
4 files changed, 561 insertions, 46 deletions
diff --git a/Makefile b/Makefile
index 4cf057a..9abe133 100644
--- a/Makefile
+++ b/Makefile
@@ -3,14 +3,17 @@ all: cibic
run:
./cibic
+debug:
+ gdb cibic
+
cibic: lex.yy.o cibic.tab.o ast.o
gcc -o cibic lex.yy.o cibic.tab.o ast.o
lex.yy.o: lex.yy.c
- gcc -c lex.yy.c
+ gcc -c lex.yy.c -Wall -Wextra
cibic.tab.o: cibic.tab.c
- gcc -c cibic.tab.c
+ gcc -c cibic.tab.c -Wall -Wextra
ast.o: ast.c
- gcc -c ast.c -g
+ gcc -c ast.c -g -Wall -Wextra
lex.yy.c: cibic.l
flex cibic.l
cibic.tab.c: cibic.y
diff --git a/ast.c b/ast.c
new file mode 100644
index 0000000..e36bb30
--- /dev/null
+++ b/ast.c
@@ -0,0 +1,336 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "ast.h"
+#include "cibic.tab.h"
+#define NEW_CNODE ((CNode *)malloc(sizeof(CNode)))
+
+CNode *ast_root;
+
+void cnode_init() {
+}
+
+CNode *cnode_create_nop() {
+ CNode *nop = NEW_CNODE;
+ nop->type = NOP;
+ nop->next = nop->chd = NULL;
+ return nop;
+}
+
+CNode *cnode_create_general(int type, int subtype, int pnum, va_list ap) {
+ int i;
+ CNode *exp = NEW_CNODE;
+ exp->type = type;
+ exp->rec.subtype = subtype;
+ exp->next = NULL;
+ for (i = 0; i < pnum; i++)
+ {
+ CNode *subexp = va_arg(ap, CNode*);
+ if (subexp->next)
+ {
+ puts("asdf");
+ }
+ assert(subexp->next == NULL);
+ subexp->next = exp->chd;
+ exp->chd = subexp;
+ }
+ return exp;
+}
+
+CNode *cnode_append(CNode *node, CNode *tail) {
+ if (node->type == NOP)
+ {
+ free(node);
+ return tail;
+ }
+ tail->next = node;
+ return tail;
+}
+
+CNode *cnode_create_identifier(char *val) {
+ CNode *exp = NEW_CNODE;
+ exp->type = ID;
+ exp->chd = exp->next = NULL;
+ exp->rec.strval = val;
+ return exp;
+}
+
+CNode *cnode_create_int_const(int val) {
+ /* TODO: overflow checking */
+ CNode *exp = NEW_CNODE;
+ exp->type = INT;
+ exp->chd = exp->next = NULL;
+ exp->rec.intval = val;
+ return exp;
+}
+
+CNode *cnode_create_char_const(int val) {
+ /* TODO: overflow checking */
+ CNode *exp = NEW_CNODE;
+ exp->type = CHAR;
+ exp->chd = exp->next = NULL;
+ exp->rec.intval = val;
+ return exp;
+}
+
+CNode *cnode_create_str_const(char *val) {
+ CNode *exp = NEW_CNODE;
+ exp->type = STR;
+ exp->chd = exp->next = NULL;
+ exp->rec.strval = val;
+ return exp;
+}
+
+CNode *cnode_create_exp(int exp_type, int pnum, ...) {
+ CNode *ret;
+ va_list ap;
+ va_start(ap, pnum);
+ ret = cnode_create_general(EXP, exp_type, pnum, ap);
+ va_end(ap);
+ return ret;
+}
+
+CNode *cnode_create_type_spec(int spec_type, int pnum, ...) {
+ CNode *ret;
+ va_list ap;
+ va_start(ap, pnum);
+ ret = cnode_create_general(TYPE_SPEC, spec_type, pnum, ap);
+ va_end(ap);
+ return ret;
+}
+
+CNode *cnode_create_declr(int declr_type, int pnum, ...) {
+ CNode *ret;
+ va_list ap;
+ va_start(ap, pnum);
+ ret = cnode_create_general(DECLR, declr_type, pnum, ap);
+ va_end(ap);
+ return ret;
+}
+
+CNode *cnode_create_stmt(int stmt_type, int pnum, ...) {
+ CNode *ret;
+ va_list ap;
+ va_start(ap, pnum);
+ ret = cnode_create_general(STMT, stmt_type, pnum, ap);
+ va_end(ap);
+ return ret;
+}
+
+CNode *cnode_create_initr(int initr_type, CNode *body) {
+ CNode *initr = NEW_CNODE;
+ initr->type = INITR;
+ initr->rec.subtype = initr_type;
+ initr->chd = body;
+ return initr;
+}
+
+CNode *cnode_create_decl(CNode *type, CNode *init_declrs) {
+ CNode *decl = NEW_CNODE;
+ decl->type = DECL;
+ decl->chd = type;
+ type->next = init_declrs;
+ return decl;
+}
+
+CNode *cnode_create_func(CNode *type, CNode *plain_decl, CNode *params, CNode *stmt) {
+ CNode *func = NEW_CNODE;
+ func->type = FUNC_DEF;
+ func->chd = stmt;
+ func->next = NULL;
+ stmt->next = params;
+ params->next = plain_decl;
+ plain_decl->next = type;
+ return func;
+}
+
+CNode *cnode_create_init_declr(CNode *declr, CNode *initr) {
+ CNode *init_declr = NEW_CNODE;
+ init_declr->type = INIT_DECLR;
+ init_declr->chd = initr;
+ initr->next = declr;
+ return init_declr;
+}
+
+CNode *cnode_create_struct_field(CNode *type_spec, CNode *declrs) {
+ CNode *field = NEW_CNODE;
+ field->type = FIELD;
+ field->chd = declrs;
+ declrs->next = type_spec;
+ return field;
+}
+
+CNode *cnode_create_plain_decl(CNode *type_spec, CNode *declr) {
+ CNode *pdecl = NEW_CNODE;
+ pdecl->type = PLAIN_DECL;
+ pdecl->chd = declr;
+ declr->next = type_spec;
+ return pdecl;
+}
+
+CNode *cnode_create_comp_decls(CNode *decls) {
+ CNode *comp_decls = NEW_CNODE;
+ comp_decls->type = COMP_DECLS;
+ comp_decls->chd = decls;
+ return comp_decls;
+}
+
+CNode *cnode_create_comp_stmts(CNode *stmts) {
+ CNode *comp_stmts = NEW_CNODE;
+ comp_stmts->type = COMP_STMTS;
+ comp_stmts->chd = stmts;
+ comp_stmts->next = NULL;
+ return comp_stmts;
+}
+
+CNode *cnode_create_args(CNode *arg_list) {
+ CNode *args = NEW_CNODE;
+ args->type = ARGS;
+ args->chd = arg_list;
+ args->next = NULL;
+ return args;
+}
+
+CNode *cnode_create_params(CNode *plist) {
+ CNode *params = NEW_CNODE;
+ params->type = PARAMS;
+ params->chd = plist;
+ params->next = NULL;
+ return params;
+}
+
+char *cnode_debug_type_repr(CNode *ast) {
+ static buffer[1024];
+ char *type = NULL;
+ switch (ast->type)
+ {
+ case PROG: type = "prog"; break;
+ case FUNC_DEF: type = "func"; break;
+ case DECL: type = "decl"; break;
+ case DECLR: type = "declr"; break;
+ case INIT_DECLR: type = "init_declr"; break;
+ case PLAIN_DECL: type = "p_decl"; break;
+ case TYPE_NAME: type = "type_name"; break;
+ case COMP_STMTS: type = "stmts"; break;
+ case COMP_DECLS: type = "decls"; break;
+ case ARGS: type = "args"; break;
+ case PARAMS: type = "params"; break;
+ case ID: type = "id"; break;
+ case INT: type = "int"; break;
+ case CHAR: type = "char"; break;
+ case STR: type = "str"; break;
+ case NOP: type = "nop"; break;
+ }
+ if (ast->type == EXP)
+ {
+ switch (ast->rec.subtype)
+ {
+ case ',': type = ","; break;
+ case '=': type = "="; break;
+ case ASS_MUL: type = "*="; break;
+ case ASS_DIV: type = "/="; break;
+ case ASS_MOD: type = "%="; break;
+ case ASS_ADD: type = "+="; break;
+ case ASS_SUB: type = "-="; break;
+ case ASS_SHL: type = "<<="; break;
+ case ASS_SHR: type = ">>="; break;
+ case ASS_AND: type = "&="; break;
+ case ASS_XOR: type = "^="; break;
+ case ASS_OR: type = "|="; break;
+ case OPT_OR: type = "||"; break;
+ case OPT_AND: type = "&&"; break;
+ case '|': type = "|"; break;
+ case '^': type = "^"; break;
+ case '&': type = "&"; break;
+ case OPT_EQ: type = "=="; break;
+ case OPT_NE: type = "!="; break;
+ case '<': type = "<"; break;
+ case '>': type = ">"; break;
+ case OPT_LE: type = "<="; break;
+ case OPT_GE: type = ">="; break;
+ case OPT_SHL: type = "<<"; break;
+ case OPT_SHR: type = ">>"; break;
+ case '+': type = "+"; break;
+ case '-': type = "-"; break;
+ case '*': type = "*"; break;
+ case '/': type = "/"; break;
+ case '%': type = "%"; break;
+ case EXP_CAST: type = "cast"; break;
+ case OPT_INC: type = "++"; break;
+ case OPT_DEC: type = "--"; break;
+ case '~': type = "~"; break;
+ case '!': type = "!"; break;
+ case KW_SIZEOF: type = "sizeof"; break;
+ case EXP_POSTFIX: type = "pofix"; break;
+ case POSTFIX_ARR: type = "arr"; break;
+ case POSTFIX_CALL: type = "call"; break;
+ case POSTFIX_DOT: type = "dot"; break;
+ case POSTFIX_PTR: type = "ptr"; break;
+ default: assert(0);
+ }
+ }
+ else if (ast->type == TYPE_SPEC)
+ {
+ switch (ast->rec.subtype)
+ {
+ case KW_VOID: type = "void"; break;
+ case KW_CHAR: type = "char"; break;
+ case KW_INT: type = "int"; break;
+ case KW_STRUCT: type = "struct"; break;
+ case KW_UNION: type = "union"; break;
+ default: assert(0);
+ }
+ }
+ else if (ast->type == DECLR)
+ {
+ switch (ast->rec.subtype)
+ {
+ case DECLR_FUNC: type = "func"; break;
+ case DECLR_ARR: type = "arr"; break;
+ default: assert(0);
+ }
+ }
+ else if (ast->type == STMT)
+ {
+ switch (ast->rec.subtype)
+ {
+ case STMT_EXP: type = "exp"; break;
+ case STMT_COMP: type = "blk"; break;
+ case STMT_IF: type = "if"; break;
+ case STMT_WHILE: type = "while"; break;
+ case STMT_FOR: type = "for"; break;
+ case STMT_CONT: type = "cont"; break;
+ case STMT_BREAK: type = "break"; break;
+ case STMT_RET: type = "ret"; break;
+ default: assert(0);
+ }
+ }
+ else if (ast->type == INITR)
+ {
+ switch (ast->rec.subtype)
+ {
+ case INITR_NORM: type = "initr_n"; break;
+ case INITR_ARR: type = "initr_a"; break;
+ default: assert(0);
+ }
+ }
+ else assert(type);
+ sprintf(buffer, "%s", type);
+ return buffer;
+}
+
+void cnode_debug_print_(CNode *ast) {
+ printf("(%s", cnode_debug_type_repr(ast));
+ for (ast = ast->chd; ast; ast = ast->next)
+ {
+ printf(" ");
+ cnode_debug_print_(ast);
+ }
+ printf(")");
+}
+
+void cnode_debug_print(CNode *ast) {
+ cnode_debug_print_(ast);
+ puts("");
+}
diff --git a/ast.h b/ast.h
index d438b92..0b0264a 100644
--- a/ast.h
+++ b/ast.h
@@ -7,33 +7,48 @@
#define POSTFIX_DOT 1027
#define POSTFIX_PTR 1028
#define EXP_CAST 1029
+#define INITR_NORM 1030
+#define INITR_ARR 1031
+#define DECLR_FUNC 1032
+#define DECLR_ARR 1033
+#define STMT_EXP 1034
+#define STMT_COMP 1035
+#define STMT_IF 1036
+#define STMT_WHILE 1037
+#define STMT_FOR 1038
+#define STMT_CONT 1039
+#define STMT_BREAK 1040
+#define STMT_RET 1041
typedef struct CNode {
enum {
/* Top Level */
- PROG, FUNC_DEF, PARAMS,
+ PROG,
+ FUNC_DEF,
DECL, /* declaration */
DECLR, /* declarator */
- DECLRS,
- INIT_DECLRS, INIT_DECLR,
+ INIT_DECLR,
INITR, /* initializer */
TYPE_SPEC,
- STRUCT, UNION,
- PLAIN_DECL, PLAIN_DECLR,
+ FIELD, /* struct-or-union field */
+ PLAIN_DECL,
/* Statments */
- EXP_STMT, /* expression-statment */
- COMP_STMT, IF_STMT, /* selection-statment */
- WHILE_STMT, FOR_STMT,
- CONT_STMT , BREAK_STMT, RET_STMT, /* 'continue', 'break', 'return' */
+ STMT,
- /* Expressions (expressions use their token ID to denote their types */
+ /* Expressions */
EXP,
TYPE_NAME,
ID, /* identifier */
INT, /* INT_CONST */
CHAR,
- STR
+ STR,
+ NOP,
+
+ COMP_STMTS,
+ COMP_DECLS,
+ ARGS,
+ PARAMS
} type;
union {
int intval;
@@ -47,15 +62,35 @@ typedef struct CNode {
} loc;
} CNode;
+void cnode_init();
+CNode *cnode_create_nop();
+CNode *cnode_create_general(int type, int subtype, int pnum, va_list ap);
+CNode *cnode_append(CNode *node, CNode *tail);
+
CNode *cnode_create_exp(int exp_type, int pnum, ...);
CNode *cnode_create_type_spec(int spec_type, int pnum, ...);
-CNode *cnode_append(CNode *node, CNode *tail);
+CNode *cnode_create_declr(int declr_type, int pnum, ...);
+CNode *cnode_create_stmt(int stmt_type, int pnum, ...);
+CNode *cnode_create_initr(int initr_type, CNode *body);
+
+CNode *cnode_create_decl(CNode *type, CNode *init_declrs);
+CNode *cnode_create_func(CNode *type, CNode *plain_decl, CNode *params, CNode *stmt);
+CNode *cnode_create_init_declr(CNode *declr, CNode *initr);
+CNode *cnode_create_struct_field(CNode *type_spec, CNode *declrs);
+CNode *cnode_create_plain_decl(CNode *type_spec, CNode *declr);
+CNode *cnode_create_comp_decls(CNode *decls);
+CNode *cnode_create_comp_stmts(CNode *stmts);
+CNode *cnode_create_args(CNode *arg_list);
+CNode *cnode_create_params(CNode *plist);
+
CNode *cnode_create_identifier(char *val);
CNode *cnode_create_int_const(int val);
CNode *cnode_create_char_const(int val);
CNode *cnode_create_str_const(char *val);
-CNode *cnode_debug_print(CNode *ast);
+
+void cnode_debug_print(CNode *ast);
extern CNode *ast_root;
+extern CNode *null;
#endif
diff --git a/cibic.y b/cibic.y
index daeb35a..6752883 100644
--- a/cibic.y
+++ b/cibic.y
@@ -12,17 +12,142 @@
%token KW_VOID KW_CHAR KW_INT KW_STRUCT KW_UNION KW_IF KW_ELSE KW_WHILE
%token KW_FOR KW_CONT KW_BREAK KW_RET KW_SIZEOF
%token OPT_OR OPT_AND OPT_EQ OPT_NE OPT_LE OPT_GE OPT_SHL OPT_SHR OPT_INC OPT_DEC OPT_PTR
-%token ASS_MUL ASS_DIV ASS_MOD ASS_ADD ASS_SUB ASS_SHL ASS_SHR ASS_AND ASS_XOR ASS_OR
+%token ASS_MUL ASS_DIV ASS_MOD ASS_ADD ASS_SUB ASS_SHL ASS_SHR ASS_AND ASS_XOR ASS_OR
%token UNKNOWN
%type<intval> INT_CONST CHAR_CONST
%type<strval> IDENTIFIER STR_CONST
-%type<intval> assignment_operator equality_operator relational_operator shift_operator additive_operator multiplicative_operator unary_operator
-%type<cnode> expression assignment_expression constant_expression
+%type<intval> assignment_operator equality_operator relational_operator shift_operator additive_operator multiplicative_operator unary_operator struct_or_union
+%type<cnode> expression assignment_expression constant_expression
%type<cnode> logical_or_expression logical_and_expression inclusive_or_expression exclusive_or_expression and_expression equality_expression relational_expression shift_expression additive_expression multiplicative_expression cast_expression type_name
-%type<cnode>unary_expression postfix_expression identifier primary_expression arguments postfix type_specifier
+%type<cnode> unary_expression postfix_expression identifier primary_expression arguments postfix type_specifier program declaration function_definition parameters declarators init_declarators init_declarator initializer array_initializer struct_fields struct_field plain_declaration declarator_array plain_declarator expression_statement compound_statement statement
+%type<cnode> comp_decls comp_stmts selection_statement iteration_statement jump_statement optional_exp declarator
%%
-debug_top
- : expression { ast_root = $1; }
+program
+ : declaration { ast_root = $1; }
+ | function_definition { ast_root = $1; }
+ | program declaration { ast_root = cnode_append(ast_root, $2); }
+ | program function_definition { ast_root = cnode_append(ast_root, $2); }
+
+declaration
+ : type_specifier ';' { $$ = cnode_create_decl($1, cnode_create_nop()); }
+ | type_specifier init_declarators ';' { $$ = cnode_create_decl($1, $2); }
+
+function_definition
+ : type_specifier plain_declarator '(' parameters ')' compound_statement {
+ $$ = cnode_create_func($1, $2, cnode_create_params($4), $6);
+ }
+ | type_specifier plain_declarator '(' ')' compound_statement {
+ $$ = cnode_create_func($1, $2, cnode_create_nop(), $5);
+ }
+
+parameters
+ : plain_declaration
+ | parameters ',' plain_declaration { $$ = cnode_append($1, $3); }
+
+declarators
+ : declarator
+ | declarators ',' declarator { $$ = cnode_append($1, $3); }
+
+init_declarators
+ : init_declarator
+ | init_declarators ',' init_declarator { $$ = cnode_append($1, $3); }
+
+init_declarator
+ : declarator { $$ = cnode_create_init_declr($1, cnode_create_nop()); }
+ | declarator '=' initializer { $$ = cnode_create_init_declr($1, $3); }
+
+initializer
+ : assignment_expression { $$ = cnode_create_initr(INITR_NORM, $1); }
+ | '{' array_initializer '}' { $$ = cnode_create_initr(INITR_ARR, $2); }
+
+array_initializer
+ : initializer
+ | array_initializer ',' initializer { $$ = cnode_append($1, $3); }
+
+type_specifier
+ : KW_VOID { $$ = cnode_create_type_spec(KW_VOID, 0); }
+ | KW_CHAR { $$ = cnode_create_type_spec(KW_CHAR, 0); }
+ | KW_INT { $$ = cnode_create_type_spec(KW_INT, 0); }
+ | struct_or_union identifier '{' struct_fields '}' { $$ = cnode_create_type_spec($1, 2, $2, $4); }
+ | struct_or_union '{' struct_fields '}' { $$ = cnode_create_type_spec($1, 2, cnode_create_nop(), $3); }
+ | struct_or_union identifier { $$ = cnode_create_type_spec($1, 2, $2, cnode_create_nop()); }
+
+struct_fields
+ : struct_field
+ | struct_fields struct_field { $$ = cnode_append($1, $2); }
+struct_field
+ : type_specifier declarators ';' { $$ = cnode_create_struct_field($1, $2); }
+
+struct_or_union
+ : KW_STRUCT { $$ = KW_STRUCT; }
+ | KW_UNION { $$ = KW_UNION; }
+
+plain_declaration
+ : type_specifier declarator { $$ = cnode_create_plain_decl($1, $2); }
+
+declarator
+ : plain_declarator '(' ')' { $$ = cnode_create_declr(DECLR_FUNC, 2, $1, cnode_create_nop());}
+ | plain_declarator '(' parameters ')' { $$ = cnode_create_declr(DECLR_FUNC, 2, $1, $3);}
+ | declarator_array
+
+declarator_array
+ : plain_declarator
+ | declarator_array '[' constant_expression ']' { $$ = cnode_create_declr(DECLR_ARR, 2, $1, $3); }
+
+plain_declarator
+ : identifier
+ | '*' plain_declarator { $$ = cnode_create_declr('*', 1, $2); }
+
+statement
+ : expression_statement
+ | compound_statement
+ | selection_statement
+ | iteration_statement
+ | jump_statement
+
+expression_statement
+ : ';' { $$ = cnode_create_stmt(STMT_EXP, 1, cnode_create_nop()); }
+ | expression ';' { $$ = cnode_create_stmt(STMT_EXP, 1, $1); }
+
+compound_statement
+ : '{' comp_decls comp_stmts '}' {
+ $$ = cnode_create_stmt(STMT_COMP, 2, cnode_create_comp_decls($2),
+ cnode_create_comp_stmts($3));
+ }
+
+comp_decls
+ : { $$ = cnode_create_nop(); }
+ | comp_decls declaration { $$ = cnode_append($1, $2); }
+
+comp_stmts
+ : { $$ = cnode_create_nop(); }
+ | comp_stmts statement { $$ = cnode_append($1, $2); }
+
+selection_statement
+ : KW_IF '(' expression ')' statement {
+ $$ = cnode_create_stmt(STMT_IF, 3, $3, $5, cnode_create_nop());
+ }
+ | KW_IF '(' expression ')' statement KW_ELSE statement {
+ $$ = cnode_create_stmt(STMT_IF, 3, $3, $5, $7);
+ }
+
+iteration_statement
+ : KW_WHILE '(' expression ')' statement {
+ $$ = cnode_create_stmt(STMT_WHILE, 2, $3, $5);
+ }
+ | KW_FOR '(' optional_exp ';' optional_exp ';' optional_exp ')' statement {
+ $$ = cnode_create_stmt(STMT_FOR, 4, $3, $5, $7, $9);
+ }
+
+optional_exp
+ : { $$ = cnode_create_nop(); }
+ | expression
+
+jump_statement
+ : KW_CONT ';' { $$ = cnode_create_stmt(STMT_CONT, 0); }
+ | KW_BREAK ';' { $$ = cnode_create_stmt(STMT_BREAK, 0); }
+ | KW_RET optional_exp ';' { $$ = cnode_create_stmt(STMT_RET, 1, $2); }
+
expression
: assignment_expression
| expression ',' assignment_expression { $$ = cnode_create_exp(',', 2, $1, $3); }
@@ -47,27 +172,39 @@ assignment_operator
constant_expression: logical_or_expression
logical_or_expression
: logical_and_expression
- | logical_or_expression OPT_OR logical_and_expression { $$ = cnode_create_exp(OPT_OR, 2, $1, $3); }
+ | logical_or_expression OPT_OR logical_and_expression {
+ $$ = cnode_create_exp(OPT_OR, 2, $1, $3);
+ }
logical_and_expression
: inclusive_or_expression
- | logical_and_expression OPT_AND inclusive_or_expression { $$ = cnode_create_exp(OPT_AND, 2, $1, $3); }
+ | logical_and_expression OPT_AND inclusive_or_expression {
+ $$ = cnode_create_exp(OPT_AND, 2, $1, $3);
+ }
inclusive_or_expression
: exclusive_or_expression
- | inclusive_or_expression '|' exclusive_or_expression { $$ = cnode_create_exp('|', 2, $1, $3); }
+ | inclusive_or_expression '|' exclusive_or_expression {
+ $$ = cnode_create_exp('|', 2, $1, $3);
+ }
exclusive_or_expression
: and_expression
- | exclusive_or_expression '^' and_expression { $$ = cnode_create_exp('^', 2, $1, $3); }
+ | exclusive_or_expression '^' and_expression {
+ $$ = cnode_create_exp('^', 2, $1, $3);
+ }
and_expression
: equality_expression
- | and_expression '&' equality_expression { $$ = cnode_create_exp('&', 2, $1, $3); }
+ | and_expression '&' equality_expression {
+ $$ = cnode_create_exp('&', 2, $1, $3);
+ }
equality_expression
- : relational_expression
- | equality_expression equality_operator relational_expression { $$ = cnode_create_exp($2, 2, $1, $3); }
+ : relational_expression
+ | equality_expression equality_operator relational_expression {
+ $$ = cnode_create_exp($2, 2, $1, $3);
+ }
equality_operator
: OPT_EQ { $$ = OPT_EQ; }
@@ -75,7 +212,9 @@ equality_operator
relational_expression
: shift_expression
- | relational_expression relational_operator shift_expression { $$ = cnode_create_exp($2, 2, $1, $3); }
+ | relational_expression relational_operator shift_expression {
+ $$ = cnode_create_exp($2, 2, $1, $3);
+ }
relational_operator
: '<' { $$ = '<'; }
@@ -85,7 +224,9 @@ relational_operator
shift_expression
: additive_expression
- | shift_expression shift_operator additive_expression { $$ = cnode_create_exp($2, 2, $1, $3); }
+ | shift_expression shift_operator additive_expression {
+ $$ = cnode_create_exp($2, 2, $1, $3);
+ }
shift_operator
: OPT_SHL { $$ = OPT_SHL; }
@@ -93,7 +234,9 @@ shift_operator
additive_expression
: multiplicative_expression
- | additive_expression additive_operator multiplicative_expression { $$ = cnode_create_exp($2, 2, $1, $3); }
+ | additive_expression additive_operator multiplicative_expression {
+ $$ = cnode_create_exp($2, 2, $1, $3);
+ }
additive_operator
: '+' { $$ = '+'; }
@@ -101,7 +244,9 @@ additive_operator
multiplicative_expression
: cast_expression
- | multiplicative_expression multiplicative_operator cast_expression { $$ = cnode_create_exp($2, 2, $1, $3); }
+ | multiplicative_expression multiplicative_operator cast_expression {
+ $$ = cnode_create_exp($2, 2, $1, $3);
+ }
multiplicative_operator
: '*' { $$ = '*'; }
@@ -110,7 +255,9 @@ multiplicative_operator
cast_expression
: unary_expression
- | '(' type_name ')' cast_expression { $$ = cnode_create_exp(EXP_CAST, 2, $2, $4); }
+ | '(' type_name ')' cast_expression {
+ $$ = cnode_create_exp(EXP_CAST, 2, $2, $4);
+ }
type_name
: type_specifier
@@ -138,8 +285,9 @@ postfix_expression
postfix
: '[' expression ']' { $$ = cnode_create_exp(POSTFIX_ARR, 1, $2); }
- | '(' arguments ')' { $$ = cnode_create_exp(POSTFIX_CALL, 1, $2); }
- | '(' ')' { $$ = cnode_create_exp(POSTFIX_CALL, 1, NULL); }
+ | '(' arguments ')' { $$ = cnode_create_exp(POSTFIX_CALL, 1,
+ cnode_create_args($2)); }
+ | '(' ')' { $$ = cnode_create_exp(POSTFIX_CALL, 1, cnode_create_nop()); }
| '.' identifier { $$ = cnode_create_exp(POSTFIX_DOT, 1, $2); }
| OPT_PTR identifier { $$ = cnode_create_exp(POSTFIX_PTR, 1, $2); }
| OPT_INC { $$ = cnode_create_exp(OPT_INC, 0); }
@@ -158,17 +306,9 @@ primary_expression
identifier
: IDENTIFIER { $$ = cnode_create_identifier($1); }
-
-type_specifier
- : KW_VOID { $$ = cnode_create_type_spec(KW_VOID, 0); }
- | KW_CHAR { $$ = cnode_create_type_spec(KW_CHAR, 0); }
- | KW_INT { $$ = cnode_create_type_spec(KW_INT, 0); }
- /* to be continue */
-
-
%%
-int yywrap() {
- return 1;
+int yywrap() {
+ return 1;
}
int yyerror(char *s) {
@@ -177,6 +317,7 @@ int yyerror(char *s) {
extern FILE *yyin;
void test_ast() {
yyparse();
+ cnode_init();
if (ast_root)
cnode_debug_print(ast_root);
else