├── include ├── err.h ├── limits.h ├── sys │ ├── types.h │ └── wait.h ├── assert.h ├── stdbool.h ├── ctype.h ├── unistd.h ├── stdlib.h ├── string.h └── stdio.h ├── sncc ├── .gitignore ├── example ├── fib.c ├── cat.c ├── n-queen.c └── lsh.c ├── selflib.c ├── test ├── parser_expr_test.c ├── lexer_test.c ├── parser_stmt_test.c ├── map_test.c ├── vector_test.c └── funcdecl_test.c ├── README.md ├── sncc.c ├── vector.c ├── sncclib.c ├── utils.c ├── map.c ├── Makefile ├── compiler_test.sh ├── sncc.h ├── semantic.c ├── test.c ├── lexer.c ├── codegen.c └── parser.c /include/err.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/limits.h: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /include/sys/types.h: -------------------------------------------------------------------------------- 1 | typedef int* pid_t; 2 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void assert(bool b); 4 | -------------------------------------------------------------------------------- /include/stdbool.h: -------------------------------------------------------------------------------- 1 | typedef int bool; 2 | #define true 1 3 | #define false 0 4 | -------------------------------------------------------------------------------- /include/ctype.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | bool isalpha(char c); 4 | bool isdigit(char c); 5 | -------------------------------------------------------------------------------- /include/sys/wait.h: -------------------------------------------------------------------------------- 1 | #define WUNTRACED 2 2 | 3 | int WIFEXITED(int status); 4 | int WIFSIGNALED(int status); 5 | -------------------------------------------------------------------------------- /sncc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | ./sncc.out < $1 > test.s && ./sncc.out < selflib.c > selflib.s && gcc -oa test.s selflib.s 3 | -------------------------------------------------------------------------------- /include/unistd.h: -------------------------------------------------------------------------------- 1 | #define HOST_NAME_MAX 64 2 | extern int optind; 3 | int getopt(int argc, char** argv, char* optstring); 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.out 3 | a 4 | self 5 | self2 6 | test.pp.c 7 | /*.s 8 | *.o 9 | *.log 10 | .vagrant/ 11 | *.swp 12 | -------------------------------------------------------------------------------- /include/stdlib.h: -------------------------------------------------------------------------------- 1 | #define NULL 0 2 | 3 | void* malloc(int size); 4 | void* realloc(void* p, int size); 5 | void free(void* p); 6 | int atoi(char* s); 7 | -------------------------------------------------------------------------------- /example/fib.c: -------------------------------------------------------------------------------- 1 | int fib(int n) { 2 | if (n < 2) { 3 | return n; 4 | } else { 5 | return fib(n-1) + fib(n-2); 6 | } 7 | } 8 | 9 | int main() { 10 | printf("%d", fib(10)); 11 | } 12 | -------------------------------------------------------------------------------- /include/string.h: -------------------------------------------------------------------------------- 1 | char* strtok(char* s1, char* s2); 2 | int strcmp(char* a, char* b); 3 | char* strdup(char* s); 4 | int strncmp(char* a, int n, char* b); 5 | int strncpy(char* d, char* s, int n); 6 | int strlen(char* s); 7 | -------------------------------------------------------------------------------- /selflib.c: -------------------------------------------------------------------------------- 1 | char EOF = -1; 2 | 3 | int _WSTATUS(int status) { 4 | return status & 127; 5 | } 6 | 7 | int WIFEXITED(int status) { 8 | return _WSTATUS(status) == 0; 9 | } 10 | 11 | int WIFSIGNALED(int status) { 12 | return (_WSTATUS(status) != 127) && (_WSTATUS(status) != 0); 13 | } 14 | -------------------------------------------------------------------------------- /test/parser_expr_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../sncc.h" 3 | 4 | int main() { 5 | init_lexer(); 6 | init_parser(); 7 | vector* tokenss = lexer(); 8 | tokenstream* ts = new_tokenstream(tokenss); 9 | astree* ast = expression(ts); 10 | printf("%s", ast_to_kindstr(ast)); 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # sncc (snow c compiler) 3 | 4 | Self hosted C compiler at seccamp2018. (has many unimplemented features) 5 | 6 | # Build 7 | 8 | ``` 9 | $ make build 10 | ``` 11 | 12 | # Test 13 | 14 | ``` 15 | $ make test 16 | ``` 17 | 18 | # Usage 19 | 20 | ``` 21 | ./sncc filename.c 22 | ./a 23 | ``` 24 | -------------------------------------------------------------------------------- /test/lexer_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../sncc.h" 3 | 4 | int main() { 5 | init_lexer(); 6 | vector* tokenss = lexer(); 7 | for (int i=0; ilen; i++) { 8 | token* t = (token*)vector_get(tokenss, i); 9 | printf("%s:%s ", token_to_kindstr(t), token_to_str(t)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/parser_stmt_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "../sncc.h" 3 | 4 | int main() { 5 | init_lexer(); 6 | init_parser(); 7 | vector* tokenss = lexer(); 8 | tokenstream* ts = new_tokenstream(tokenss); 9 | vector* stmts = parse_statements(ts); 10 | printf("%d", stmts->len); 11 | for (int i=0; ilen; i++) { 12 | astree* ast = vector_get(stmts, i); 13 | printf(" %s", ast_to_kindstr(ast)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /sncc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sncc.h" 3 | 4 | int main() { 5 | init_lexer(); 6 | init_parser(); 7 | vector* tokenss = lexer(); 8 | tokenstream* ts = new_tokenstream(tokenss); 9 | 10 | init_semantic(); 11 | while (true) { 12 | if (get_token(ts) == NULL) break; 13 | toplevel* top = parse_toplevel(ts); 14 | semantic_analysis_toplevel(top); 15 | codegen_strlits(); 16 | codegen_toplevel(top); 17 | } 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /include/stdio.h: -------------------------------------------------------------------------------- 1 | typedef void FILE; 2 | 3 | #define EXIT_SUCCESS 0 4 | #define EXIT_FAILURE 1 5 | 6 | extern FILE* stdin; 7 | extern FILE* stderr; 8 | extern char EOF; 9 | 10 | FILE* fopen(char* filename, char* mode); 11 | void fclose(FILE* fp); 12 | char getc(FILE* fp); 13 | void ungetc(char c, FILE* fp); 14 | char fgetc(FILE* fp); 15 | void putchar(char c); 16 | char getchar(); 17 | void printf(char* fmt); 18 | void fprintf(FILE* f, char* fmt); 19 | void sprintf(char* s, char* fmt); 20 | void snprintf(char* s, int n, char* fmt); 21 | void exit(int code); 22 | -------------------------------------------------------------------------------- /test/map_test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "../vector.c" 4 | #include "../map.c" 5 | 6 | int* pint(int x) { 7 | int* p = malloc(sizeof(int)); 8 | *p = x; 9 | return p; 10 | } 11 | 12 | int main() { 13 | map* m = new_map(); 14 | map_insert(m, "a", pint(1)); 15 | map_insert(m, "b", pint(2)); 16 | map_insert(m, "c", pint(3)); 17 | map_insert(m, "d", pint(4)); 18 | 19 | assert(1 == *(int*)map_get(m, "a")); 20 | assert(2 == *(int*)map_get(m, "b")); 21 | assert(3 == *(int*)map_get(m, "c")); 22 | assert(4 == *(int*)map_get(m, "d")); 23 | map_insert(m, "a", pint(9)); 24 | assert(9 == *(int*)map_get(m, "a")); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /test/vector_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../vector.c" 5 | 6 | int* pint(int x) { 7 | int* p = (int*)malloc(sizeof(int)); 8 | *p = x; 9 | return p; 10 | } 11 | 12 | int main() { 13 | vector* v = new_vector_cap(1); 14 | vector_push(v, pint(1)); 15 | vector_push(v, pint(2)); 16 | vector_push(v, pint(3)); 17 | vector_push(v, pint(4)); 18 | vector_push(v, pint(5)); 19 | 20 | assert(1 == *(int*)vector_get(v, 0)); 21 | assert(2 == *(int*)vector_get(v, 1)); 22 | assert(3 == *(int*)vector_get(v, 2)); 23 | assert(4 == *(int*)vector_get(v, 3)); 24 | assert(5 == *(int*)vector_get(v, 4)); 25 | assert(5 == v->len); 26 | 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /example/cat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX_FILENAME_LEN 255 6 | 7 | int main(int argc, char **argv) { 8 | char filename[MAX_FILENAME_LEN]; 9 | 10 | if (argc <= 1) { 11 | printf("Usage cat \n"); 12 | return 0; 13 | } 14 | 15 | for (int i=1; idata = malloc(cap*sizeof(void*)); 6 | v->cap = cap; 7 | v->len = 0; 8 | return v; 9 | } 10 | vector* new_vector() { 11 | return new_vector_cap(256); 12 | } 13 | 14 | void vector_extend(vector* v) { 15 | if (v->cap < v->len+1) { 16 | v->data = realloc(v->data, v->cap*2*sizeof(void*)); 17 | v->cap *= 2; 18 | } 19 | } 20 | 21 | void* vector_get(vector* v, int index) { 22 | return v->data[index]; 23 | } 24 | void vector_set(vector* v, int index, void* elem) { 25 | v->data[index] = elem; 26 | } 27 | 28 | void vector_push(vector* v, void* elem) { 29 | vector_extend(v); 30 | vector_set(v, v->len++, elem); 31 | } 32 | -------------------------------------------------------------------------------- /example/n-queen.c: -------------------------------------------------------------------------------- 1 | int board[20]; 2 | 3 | int canplace(int row, int column) { 4 | int i; 5 | for (i=1; i<=row-1; i=i+1) { 6 | if (board[i] == column) { 7 | return 0; 8 | } else { 9 | if (abs(board[i]-column) == abs(i-row)) { 10 | return 0; 11 | } 12 | } 13 | } 14 | 15 | return 1; 16 | } 17 | 18 | int queen(int row, int n) { 19 | int count = 0; 20 | 21 | int column; 22 | for (column=1; column<=n; column=column+1) { 23 | if (canplace(row, column)) { 24 | board[row] = column; 25 | if (row == n) { 26 | count = count+1; 27 | } else { 28 | count = count + queen(row+1, n); 29 | } 30 | } 31 | } 32 | 33 | return count; 34 | } 35 | 36 | int main() { 37 | printf("%d", queen(1, 8)); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /sncclib.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef struct _ptrint { 4 | int kind; 5 | void* fdecl; 6 | void* argdecls; 7 | void* body; 8 | int stacksize; 9 | void* vdecl; 10 | void* vinit; 11 | void* structtype; 12 | } ptrint; 13 | 14 | struct incom { 15 | int x; 16 | struct incom* next; 17 | }; 18 | 19 | int addpp(int* a, int* b) { 20 | return *a + *b; 21 | } 22 | int addic(int a, char b) { 23 | return a + b; 24 | } 25 | int* padd(int a, char b) { 26 | int* p = malloc(sizeof(int)); 27 | *p = a+b; 28 | return p; 29 | } 30 | 31 | int pi_stacksize(ptrint* pi) { 32 | return pi->stacksize; 33 | } 34 | 35 | struct incom* new_incom() { 36 | struct incom* ic = malloc(sizeof(struct incom)); 37 | ic->next = malloc(sizeof(struct incom)); 38 | ic->next->x = 9; 39 | return ic; 40 | } 41 | 42 | -------------------------------------------------------------------------------- /utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void assert(bool b) { 5 | if (!b) { 6 | fprintf(stderr, "Assertion faled\n"); 7 | exit(1); 8 | } 9 | } 10 | 11 | void error(char* fmt) { 12 | fprintf(stderr, fmt); 13 | fprintf(stderr, "\n"); 14 | exit(1); 15 | } 16 | void error_s(char* fmt, char* s) { 17 | fprintf(stderr, fmt, s); 18 | fprintf(stderr, "\n"); 19 | exit(1); 20 | } 21 | void error_ss(char* fmt, char* s1, char* s2) { 22 | fprintf(stderr, fmt, s1, s2); 23 | fprintf(stderr, "\n"); 24 | exit(1); 25 | } 26 | 27 | void warning(char* fmt) { 28 | fprintf(stderr, "warning: "); 29 | fprintf(stderr, fmt); 30 | fprintf(stderr, "\n"); 31 | } 32 | void warning_s(char* fmt, char* s) { 33 | fprintf(stderr, "warning: "); 34 | fprintf(stderr, fmt, s); 35 | fprintf(stderr, "\n"); 36 | } 37 | -------------------------------------------------------------------------------- /test/funcdecl_test.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "../sncc.h" 5 | 6 | int main() { 7 | init_lexer(); 8 | init_parser(); 9 | vector* tokenss = lexer(); 10 | tokenstream* ts = new_tokenstream(tokenss); 11 | toplevel* top = parse_toplevel(ts); 12 | 13 | if (top->kind == TOP_FUNCDECL) { 14 | printf("%s ", top->fdecl->name); 15 | for (int i=0; iargdecls->len; i++) { 16 | paramtype* pt = vector_get(top->argdecls, i); 17 | printf(" %s", pt->name); 18 | } 19 | } else if (top->kind == TOP_STRUCT) { 20 | printf("%s ", top->structtype->tname); 21 | for (int i=0; istructtype->fields->len; i++) { 22 | paramtype* pt = vector_get(top->structtype->fields, i); 23 | printf(" %s", pt->name); 24 | } 25 | } else { 26 | assert(false); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /map.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "sncc.h" 3 | 4 | map* new_map_cap(int cap) { 5 | map* m = malloc(sizeof(map)); 6 | m->vector = new_vector_cap(cap); 7 | return m; 8 | } 9 | 10 | map* new_map() { 11 | return new_map_cap(256); 12 | } 13 | 14 | mappair* new_mappair(char* name, void* value) { 15 | mappair* mp = malloc(sizeof(mappair)); 16 | mp->name = name; 17 | mp->value = value; 18 | return mp; 19 | } 20 | 21 | void* map_get(map* m, char* name) { 22 | for (int i=0; ivector->len; i++) { 23 | mappair* mp = vector_get(m->vector, i); 24 | if (strcmp(mp->name, name) == 0) { 25 | return mp->value; 26 | } 27 | } 28 | return 0; 29 | } 30 | 31 | void map_insert(map* m, char* name, void* value) { 32 | for (int i=0; i vector->len; i++) { 33 | mappair* mp = vector_get(m->vector, i); 34 | if (strcmp(mp->name, name) == 0) { 35 | mp->value = value; 36 | return; 37 | } 38 | } 39 | vector_push(m->vector, new_mappair(name, value)); 40 | } 41 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | CFLAGS = -Wall -Wextra -O2 -std=c11 3 | 4 | SNCC_LIBS = vector.o map.o lexer.o parser.o semantic.o codegen.o utils.o 5 | SELF_LIBS = vector.self.o map.self.o lexer.self.o parser.self.o semantic.self.o codegen.self.o utils.self.o selflib.self.o 6 | SELF2_LIBS = vector.self2.o map.self2.o lexer.self2.o parser.self2.o semantic.self2.o codegen.self2.o utils.self2.o selflib.self2.o 7 | 8 | build: sncc.out ; 9 | 10 | %.o: %.c sncc.h 11 | $(CC) -c $(CFLAGS) $< 12 | %.self.o: %.c sncc.h 13 | ./sncc.out < $< > $(basename $<).self.s 14 | $(CC) -c $(CFLAGS) $(basename $<).self.s 15 | %.self2.o: %.c sncc.h 16 | ./self < $< > $(basename $<).self2.s 17 | $(CC) -c $(CFLAGS) $(basename $<).self2.s 18 | 19 | lexer.out: $(SNCC_LIBS) sncc.h test/lexer_test.c 20 | $(CC) $(CFLAGS) -olexer.out $(SNCC_LIBS) test/lexer_test.c 21 | parser_expr.out: $(SNCC_LIBS) sncc.h test/parser_expr_test.c 22 | $(CC) $(CFLAGS) -oparser_expr.out $(SNCC_LIBS) test/parser_expr_test.c 23 | parser_stmt.out: $(SNCC_LIBS) sncc.h test/parser_stmt_test.c 24 | $(CC) $(CFLAGS) -oparser_stmt.out $(SNCC_LIBS) test/parser_stmt_test.c 25 | funcdecl.out: $(SNCC_LIBS) sncc.h test/funcdecl_test.c 26 | $(CC) $(CFLAGS) -ofuncdecl.out $(SNCC_LIBS) test/funcdecl_test.c 27 | sncc.out: $(SNCC_LIBS) sncc.c 28 | $(CC) $(CFLAGS) -osncc.out $(SNCC_LIBS) sncc.c 29 | 30 | compiler-test: lexer.out parser_expr.out parser_stmt.out funcdecl.out 31 | ./compiler_test.sh 32 | 33 | test.pp.c: test.c 34 | gcc -P -E test.c > test.pp.c 35 | sncc-test: compiler-test sncc.out test.pp.c 36 | ./sncc.out < test.pp.c > test.s 37 | gcc test.s sncclib.c 38 | ./a.out 39 | 40 | self: sncc.out $(SELF_LIBS) sncc.self.o 41 | $(CC) -oself $(SELF_LIBS) sncc.self.o 42 | self-test: self test.pp.c 43 | ./self < test.pp.c > test.s 44 | gcc test.s sncclib.c 45 | ./a.out 46 | 47 | self2: self $(SELF2_LIBS) sncc.self2.o 48 | $(CC) -oself2 $(SELF2_LIBS) sncc.self2.o 49 | self2-test: self2 test.pp.c 50 | ./self2 < test.pp.c > test.s 51 | gcc test.s sncclib.c 52 | ./a.out 53 | 54 | test: sncc-test self-test self2-test ; 55 | 56 | .PHONY: clean 57 | clean: 58 | @rm -rf *.o *.s *.out self self2 test.pp.c 59 | -------------------------------------------------------------------------------- /compiler_test.sh: -------------------------------------------------------------------------------- 1 | unittest() { 2 | gcc -otest.out -Wall $1 3 | ./test.out 4 | RET=$? 5 | if [ ! $RET = 0 ]; then 6 | echo "[ERROR] unittest: $1" 7 | exit 1 8 | fi 9 | } 10 | 11 | lexertest() { 12 | OUT=`echo "$1" | ./lexer.out` 13 | OUT=`echo $OUT` 14 | if [ ! "$OUT" = "$2" ]; then 15 | echo "[ERROR] lexer: $1, expected $2, but got $OUT" 16 | exit 1 17 | fi 18 | } 19 | 20 | exprtest() { 21 | OUT=`echo "$1" | ./parser_expr.out` 22 | OUT=`echo $OUT` 23 | if [ ! "$OUT" = "$2" ]; then 24 | echo "[ERROR] expr: $1, expected $2, but got $OUT" 25 | exit 1 26 | fi 27 | } 28 | 29 | stmttest() { 30 | OUT=`echo "$1" | ./parser_stmt.out` 31 | OUT=`echo $OUT` 32 | if [ ! "$OUT" = "$2" ]; then 33 | echo "[ERROR] stmt: $1, expected $2, but got $OUT" 34 | exit 1 35 | fi 36 | } 37 | 38 | funcdecltest() { 39 | OUT=`echo "$1" | ./funcdecl.out` 40 | OUT=`echo $OUT` 41 | if [ ! "$OUT" = "$2" ]; then 42 | echo "[ERROR] funcdecl: $1, expected $2, but got $OUT" 43 | exit 1 44 | fi 45 | } 46 | 47 | # unittest "test/vector_test.c" 48 | # unittest "test/map_test.c" 49 | 50 | lexertest "9" "TOKEN_INTLIT:9" 51 | lexertest "12345" "TOKEN_INTLIT:12345" 52 | lexertest "\"yukaia\"" "TOKEN_STRLIT:yukaia" 53 | lexertest "yukari" "TOKEN_IDENT:yukari" 54 | lexertest "+" "TOKEN_ADD:+" 55 | lexertest "-" "TOKEN_SUB:-" 56 | lexertest "*" "TOKEN_MUL:*" 57 | lexertest "/" "TOKEN_DIV:/" 58 | lexertest "=" "TOKEN_ASSIGN:=" 59 | lexertest "&" "TOKEN_AND:&" 60 | lexertest "(" "TOKEN_LPAREN:(" 61 | lexertest ")" "TOKEN_RPAREN:)" 62 | lexertest "[" "TOKEN_LBRACKET:[" 63 | lexertest "]" "TOKEN_RBRACKET:]" 64 | lexertest "{" "TOKEN_LBRACE:{" 65 | lexertest "}" "TOKEN_RBRACE:}" 66 | lexertest "," "TOKEN_COMMA:," 67 | lexertest ";" "TOKEN_SEMICOLON:;" 68 | lexertest "1 + 2" "TOKEN_INTLIT:1 TOKEN_ADD:+ TOKEN_INTLIT:2" 69 | lexertest "3 - 4" "TOKEN_INTLIT:3 TOKEN_SUB:- TOKEN_INTLIT:4" 70 | lexertest "1 + 2 - 3" "TOKEN_INTLIT:1 TOKEN_ADD:+ TOKEN_INTLIT:2 TOKEN_SUB:- TOKEN_INTLIT:3" 71 | lexertest "1 + (2 + 3)" "TOKEN_INTLIT:1 TOKEN_ADD:+ TOKEN_LPAREN:( TOKEN_INTLIT:2 TOKEN_ADD:+ TOKEN_INTLIT:3 TOKEN_RPAREN:)" 72 | lexertest "yukari + ia" "TOKEN_IDENT:yukari TOKEN_ADD:+ TOKEN_IDENT:ia" 73 | lexertest "a = 1" "TOKEN_IDENT:a TOKEN_ASSIGN:= TOKEN_INTLIT:1" 74 | lexertest "n < 2" "TOKEN_IDENT:n TOKEN_LESSER:< TOKEN_INTLIT:2" 75 | lexertest "n > 2" "TOKEN_IDENT:n TOKEN_GREATER:> TOKEN_INTLIT:2" 76 | lexertest "i++" "TOKEN_IDENT:i TOKEN_INC:++" 77 | 78 | exprtest "1" "AST_INTLIT" 79 | exprtest "1 + 2" "AST_ADD" 80 | exprtest "1 - 2" "AST_SUB" 81 | exprtest "2 * 1" "AST_MUL" 82 | exprtest "2 / 1" "AST_DIV" 83 | exprtest "2 < 1" "AST_LESSER" 84 | exprtest "2 > 1" "AST_LESSER" 85 | exprtest "2 != 1" "AST_EQ" 86 | exprtest "2 * 1 + 3" "AST_ADD" 87 | exprtest "2 / 1 + 3" "AST_ADD" 88 | exprtest "1 + 2 * 3" "AST_ADD" 89 | exprtest "1 + 2 / 3" "AST_ADD" 90 | exprtest "(1 + 1) * 2" "AST_MUL" 91 | exprtest "(1 + 1) / 2" "AST_DIV" 92 | exprtest "2 * (1 + 1)" "AST_MUL" 93 | exprtest "2 / (1 + 1)" "AST_DIV" 94 | exprtest "-9" "AST_MINUS" 95 | exprtest "a = 1" "AST_ASSIGN" 96 | exprtest "a = 1 + 2 * 3" "AST_ASSIGN" 97 | exprtest "fib()" "AST_CALL" 98 | exprtest "&a" "AST_ADDR" 99 | exprtest "*a" "AST_DEREF" 100 | exprtest "\"yukaia\"" "AST_STRLIT" 101 | exprtest "*a = 1" "AST_ASSIGN" 102 | exprtest "i++" "AST_POSTINC" 103 | exprtest "i+1++" "AST_ADD" 104 | exprtest "++i" "AST_PREINC" 105 | exprtest "++i++" "AST_PREINC" 106 | exprtest "sizeof(int)*4" "AST_MUL" 107 | exprtest "struc.a" "AST_DOT" 108 | exprtest "struc.a + struc.b" "AST_ADD" 109 | exprtest "struc->a" "AST_DOT" 110 | exprtest "struc->a + struc->b" "AST_ADD" 111 | 112 | stmttest "1; 2; 3;" "3 AST_INTLIT AST_INTLIT AST_INTLIT" 113 | stmttest "1 + 1; 2 - 2; 3 * 3;" "3 AST_ADD AST_SUB AST_MUL" 114 | stmttest "a = 1; a;" "2 AST_ASSIGN AST_IDENT" 115 | stmttest "if (1) 9;" "1 AST_IF" 116 | stmttest "if (1) {9;}" "1 AST_IF" 117 | stmttest "if (1) {9;} else {12;}" "1 AST_IF" 118 | stmttest "while (1) {1;}" "1 AST_WHILE" 119 | stmttest "while (c != EOF) {1;}" "1 AST_WHILE" 120 | stmttest "int a;" "1 AST_STATEMENTS" 121 | stmttest "return 1;" "1 AST_RETURN" 122 | stmttest "int a = 1;" "1 AST_STATEMENTS" 123 | stmttest "break" "1 AST_BREAK" 124 | stmttest "continue" "1 AST_CONTINUE" 125 | 126 | funcdecltest "int* malloc(int size);" "malloc size" 127 | funcdecltest "int main() {}" "main" 128 | funcdecltest "int fib(int n) {n;}" "fib n" 129 | funcdecltest "int padd(int* a, int* b) {int* c; c = a + b;}" "padd a b" 130 | funcdecltest "struct myint { int x; int y; };" "myint x y" 131 | funcdecltest "struct myptr { int* p; };" "myptr p" 132 | funcdecltest "struct myptr { int* p; }; struct myptr* main() {}" "myptr p" 133 | 134 | echo "[OK]" 135 | -------------------------------------------------------------------------------- /example/lsh.c: -------------------------------------------------------------------------------- 1 | /***************************************************************************//** 2 | 3 | @file main.c 4 | 5 | @author Stephen Brennan 6 | 7 | @date Thursday, 8 January 2015 8 | 9 | @brief LSH (Libstephen SHell) 10 | 11 | *******************************************************************************/ 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | /* 21 | Function Declarations for builtin shell commands: 22 | */ 23 | int lsh_cd(char **args); 24 | int lsh_help(char **args); 25 | int lsh_exit(char **args); 26 | 27 | /* 28 | Builtin function implementations. 29 | */ 30 | 31 | /** 32 | @brief Bultin command: change directory. 33 | @param args List of args. args[0] is "cd". args[1] is the directory. 34 | @return Always returns 1, to continue executing. 35 | */ 36 | int lsh_cd(char **args) 37 | { 38 | if (args[1] == NULL) { 39 | fprintf(stderr, "lsh: expected argument to \"cd\"\n"); 40 | } else { 41 | if (chdir(args[1]) != 0) { 42 | perror("lsh"); 43 | } 44 | } 45 | return 1; 46 | } 47 | 48 | /** 49 | @brief Builtin command: print help. 50 | @param args List of args. Not examined. 51 | @return Always returns 1, to continue executing. 52 | */ 53 | int lsh_help(char **args) 54 | { 55 | int i; 56 | printf("Stephen Brennan's LSH\n"); 57 | printf("Type program names and arguments, and hit enter.\n"); 58 | printf("The following are built in:\n"); 59 | 60 | printf(" cd\n"); 61 | printf(" help\n"); 62 | printf(" exit\n"); 63 | 64 | printf("Use the man command for information on other programs.\n"); 65 | return 1; 66 | } 67 | 68 | /** 69 | @brief Builtin command: exit. 70 | @param args List of args. Not examined. 71 | @return Always returns 0, to terminate execution. 72 | */ 73 | int lsh_exit(char **args) 74 | { 75 | return 0; 76 | } 77 | 78 | /** 79 | @brief Launch a program and wait for it to terminate. 80 | @param args Null terminated list of arguments (including program). 81 | @return Always returns 1, to continue execution. 82 | */ 83 | int lsh_launch(char **args) 84 | { 85 | pid_t pid; 86 | int status; 87 | 88 | pid = fork(); 89 | if (pid == 0) { 90 | // Child process 91 | if (execvp(args[0], args) == -1) { 92 | perror("lsh"); 93 | } 94 | exit(EXIT_FAILURE); 95 | } else if (pid < 0) { 96 | // Error forking 97 | perror("lsh"); 98 | } else { 99 | // Parent process 100 | while (1) { 101 | waitpid(pid, &status, WUNTRACED); 102 | if (WIFEXITED(status)) break; 103 | } 104 | } 105 | 106 | return 1; 107 | } 108 | 109 | /** 110 | @brief Execute shell built-in or launch program. 111 | @param args Null terminated list of arguments. 112 | @return 1 if the shell should continue running, 0 if it should terminate 113 | */ 114 | int lsh_execute(char **args) 115 | { 116 | if (args[0] == NULL) { 117 | // An empty command was entered. 118 | return 1; 119 | } 120 | 121 | if (strcmp(args[0], "cd") == 0) { 122 | return lsh_cd(args); 123 | } 124 | if (strcmp(args[0], "help") == 0) { 125 | return lsh_help(args); 126 | } 127 | if (strcmp(args[0], "exit") == 0) { 128 | return lsh_exit(args); 129 | } 130 | 131 | return lsh_launch(args); 132 | } 133 | 134 | #define LSH_RL_BUFSIZE 1024 135 | /** 136 | @brief Read a line of input from stdin. 137 | @return The line from stdin. 138 | */ 139 | char *lsh_read_line() 140 | { 141 | int bufsize = LSH_RL_BUFSIZE; 142 | int position = 0; 143 | char *buffer = malloc(sizeof(char) * bufsize); 144 | int c; 145 | 146 | if (!buffer) { 147 | fprintf(stderr, "lsh: allocation error\n"); 148 | exit(EXIT_FAILURE); 149 | } 150 | 151 | while (1) { 152 | // Read a character 153 | c = getchar(); 154 | 155 | if (c == EOF) { 156 | exit(EXIT_SUCCESS); 157 | } else if (c == '\n') { 158 | buffer[position] = '\0'; 159 | return buffer; 160 | } else { 161 | buffer[position] = c; 162 | } 163 | position++; 164 | 165 | // If we have exceeded the buffer, reallocate. 166 | if (position >= bufsize) { 167 | bufsize += LSH_RL_BUFSIZE; 168 | buffer = realloc(buffer, bufsize); 169 | if (!buffer) { 170 | fprintf(stderr, "lsh: allocation error\n"); 171 | exit(EXIT_FAILURE); 172 | } 173 | } 174 | } 175 | } 176 | 177 | #define LSH_TOK_BUFSIZE 64 178 | #define LSH_TOK_DELIM " \t\r\n\a" 179 | /** 180 | @brief Split a line into tokens (very naively). 181 | @param line The line. 182 | @return Null-terminated array of tokens. 183 | */ 184 | char **lsh_split_line(char *line) 185 | { 186 | int bufsize = LSH_TOK_BUFSIZE; 187 | int position = 0; 188 | char **tokens = malloc(bufsize * sizeof(char*)); 189 | char *token; 190 | char **tokens_backup; 191 | 192 | if (!tokens) { 193 | fprintf(stderr, "lsh: allocation error\n"); 194 | exit(EXIT_FAILURE); 195 | } 196 | 197 | token = strtok(line, " "); 198 | while (token != NULL) { 199 | tokens[position] = token; 200 | position++; 201 | 202 | if (position >= bufsize) { 203 | bufsize += LSH_TOK_BUFSIZE; 204 | tokens_backup = tokens; 205 | tokens = realloc(tokens, bufsize * sizeof(char*)); 206 | if (!tokens) { 207 | fprintf(stderr, "lsh: allocation error\n"); 208 | exit(EXIT_FAILURE); 209 | } 210 | } 211 | 212 | token = strtok(NULL, " "); 213 | } 214 | tokens[position] = NULL; 215 | return tokens; 216 | } 217 | 218 | /** 219 | @brief Loop getting input and executing it. 220 | */ 221 | void lsh_loop() 222 | { 223 | char *line; 224 | char **args; 225 | int status = 1; 226 | 227 | while (status) { 228 | printf("> "); 229 | line = lsh_read_line(); 230 | args = lsh_split_line(line); 231 | status = lsh_execute(args); 232 | 233 | free(line); 234 | free(args); 235 | } 236 | } 237 | 238 | /** 239 | @brief Main entry point. 240 | @param argc Argument count. 241 | @param argv Argument vector. 242 | @return status code 243 | */ 244 | int main(int argc, char **argv) 245 | { 246 | // Load config files, if any. 247 | 248 | // Run command loop. 249 | lsh_loop(); 250 | 251 | // Perform any shutdown/cleanup. 252 | 253 | return EXIT_SUCCESS; 254 | } 255 | 256 | -------------------------------------------------------------------------------- /sncc.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | typedef struct _vector { 6 | void** data; 7 | int cap; 8 | int len; 9 | } vector; 10 | 11 | typedef struct _varinfo { 12 | struct _typenode* typ; 13 | int offset; 14 | } varinfo; 15 | 16 | typedef struct _strlitinfo { 17 | char* label; 18 | char* strval; 19 | } strlitinfo; 20 | 21 | typedef struct _mappair { 22 | char* name; 23 | void* value; 24 | } mappair; 25 | typedef struct _map { 26 | vector* vector; 27 | } map; 28 | 29 | typedef enum _tokenkind { 30 | TOKEN_ADD, 31 | TOKEN_SUB, 32 | TOKEN_MUL, 33 | TOKEN_DIV, 34 | TOKEN_MOD, 35 | TOKEN_LESSER, 36 | TOKEN_GREATER, 37 | TOKEN_LESSEREQ, 38 | TOKEN_GREATEREQ, 39 | TOKEN_ASSIGN, 40 | TOKEN_ADDASSIGN, 41 | TOKEN_MULASSIGN, 42 | TOKEN_LAND, 43 | TOKEN_LOR, 44 | TOKEN_INC, 45 | TOKEN_EQ, 46 | TOKEN_NOTEQ, 47 | TOKEN_NOT, 48 | TOKEN_DOT, 49 | TOKEN_ALLOW, 50 | TOKEN_AND, 51 | TOKEN_INTLIT, 52 | TOKEN_STRLIT, 53 | TOKEN_LPAREN, 54 | TOKEN_RPAREN, 55 | TOKEN_LBRACKET, 56 | TOKEN_RBRACKET, 57 | TOKEN_LBRACE, 58 | TOKEN_RBRACE, 59 | TOKEN_COMMA, 60 | TOKEN_SEMICOLON, 61 | TOKEN_IDENT 62 | } tokenkind; 63 | 64 | typedef struct _token { 65 | tokenkind kind; 66 | int intval; 67 | char* strval; 68 | char* ident; 69 | } token; 70 | 71 | typedef enum _astkind { 72 | AST_ADD, 73 | AST_SUB, 74 | AST_MUL, 75 | AST_DIV, 76 | AST_MOD, 77 | AST_LESSER, 78 | AST_LESSEREQ, 79 | AST_MINUS, 80 | AST_ASSIGN, 81 | AST_ADDASSIGN, 82 | AST_MULASSIGN, 83 | AST_PREINC, 84 | AST_POSTINC, 85 | AST_EQ, 86 | AST_LAND, 87 | AST_LOR, 88 | AST_BAND, 89 | AST_DOT, 90 | AST_ADDR, 91 | AST_DEREF, 92 | AST_VARDECL, 93 | AST_INTLIT, 94 | AST_STRLIT, 95 | AST_IDENT, 96 | AST_GLOBALREF, 97 | AST_CALL, 98 | AST_STATEMENTS, 99 | AST_FUNCDEF, 100 | AST_RETURN, 101 | AST_IF, 102 | AST_WHILE, 103 | AST_FOR, 104 | AST_BREAK, 105 | AST_CONTINUE, 106 | AST_SIZEOF_EXPR, 107 | AST_SIZEOF_TYPE 108 | } astkind; 109 | 110 | typedef enum _typekind { 111 | TYPE_INT, 112 | TYPE_UINT, 113 | TYPE_CHAR, 114 | TYPE_VOID, 115 | TYPE_PTR, 116 | TYPE_ARRAY, 117 | TYPE_STRUCT, 118 | TYPE_INCOMPLETE_STRUCT 119 | } typekind; 120 | 121 | typedef struct _typenode { 122 | typekind kind; 123 | struct _typenode* ptrof; 124 | int arraysize; 125 | struct _typenode* truetype; 126 | char* tname; 127 | vector* fields; 128 | int structsize; 129 | int maxalign; 130 | } typenode; 131 | 132 | typedef struct _paramtype { 133 | typenode* typ; 134 | char* name; 135 | int offset; 136 | } paramtype; 137 | 138 | typedef enum _toplevelkind { 139 | TOP_NONE, 140 | TOP_FUNCDECL, 141 | TOP_GLOBALVAR, 142 | TOP_EXTERN, 143 | TOP_STRUCT 144 | } toplevelkind; 145 | 146 | typedef struct _toplevel { 147 | toplevelkind kind; 148 | paramtype* fdecl; 149 | vector* argdecls; 150 | vector* body; 151 | int stacksize; 152 | paramtype* vdecl; 153 | struct _astree* vinit; 154 | typenode* structtype; 155 | } toplevel; 156 | 157 | typedef struct _astree { 158 | astkind kind; 159 | typenode* typ; 160 | struct _astree* left; 161 | struct _astree* right; 162 | struct _astree* structvalue; 163 | char* fieldname; 164 | paramtype* vardecl; 165 | struct _astree* varinit; 166 | struct _astree* value; 167 | typenode* typedesc; 168 | int intval; 169 | char* strval; 170 | char* ident; 171 | int offset; 172 | struct _astree* call; 173 | vector* arguments; 174 | struct _astree* ifcond; 175 | struct _astree* ifbody; 176 | vector* elifconds; 177 | vector* elifbodies; 178 | struct _astree* elsebody; 179 | struct _astree* whilecond; 180 | struct _astree* whilebody; 181 | struct _astree* forinit; 182 | struct _astree* forcond; 183 | struct _astree* fornext; 184 | struct _astree* forbody; 185 | vector* stmts; 186 | } astree; 187 | 188 | typedef struct _tokenstream { 189 | vector* tokens; 190 | int pos; 191 | } tokenstream; 192 | 193 | // utils.c 194 | void error(char* s); 195 | void error_s(char* fmt, char* s); 196 | void error_ss(char* fmt, char* s1, char* s2); 197 | void warning(char* s); 198 | void warning_s(char* fmt, char* s); 199 | 200 | // globals 201 | extern vector* strlits; 202 | 203 | // vector.c 204 | vector* new_vector_cap(int cap); 205 | vector* new_vector(); 206 | void* vector_get(vector* v, int index); 207 | void vector_set(vector* v, int index, void* elem); 208 | void vector_push(vector* v, void* elem); 209 | 210 | // map.c 211 | map* new_map_cap(int cap); 212 | map* new_map(); 213 | void* map_get(map* m, char* name); 214 | void map_insert(map* m, char* name, void* value); 215 | 216 | // lexer.c 217 | void init_lexer(); 218 | bool single_token_lexer(vector* tokenss); 219 | vector* lexer(); 220 | char* token_to_kindstr(token* token); 221 | char* token_to_str(token* token); 222 | 223 | // parser.c 224 | void init_parser(); 225 | // ast 226 | astree* new_ast(astkind kind); 227 | astree* new_ast_ident(char* ident); 228 | astree* new_ast_intlit(int x); 229 | astree* new_ast_prefix(astkind kind, astree* value); 230 | astree* new_ast_infix(astkind kind, astree* left, astree* right); 231 | char* ast_to_kindstr(astree* ast); 232 | // type 233 | typenode* new_typenode(typekind kind); 234 | typenode* new_ptrnode(typenode* typ); 235 | typenode* new_arraynode(typenode* typ, int size); 236 | // tokenstream 237 | tokenstream* new_tokenstream(vector* tokens); 238 | token* get_token(tokenstream* ts); 239 | void next_token(tokenstream* ts); 240 | astree* expression(tokenstream* ts); 241 | // statement 242 | paramtype* parse_paramtype(tokenstream* ts); 243 | astree* parse_statement(tokenstream* ts); 244 | vector* parse_statements(tokenstream* ts); 245 | astree* parse_compound(tokenstream* ts); 246 | // toplevel 247 | toplevel* parse_toplevel(tokenstream* ts); 248 | 249 | // semantic.c 250 | int typesize(typenode* tn); 251 | paramtype* get_field(typenode* typ, char* fieldname); 252 | char* gen_label(); 253 | void init_semantic(); 254 | void semantic_analysis(astree* ast); 255 | void semantic_analysis_toplevel(toplevel* top); 256 | 257 | // codegen.c 258 | void codegen_strlits(); 259 | void codegen(astree* ast); 260 | void codegen_toplevel(toplevel* top); 261 | // emit 262 | void emit_global(char* name); 263 | void emit_label(char* label); 264 | void emit_pop(char* s); 265 | void emit_return(); 266 | void emit_prologue(int localsize); 267 | void emit_epilogue(); 268 | -------------------------------------------------------------------------------- /semantic.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "sncc.h" 5 | 6 | map* varmap; 7 | int varpos; 8 | map* fnmap; 9 | map* globalvarmap; 10 | vector* strlits; 11 | 12 | int labelcnt = 0; 13 | 14 | char* gen_label() { 15 | labelcnt++; 16 | char labelbuf[256]; 17 | snprintf(labelbuf, 256, ".L%d", labelcnt); 18 | return strdup(labelbuf); 19 | } 20 | 21 | varinfo* new_varinfo(typenode* typ, int offset) { 22 | varinfo* info = malloc(sizeof(varinfo)); 23 | info->typ = typ; 24 | info->offset = offset; 25 | return info; 26 | } 27 | 28 | strlitinfo* new_strlitinfo(char* label, char* strval) { 29 | strlitinfo* info = malloc(sizeof(strlitinfo)); 30 | info->label = label; 31 | info->strval = strval; 32 | return info; 33 | } 34 | 35 | void init_semantic() { 36 | fnmap = new_map(); 37 | globalvarmap = new_map(); 38 | } 39 | 40 | void init_fn_semantic() { 41 | varmap = new_map(); 42 | varpos = 0; 43 | strlits = new_vector(); 44 | } 45 | 46 | int getalign(typenode* typ) { 47 | if (typ->truetype != NULL) { 48 | return getalign(typ->truetype); 49 | } 50 | 51 | if (typ->kind == TYPE_INT) { 52 | return 4; 53 | } else if (typ->kind == TYPE_UINT) { 54 | return 4; 55 | } else if (typ->kind == TYPE_CHAR) { 56 | return 1; 57 | } else if (typ->kind == TYPE_VOID) { 58 | error("void type hasn't align."); 59 | } else if (typ->kind == TYPE_PTR) { 60 | return 8; 61 | } else if (typ->kind == TYPE_ARRAY) { 62 | return getalign(typ->ptrof) * typ->arraysize; 63 | } else if (typ->kind == TYPE_STRUCT) { 64 | if (typ->maxalign == -1) error_s("%s is imcomplete type.", typ->tname); 65 | return typ->maxalign; 66 | } else { 67 | assert(false); 68 | } 69 | } 70 | 71 | int typesize(typenode* typ) { 72 | if (typ->truetype != NULL) { 73 | return typesize(typ->truetype); 74 | } 75 | 76 | if (typ->kind == TYPE_INCOMPLETE_STRUCT) error_s("%s type is incomplete type.", typ->tname); 77 | 78 | if (typ->kind == TYPE_INT) { 79 | return 4; 80 | } else if (typ->kind == TYPE_UINT) { 81 | return 4; 82 | } else if (typ->kind == TYPE_CHAR) { 83 | return 1; 84 | } else if (typ->kind == TYPE_VOID) { 85 | error("void type hasn't align."); 86 | } else if (typ->kind == TYPE_PTR) { 87 | return 8; 88 | } else if (typ->kind == TYPE_ARRAY) { 89 | return typesize(typ->ptrof) * typ->arraysize; 90 | } else if (typ->kind == TYPE_STRUCT) { 91 | if (typ->structsize == -1) error_s("%s is imcomplete type.", typ->tname); 92 | return typ->structsize; 93 | } else { 94 | assert(false); 95 | } 96 | } 97 | 98 | paramtype* get_field(typenode* typ, char* fieldname) { 99 | for (int i=0; ifields->len; i++) { 100 | paramtype* field = vector_get(typ->fields, i); 101 | if (strcmp(field->name, fieldname) == 0) { 102 | return field; 103 | } 104 | } 105 | error_ss("%s hasn't %s field.", typ->tname, fieldname); 106 | } 107 | 108 | bool is_implicit_int(typenode* typ) { 109 | return typ->kind == TYPE_INT || typ->kind == TYPE_UINT ||typ->kind == TYPE_CHAR || typ->kind == TYPE_PTR; 110 | } 111 | 112 | void semantic_analysis(astree* ast) { 113 | if (ast->kind == AST_IDENT) { 114 | varinfo* info = map_get(varmap, ast->ident); 115 | if (info == NULL) { // lookup global variable 116 | typenode* typ = map_get(globalvarmap, ast->ident); 117 | if (typ == NULL) error_s("undeclared %s variable.", ast->ident); 118 | ast->kind = AST_GLOBALREF; 119 | ast->typ = typ; 120 | } else { 121 | ast->typ = info->typ; 122 | ast->offset = info->offset; 123 | } 124 | } else if (ast->kind == AST_INTLIT) { 125 | ast->typ = new_typenode(TYPE_INT); 126 | } else if (ast->kind == AST_STRLIT) { 127 | char* strval = ast->strval; 128 | int strsize = strlen(strval); 129 | ast->kind = AST_GLOBALREF; 130 | ast->ident = gen_label(); 131 | ast->typ = new_arraynode(new_typenode(TYPE_CHAR), strsize+1); 132 | vector_push(strlits, new_strlitinfo(ast->ident, strval)); 133 | } else if (ast->kind == AST_ADD || ast->kind == AST_SUB) { 134 | semantic_analysis(ast->left); 135 | semantic_analysis(ast->right); 136 | if (ast->left->typ->kind == TYPE_PTR && ast->right->typ->kind == TYPE_INT) { 137 | ast->typ = ast->left->typ; 138 | } else if (ast->left->typ->kind == TYPE_UINT && is_implicit_int(ast->right->typ)) { 139 | ast->typ = ast->left->typ; 140 | } else if (is_implicit_int(ast->left->typ) && is_implicit_int(ast->right->typ)) { 141 | ast->typ = new_typenode(TYPE_INT);; 142 | } else { 143 | error("illegal add arithmetic."); 144 | } 145 | } else if (ast->kind == AST_MUL || ast->kind == AST_DIV || ast->kind == AST_MOD || ast->kind == AST_LESSER || ast->kind == AST_LESSEREQ) { 146 | semantic_analysis(ast->left); 147 | semantic_analysis(ast->right); 148 | if (is_implicit_int(ast->left->typ) && is_implicit_int(ast->right->typ)) { 149 | ast->typ = new_typenode(TYPE_INT);; 150 | } else { 151 | error("illegal add arithmetic."); 152 | } 153 | } else if (ast->kind == AST_MINUS) { 154 | semantic_analysis(ast->value); 155 | ast->typ = ast->value->typ; 156 | } else if (ast->kind == AST_ASSIGN || ast->kind == AST_ADDASSIGN || ast->kind == AST_MULASSIGN) { 157 | semantic_analysis(ast->left); 158 | semantic_analysis(ast->right); 159 | ast->typ = new_typenode(TYPE_INT); 160 | } else if (ast->kind == AST_PREINC) { 161 | semantic_analysis(ast->value); 162 | ast->typ = ast->value->typ; 163 | } else if (ast->kind == AST_POSTINC) { 164 | ast->kind = AST_SUB; 165 | ast->left = new_ast_prefix(AST_PREINC, ast->value); 166 | ast->right = new_ast_intlit(1); 167 | semantic_analysis(ast); 168 | } else if (ast->kind == AST_EQ || ast->kind == AST_LAND || ast->kind == AST_LOR || ast->kind == AST_BAND) { 169 | semantic_analysis(ast->left); 170 | semantic_analysis(ast->right); 171 | } else if (ast->kind == AST_DOT) { 172 | semantic_analysis(ast->structvalue); 173 | if (ast->structvalue->typ->kind != TYPE_STRUCT) error("dot left expect struct value."); 174 | paramtype* field = get_field(ast->structvalue->typ, ast->fieldname); 175 | ast->typ = field->typ; 176 | } else if (ast->kind == AST_ADDR) { 177 | semantic_analysis(ast->value); 178 | ast->typ = new_ptrnode(ast->value->typ); 179 | } else if (ast->kind == AST_DEREF) { 180 | semantic_analysis(ast->value); 181 | if (ast->value->typ->kind != TYPE_PTR) error("cannot deref operator apply to noptr."); 182 | ast->typ = ast->value->typ->ptrof; 183 | } else if (ast->kind == AST_VARDECL) { 184 | varpos += typesize(ast->vardecl->typ); 185 | map_insert(varmap, ast->vardecl->name, new_varinfo(ast->vardecl->typ, varpos)); 186 | if (ast->varinit != NULL) { 187 | ast->kind = AST_ASSIGN; 188 | ast->left = new_ast_ident(ast->vardecl->name); 189 | ast->right = ast->varinit; 190 | semantic_analysis(ast); 191 | } 192 | } else if (ast->kind == AST_CALL && ast->call->kind == AST_IDENT) { 193 | for (int i=0; iarguments->len; i++) { 194 | semantic_analysis(vector_get(ast->arguments, i)); 195 | } 196 | typenode* rettyp = map_get(fnmap, ast->call->ident); 197 | if (rettyp == NULL){ 198 | warning_s("undeclared %s function.", ast->call->ident); 199 | ast->typ = new_typenode(TYPE_INT); 200 | } else { 201 | ast->typ = rettyp; 202 | } 203 | } else if (ast->kind == AST_STATEMENTS) { 204 | for (int i=0; istmts->len; i++) { 205 | astree* e = vector_get(ast->stmts, i); 206 | semantic_analysis(e); 207 | } 208 | } else if (ast->kind == AST_RETURN) { 209 | if (ast->value != NULL) { 210 | semantic_analysis(ast->value); 211 | } 212 | } else if (ast->kind == AST_IF) { 213 | semantic_analysis(ast->ifcond); 214 | semantic_analysis(ast->ifbody); 215 | for (int i=0; ielifconds->len; i++) { 216 | astree* cond = vector_get(ast->elifconds, i); 217 | astree* body = vector_get(ast->elifbodies, i); 218 | semantic_analysis(cond); 219 | semantic_analysis(body); 220 | } 221 | if (ast->elsebody != NULL) { 222 | semantic_analysis(ast->elsebody); 223 | } 224 | } else if (ast->kind == AST_WHILE) { 225 | semantic_analysis(ast->whilecond); 226 | semantic_analysis(ast->whilebody); 227 | } else if (ast->kind == AST_FOR) { 228 | semantic_analysis(ast->forinit); 229 | semantic_analysis(ast->forcond); 230 | semantic_analysis(ast->fornext); 231 | semantic_analysis(ast->forbody); 232 | } else if (ast->kind == AST_BREAK || ast->kind == AST_CONTINUE) { 233 | // discard 234 | } else if (ast->kind == AST_SIZEOF_EXPR) { 235 | semantic_analysis(ast->value); 236 | ast->kind = AST_INTLIT; 237 | ast->intval = typesize(ast->value->typ); 238 | ast->typ = new_typenode(TYPE_INT); 239 | } else if (ast->kind == AST_SIZEOF_TYPE) { 240 | ast->kind = AST_INTLIT; 241 | ast->intval = typesize(ast->typedesc); 242 | ast->typ = new_typenode(TYPE_INT); 243 | } else { 244 | error("unsupported kind in semantic"); 245 | } 246 | } 247 | 248 | void semantic_analysis_toplevel(toplevel* top) { 249 | init_fn_semantic(); 250 | if (top->kind == TOP_NONE) { 251 | // discard 252 | } else if (top->kind == TOP_FUNCDECL) { 253 | map_insert(fnmap, top->fdecl->name, top->fdecl->typ); 254 | for (int i=0; iargdecls->len; i++) { 255 | paramtype* argparam = vector_get(top->argdecls, i); 256 | varpos += typesize(argparam->typ); 257 | argparam->offset = varpos; 258 | map_insert(varmap, argparam->name, new_varinfo(argparam->typ, varpos)); 259 | } 260 | if (top->body != NULL) { 261 | for (int i=0; ibody->len; i++) { 262 | semantic_analysis(vector_get(top->body, i)); 263 | } 264 | top->stacksize = varpos; 265 | } 266 | } else if (top->kind == TOP_EXTERN) { 267 | map_insert(globalvarmap, top->vdecl->name, top->vdecl->typ); 268 | } else if (top->kind == TOP_GLOBALVAR) { 269 | map_insert(globalvarmap, top->vdecl->name, top->vdecl->typ); 270 | if (top->vinit != NULL) { 271 | if (top->vinit->kind != AST_INTLIT && top->vinit->kind != AST_STRLIT && !(top->vinit->kind == AST_MINUS && top->vinit->value->kind == AST_INTLIT)) { 272 | error("global variable expected constant expression."); 273 | } 274 | if (top->vinit->kind == AST_STRLIT) { 275 | top->vdecl->typ->truetype = new_typenode(TYPE_ARRAY); 276 | top->vdecl->typ->truetype->ptrof = new_typenode(TYPE_CHAR); 277 | top->vdecl->typ->truetype->arraysize = strlen(top->vinit->strval) + 1; 278 | } 279 | } 280 | } else if (top->kind == TOP_STRUCT) { 281 | // decide typesize 282 | int maxalign = 0; 283 | for (int i=0; istructtype->fields->len; i++) { 284 | paramtype* field = vector_get(top->structtype->fields, i); 285 | if (maxalign < getalign(field->typ)) { 286 | maxalign = getalign(field->typ); 287 | } 288 | } 289 | int alignsize = 0; 290 | int structsize = 0; 291 | for (int i=0; istructtype->fields->len; i++) { 292 | paramtype* field = vector_get(top->structtype->fields, i); 293 | if (alignsize == maxalign) { 294 | alignsize = 0; 295 | } else if (alignsize+typesize(field->typ) > maxalign) { 296 | structsize += maxalign - alignsize % maxalign; 297 | alignsize = 0; 298 | } 299 | field->offset = structsize; 300 | structsize += typesize(field->typ); 301 | alignsize += typesize(field->typ); 302 | } 303 | if (alignsize != maxalign) { 304 | structsize += maxalign - alignsize % maxalign; 305 | } 306 | top->structtype->structsize = structsize; 307 | top->structtype->maxalign = maxalign; 308 | } else { 309 | assert(false); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /test.c: -------------------------------------------------------------------------------- 1 | 2 | #define test(x, expect) test_impl(x, expect, #x, __LINE__) 3 | 4 | // test 5 | 6 | /* 7 | * C compiler test 8 | */ 9 | 10 | void printf(char* fmt); 11 | void exit(int x); 12 | int strcmp(char* a, char* b); 13 | char* strtok(char* s1, char* s2); 14 | 15 | void test_impl(int x, int expect, char* s, int line) { 16 | if (!(x == expect)) { 17 | printf("[ERROR] L%d %s: expect %d, but got %d", line, s, expect, x); 18 | exit(1); 19 | } 20 | } 21 | 22 | void infix_test() { 23 | test(1+2, 3); 24 | test(2-1, 1); 25 | test(1+10-2, 9); 26 | test(1+2*3, 7); 27 | test(7+2/2, 8); 28 | test((1+1)*2, 4); 29 | test((1+1)/2, 1); 30 | test(4 % 4, 0); 31 | test(4 % 5, 4); 32 | test(5 % 4, 1); 33 | test(9 == 9, 1); 34 | test(9 == 8, 0); 35 | test(!0, 1); 36 | test(!1, 0); 37 | test(!10, 0); 38 | test(2 <= 5-2, 1); 39 | test(10 <= 5-2, 0); 40 | 41 | test(10 & 7, 2); 42 | 43 | test(1 && 1, 1); 44 | test(1 && 0, 0); 45 | test(0 && 0, 0); 46 | test(0 || 1, 1); 47 | test(1 || 0, 1); 48 | test(0 || 0, 0); 49 | test(0 || 0 || 0 || 1, 1); 50 | test(1 && 1 && 1 && 0, 0); 51 | test(1 && 1 && 1 && 1, 1); 52 | } 53 | 54 | void op_test() { 55 | int a = 0; 56 | test(++a, 1); 57 | test(a, 1); 58 | test(++a, 2); 59 | test(a, 2); 60 | a += 2; 61 | test(a, 4); 62 | a *= 2; 63 | test(a, 8); 64 | 65 | int i = 0; 66 | test(i++, 0); 67 | test(i, 1); 68 | test(i++, 1); 69 | test(i, 2); 70 | } 71 | 72 | void variable_test() { 73 | int a = 9; 74 | int b = 8; 75 | test(a + b, 17); 76 | int c, d; 77 | c = 4; 78 | d = 5; 79 | test(c, 4); 80 | test(d, 5); 81 | int e, f = 1, 2; 82 | test(e, 1); 83 | test(f, 2); 84 | } 85 | 86 | int return_test_impl() { 87 | return 1+3*3; 88 | } 89 | void return_test() { 90 | test(return_test_impl(), 10); 91 | } 92 | 93 | int add(int a, int b) { 94 | return a + b; 95 | } 96 | 97 | int add8(int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { 98 | return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8; 99 | } 100 | 101 | void call_test() { 102 | test(add(4, 5), 9); 103 | test(add8(1, 1, 1, 1, 1, 1, 1, 1), 8); 104 | } 105 | 106 | int if_test_impl1() { 107 | if (1) return 9; 108 | if (0) return 5; 109 | } 110 | 111 | int if_test_impl2() { 112 | if (0) return 9; 113 | if (1) return 5; 114 | } 115 | 116 | int if_test_impl3() { 117 | if (0) { 118 | return 9; 119 | } 120 | if (1) { 121 | return 5; 122 | } 123 | } 124 | 125 | int if_test_impl4() { 126 | if (0) { 127 | return 0; 128 | } else if (0) { 129 | return 0; 130 | } else if (1) { 131 | return 1; 132 | } else { 133 | return 0; 134 | } 135 | } 136 | 137 | void if_test() { 138 | test(if_test_impl1(), 9); 139 | test(if_test_impl2(), 5); 140 | test(if_test_impl3(), 5); 141 | test(if_test_impl4(), 1); 142 | } 143 | 144 | void while_test() { 145 | int i = 0; 146 | while (i<10) { 147 | i++; 148 | } 149 | test(i, 10); 150 | i = 0; 151 | while (i<10) { 152 | if (i == 5) break; 153 | i++; 154 | } 155 | test(i, 5); 156 | i = 0; 157 | while (i<10) { 158 | if (i < 5) { 159 | i++; 160 | continue; 161 | } 162 | break; 163 | } 164 | test(i, 5); 165 | } 166 | 167 | int for_test_impl() { 168 | for (int i=0; i<10; i++) { 169 | if (i == 5) return i; 170 | } 171 | } 172 | 173 | void for_test() { 174 | for (int i=0; i<10; i++) { 175 | } 176 | test(i, 10); 177 | test(for_test_impl(), 5); 178 | for (int i=0; i<10; i++) { 179 | if (i == 5) break; 180 | } 181 | test(i, 5); 182 | for (int i=0; i<10; i++) { 183 | if (i < 9) continue; 184 | break; 185 | } 186 | test(i, 9); 187 | } 188 | 189 | void addr_test() { 190 | int x; 191 | int* p = &x; 192 | *p = 9; 193 | test(x, 9); 194 | 195 | int** pp = &p; 196 | **pp = 555; 197 | test(x, 555); 198 | } 199 | 200 | void pointer_arithmetic_test() { 201 | int arr[10]; 202 | int* p = arr; 203 | *(p+0) = 1; 204 | *(p+1) = 2; 205 | *(p+2) = 3; 206 | *(p+3) = 4; 207 | test(arr[0] + arr[1] + arr[2] + arr[3], 10); 208 | } 209 | 210 | int fib(int n) { 211 | if (n < 2) { 212 | return n; 213 | } else { 214 | return fib(n-1) + fib(n-2); 215 | } 216 | } 217 | 218 | void fib_test() { 219 | test(fib(10), 55); 220 | } 221 | 222 | void sizeof_test() { 223 | test(sizeof(int), 4); 224 | test(sizeof(int*), 8); 225 | test(sizeof int, 4); 226 | test(sizeof int*, 8); 227 | int iarr[10]; 228 | int* parr[10]; 229 | test(sizeof iarr, 40); 230 | test(sizeof parr, 80); 231 | } 232 | 233 | void array_test() { 234 | int arr[10]; 235 | arr[0] = 1; 236 | arr[1] = 2; 237 | arr[2] = 3; 238 | arr[3] = 4; 239 | test(arr[0] + arr[1] + arr[2] + arr[3], 10); 240 | 241 | *&arr[0] = 10; 242 | test(arr[0], 10); 243 | } 244 | 245 | int gx; 246 | int garr[10]; 247 | void globalvar_test() { 248 | gx = 9; 249 | test(gx, 9); 250 | int* p = &gx; 251 | *p = 555; 252 | test(gx, 555); 253 | 254 | garr[0] = 1; 255 | garr[1] = 9; 256 | test(garr[0] + garr[1], 10); 257 | } 258 | 259 | void string_test() { 260 | char cc[3]; 261 | cc[0] = 9; 262 | test(cc[0], 9); 263 | 264 | char* s = "yukaia"; 265 | test(s[0], 121); 266 | } 267 | 268 | int N; 269 | int S; 270 | int dfs(int i, int sum, int cnt) { 271 | if (cnt == N) { 272 | if (sum == S) { 273 | return 1; 274 | } 275 | } 276 | if (i == 10) return 0; 277 | if (cnt == N) return 0; 278 | 279 | int acc = 0; 280 | acc = acc+dfs(i+1, sum+i, cnt+1); 281 | acc = acc+dfs(i+1, sum, cnt); 282 | return acc; 283 | } 284 | 285 | void aoj0030() { 286 | N = 3; 287 | S = 6; 288 | test(dfs(0, 0, 0), 3); 289 | } 290 | 291 | int GI = 9; 292 | char* GS = "yukaia"; 293 | void globalinit_test() { 294 | test(GI, 9); 295 | test(GS[0], 121); 296 | } 297 | 298 | void* malloc(int size); 299 | 300 | void malloc_test() { 301 | int* p = malloc(sizeof(int)*4); 302 | p[0] = 1; 303 | p[1] = 2; 304 | p[2] = 3; 305 | p[3] = 4; 306 | test(p[0] + p[1] + p[2] + p[3], 10); 307 | } 308 | 309 | struct mychar { 310 | char a; 311 | char b; 312 | }; 313 | struct mychar3 { 314 | char a; 315 | char b; 316 | char c; 317 | }; 318 | struct mycharptr { 319 | char a; 320 | char b; 321 | int* p; 322 | }; 323 | struct myintc { 324 | char c; 325 | int x; 326 | }; 327 | struct mychari { 328 | int x; 329 | char c; 330 | }; 331 | struct mycwrap { 332 | struct mychar mc; 333 | int x; 334 | }; 335 | struct myptr { 336 | int* p; 337 | struct myintc mic; 338 | }; 339 | struct icci { 340 | int a; 341 | char b; 342 | char c; 343 | int d; 344 | }; 345 | 346 | typedef struct _ptrint { 347 | int kind; 348 | void* fdecl; 349 | void* argdecls; 350 | void* body; 351 | int stacksize; 352 | void* vdecl; 353 | void* vinit; 354 | void* structtype; 355 | } ptrint; 356 | 357 | typedef enum _tokenkind { 358 | TOKEN_ADD, 359 | TOKEN_SUB, 360 | TOKEN_MUL, 361 | TOKEN_DIV, 362 | } tokenkind; 363 | 364 | typedef struct _token { 365 | tokenkind kind; 366 | int intval; 367 | char* strval; 368 | char* ident; 369 | } token; 370 | 371 | void struct_sizeof_test() { 372 | test(sizeof(struct mychar), 2); 373 | test(sizeof(struct mychar3), 3); 374 | test(sizeof(struct mycharptr), 16); 375 | test(sizeof(struct myintc), 8); 376 | test(sizeof(struct mychari), 8); 377 | test(sizeof(struct mycwrap), 8); 378 | test(sizeof(struct myptr), 16); 379 | test(sizeof(struct icci), 12); 380 | test(sizeof(ptrint), 64); 381 | test(sizeof(token), 24); 382 | } 383 | 384 | int pi_stacksize(ptrint* pi); 385 | 386 | void struct_dot_test() { 387 | struct mychar mc; 388 | mc.a = 1; 389 | mc.b = 2; 390 | test(mc.a + mc.b, 3); 391 | 392 | struct myptr mp; 393 | mp.mic.c = 4; 394 | mp.mic.x = 5; 395 | test(mp.mic.c + mp.mic.x, 9); 396 | 397 | ptrint pi; 398 | pi.stacksize = 555; 399 | test(pi_stacksize(&pi), 555); 400 | } 401 | 402 | void struct_allow_test() { 403 | struct mychar mc; 404 | struct mychar* mcp = &mc; 405 | mcp->a = 1; 406 | mcp->b = 2; 407 | test(mcp->a + mcp->b, 3); 408 | 409 | struct myptr mp; 410 | struct myptr* mpp = ∓ 411 | mpp->mic.c = 4; 412 | mpp->mic.x = 5; 413 | test(mpp->mic.c + mpp->mic.x, 9); 414 | } 415 | 416 | struct incom { 417 | int x; 418 | struct incom* next; 419 | }; 420 | 421 | struct incom* new_incom(); 422 | 423 | void struct_incomplete_test() { 424 | test(sizeof(struct incom), 16); 425 | struct incom ic; 426 | struct incom icnext; 427 | ic.next = &icnext; 428 | ic.next->x = 9; 429 | test(icnext.x, 9); 430 | 431 | struct incom* ic2 = new_incom(); 432 | test(ic2->next->x, 9); 433 | test(new_incom()->next->x, 9); 434 | } 435 | 436 | enum tokenkind { 437 | TOKEN_IDENT, 438 | TOKEN_INTLIT, 439 | TOKEN_STRLIT 440 | }; 441 | typedef enum _astkind { 442 | AST_IDENT, 443 | AST_INTLIT, 444 | AST_STRLIT 445 | } astkind; 446 | 447 | typedef struct _ast { 448 | astkind kind; 449 | char* ident; 450 | } astree; 451 | 452 | astree* parse_ast() { 453 | astree* ast = malloc(sizeof(astree)); 454 | ast->kind = AST_IDENT; 455 | ast->ident = "yukari"; 456 | return ast; 457 | } 458 | 459 | void parse_test() { 460 | astree* ast = parse_ast(); 461 | test(strcmp(ast->ident, "yukari"), 0); 462 | } 463 | 464 | void enum_test() { 465 | enum tokenkind tk1 = TOKEN_IDENT; 466 | enum tokenkind tk2 = TOKEN_STRLIT; 467 | test(tk1, 0); 468 | test(tk2, 2); 469 | astkind ak1 = AST_IDENT; 470 | astkind ak2 = AST_STRLIT; 471 | test(ak1, 0); 472 | test(ak2, 2); 473 | } 474 | 475 | typedef struct _vector { 476 | void** data; 477 | int cap; 478 | } vector; 479 | 480 | vector* new_vector_cap(int cap) { 481 | vector* v = malloc(sizeof(vector)); 482 | v->data = malloc(sizeof(void*)*cap); 483 | v->cap = cap; 484 | return v; 485 | } 486 | 487 | void typedef_vector_test() { 488 | vector* v = new_vector_cap(10); 489 | int a; 490 | int b; 491 | int c; 492 | v->data[0] = &a; 493 | v->data[1] = &b; 494 | v->data[2] = &c; 495 | } 496 | 497 | typedef int bool; 498 | #define true 1 499 | #define false 0 500 | 501 | void typedef_bool_test() { 502 | bool t = true; 503 | bool f = false; 504 | test(t, 1); 505 | test(f, 0); 506 | } 507 | 508 | int addpp(int* a, int* b); 509 | int addic(int a, char b); 510 | int* padd(int a, char b); 511 | 512 | void exfn_test() { 513 | int x = 4; 514 | int y = 5; 515 | test(addpp(&x, &y), 9); 516 | 517 | int x = 4; 518 | char y = 5; 519 | test(addic(x, y), 9); 520 | 521 | int x = 4; 522 | char y = 5; 523 | int* p = padd(x, y); 524 | test(*p, 9); 525 | } 526 | 527 | extern int a; 528 | 529 | void charlit_test() { 530 | test('0', 48); 531 | test('a', 97); 532 | test('\'', 39); 533 | test('\\', 92); 534 | test('"', 34); 535 | test('(', 40); 536 | test(' ', 32); 537 | } 538 | 539 | void strtok_test() { 540 | char* s = malloc(sizeof(char)*10); 541 | s[0] = 'y'; 542 | s[1] = 'u'; 543 | s[2] = 'k'; 544 | s[3] = 'a'; 545 | s[4] = 'r'; 546 | s[5] = 'i'; 547 | s[6] = ' '; 548 | s[7] = 'i'; 549 | s[8] = 'a'; 550 | s[9] = '\0'; 551 | char* deli = " "; 552 | test(strcmp(strtok(s, " "), "yukari"), 0); 553 | test(strcmp(strtok(0, " "), "ia"), 0); 554 | } 555 | 556 | void unsigned_test() { 557 | unsigned int x = 2147483646; 558 | test(x, 2147483646); 559 | test(x+1, 2147483647); 560 | } 561 | 562 | int main() { 563 | infix_test(); 564 | op_test(); 565 | variable_test(); 566 | return_test(); 567 | call_test(); 568 | if_test(); 569 | while_test(); 570 | for_test(); 571 | addr_test(); 572 | pointer_arithmetic_test(); 573 | fib_test(); 574 | sizeof_test(); 575 | array_test(); 576 | globalvar_test(); 577 | string_test(); 578 | aoj0030(); 579 | globalinit_test(); 580 | malloc_test(); 581 | struct_sizeof_test(); 582 | struct_dot_test(); 583 | struct_allow_test(); 584 | struct_incomplete_test(); 585 | parse_test(); 586 | enum_test(); 587 | typedef_vector_test(); 588 | typedef_bool_test(); 589 | exfn_test(); 590 | charlit_test(); 591 | strtok_test(); 592 | unsigned_test(); 593 | 594 | printf("[OK]\n"); 595 | return 0; 596 | } 597 | -------------------------------------------------------------------------------- /lexer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "sncc.h" 7 | 8 | FILE* input; 9 | map* definemap; 10 | 11 | void init_lexer() { 12 | input = stdin; 13 | definemap = new_map(); 14 | } 15 | 16 | token* new_token(tokenkind kind) { 17 | token* t = malloc(sizeof(token)); 18 | t->kind = kind; 19 | return t; 20 | } 21 | 22 | token* new_intlit(int x) { 23 | token* t = new_token(TOKEN_INTLIT); 24 | t->intval = x; 25 | return t; 26 | } 27 | token* new_strlit(char* s) { 28 | token* t = new_token(TOKEN_STRLIT); 29 | t->strval = s; 30 | return t; 31 | } 32 | token* new_ident(char* s) { 33 | token* t = new_token(TOKEN_IDENT); 34 | t->ident = strdup(s); 35 | return t; 36 | } 37 | 38 | char* int_to_str(int x) { 39 | char* buf = malloc(6+1); 40 | snprintf(buf, 6, "%d", x); 41 | return buf; 42 | } 43 | bool isident(char c) { 44 | return isalpha(c) || c == '_'; 45 | } 46 | bool isidenttail(char c) { 47 | return isident(c) || isdigit(c); 48 | } 49 | 50 | char* token_to_kindstr(token* token) { 51 | if (token->kind == TOKEN_ADD) { 52 | return "TOKEN_ADD"; 53 | } else if (token->kind == TOKEN_SUB) { 54 | return "TOKEN_SUB"; 55 | } else if (token->kind == TOKEN_MUL) { 56 | return "TOKEN_MUL"; 57 | } else if (token->kind == TOKEN_DIV) { 58 | return "TOKEN_DIV"; 59 | } else if (token->kind == TOKEN_LESSER) { 60 | return "TOKEN_LESSER"; 61 | } else if (token->kind == TOKEN_GREATER) { 62 | return "TOKEN_GREATER"; 63 | } else if (token->kind == TOKEN_LESSEREQ) { 64 | return "TOKEN_LESSEREQ"; 65 | } else if (token->kind == TOKEN_GREATEREQ) { 66 | return "TOKEN_GREATEREQ"; 67 | } else if (token->kind == TOKEN_ASSIGN) { 68 | return "TOKEN_ASSIGN"; 69 | } else if (token->kind == TOKEN_ADDASSIGN) { 70 | return "TOKEN_ADDASSIGN"; 71 | } else if (token->kind == TOKEN_MULASSIGN) { 72 | return "TOKEN_MULASSIGN"; 73 | } else if (token->kind == TOKEN_LAND) { 74 | return "TOKEN_LAND"; 75 | } else if (token->kind == TOKEN_LOR) { 76 | return "TOKEN_LOR"; 77 | } else if (token->kind == TOKEN_INC) { 78 | return "TOKEN_INC"; 79 | } else if (token->kind == TOKEN_EQ) { 80 | return "TOKEN_EQ"; 81 | } else if (token->kind == TOKEN_NOTEQ) { 82 | return "TOKEN_NOTEQ"; 83 | } else if (token->kind == TOKEN_NOT) { 84 | return "TOKEN_NOT"; 85 | } else if (token->kind == TOKEN_DOT) { 86 | return "TOKEN_DOT"; 87 | } else if (token->kind == TOKEN_ALLOW) { 88 | return "TOKEN_ALLOW"; 89 | } else if (token->kind == TOKEN_AND) { 90 | return "TOKEN_AND"; 91 | } else if (token->kind == TOKEN_INTLIT) { 92 | return "TOKEN_INTLIT"; 93 | } else if (token->kind == TOKEN_STRLIT) { 94 | return "TOKEN_STRLIT"; 95 | } else if (token->kind == TOKEN_LPAREN) { 96 | return "TOKEN_LPAREN"; 97 | } else if (token->kind == TOKEN_RPAREN) { 98 | return "TOKEN_RPAREN"; 99 | } else if (token->kind == TOKEN_LBRACKET) { 100 | return "TOKEN_LBRACKET"; 101 | } else if (token->kind == TOKEN_RBRACKET) { 102 | return "TOKEN_RBRACKET"; 103 | } else if (token->kind == TOKEN_LBRACE) { 104 | return "TOKEN_LBRACE"; 105 | } else if (token->kind == TOKEN_RBRACE) { 106 | return "TOKEN_RBRACE"; 107 | } else if (token->kind == TOKEN_COMMA) { 108 | return "TOKEN_COMMA"; 109 | } else if (token->kind == TOKEN_SEMICOLON) { 110 | return "TOKEN_SEMICOLON"; 111 | } else if (token->kind == TOKEN_IDENT) { 112 | return "TOKEN_IDENT"; 113 | } else { 114 | assert(0); 115 | } 116 | } 117 | char* token_to_str(token* token) { 118 | if (token->kind == TOKEN_ADD) { 119 | return "+"; 120 | } else if (token->kind == TOKEN_SUB) { 121 | return "-"; 122 | } else if (token->kind == TOKEN_MUL) { 123 | return "*"; 124 | } else if (token->kind == TOKEN_DIV) { 125 | return "/"; 126 | } else if (token->kind == TOKEN_LESSER) { 127 | return "<"; 128 | } else if (token->kind == TOKEN_GREATER) { 129 | return ">"; 130 | } else if (token->kind == TOKEN_LESSEREQ) { 131 | return "<="; 132 | } else if (token->kind == TOKEN_GREATEREQ) { 133 | return ">="; 134 | } else if (token->kind == TOKEN_ASSIGN) { 135 | return "="; 136 | } else if (token->kind == TOKEN_ADDASSIGN) { 137 | return "+="; 138 | } else if (token->kind == TOKEN_MULASSIGN) { 139 | return "*="; 140 | } else if (token->kind == TOKEN_LAND) { 141 | return "&&"; 142 | } else if (token->kind == TOKEN_LOR) { 143 | return "||"; 144 | } else if (token->kind == TOKEN_INC) { 145 | return "++"; 146 | } else if (token->kind == TOKEN_EQ) { 147 | return "=="; 148 | } else if (token->kind == TOKEN_NOT) { 149 | return "!"; 150 | } else if (token->kind == TOKEN_DOT) { 151 | return "."; 152 | } else if (token->kind == TOKEN_ALLOW) { 153 | return "->"; 154 | } else if (token->kind == TOKEN_AND) { 155 | return "&"; 156 | } else if (token->kind == TOKEN_LPAREN) { 157 | return "("; 158 | } else if (token->kind == TOKEN_RPAREN) { 159 | return ")"; 160 | } else if (token->kind == TOKEN_LBRACE) { 161 | return "{"; 162 | } else if (token->kind == TOKEN_RBRACE) { 163 | return "}"; 164 | } else if (token->kind == TOKEN_LBRACKET) { 165 | return "["; 166 | } else if (token->kind == TOKEN_RBRACKET) { 167 | return "]"; 168 | } else if (token->kind == TOKEN_COMMA) { 169 | return ","; 170 | } else if (token->kind == TOKEN_SEMICOLON) { 171 | return ";"; 172 | } else if (token->kind == TOKEN_INTLIT) { 173 | return int_to_str(token->intval); 174 | } else if (token->kind == TOKEN_STRLIT) { 175 | return token->strval; 176 | } else if (token->kind == TOKEN_IDENT) { 177 | return token->ident; 178 | } else { 179 | assert(0); 180 | } 181 | } 182 | 183 | void skip_spaces() { 184 | while (true) { 185 | char nc = getc(input); 186 | if (nc != ' ') { 187 | ungetc(nc, input); 188 | break; 189 | } 190 | } 191 | } 192 | 193 | char* read_ident() { 194 | skip_spaces(); 195 | char identbuf[256]; 196 | int i = 0; 197 | while (true) { 198 | if (i >= 256) assert(false); 199 | char nc = getc(input); 200 | if (!isidenttail(nc)) { 201 | ungetc(nc, input); 202 | identbuf[i] = 0; 203 | break; 204 | } 205 | identbuf[i] = nc; 206 | i++; 207 | } 208 | return strdup(identbuf); 209 | } 210 | 211 | char* read_strlit() { 212 | char strbuf[1024]; 213 | bool inesc = false; 214 | int i = 0; 215 | while (true) { 216 | assert(i < 1024); 217 | char nc = getc(input); 218 | if (inesc && nc == '\\') { 219 | strbuf[i] = '\\'; 220 | strbuf[i+1] = '\\'; 221 | inesc = false; 222 | i++; 223 | } else if (inesc) { 224 | strbuf[i] = '\\'; 225 | strbuf[i+1] = nc; 226 | inesc = false; 227 | i++; 228 | } else if (nc == '\\') { 229 | inesc = true; 230 | i = i-1; 231 | } else if (nc == '"') { 232 | strbuf[i] = 0; 233 | break; 234 | } else if (nc == EOF) { 235 | error("expect end of string literal."); 236 | } else { 237 | strbuf[i] = nc; 238 | } 239 | i++; 240 | } 241 | return strdup(strbuf); 242 | } 243 | 244 | char* read_strlit_angled() { 245 | skip_spaces(); 246 | char strbuf[1024]; 247 | int i = 0; 248 | while (true) { 249 | assert(i < 1024); 250 | char nc = getc(input); 251 | if (nc == '>') { 252 | strbuf[i] = 0; 253 | break; 254 | } 255 | if (nc == EOF) error("expect end of string literal."); 256 | strbuf[i] = nc; 257 | i++; 258 | } 259 | return strdup(strbuf); 260 | } 261 | 262 | void preprocessor(vector* tokenss, char* prename) { 263 | if (strcmp(prename, "include") == 0) { 264 | skip_spaces(); 265 | char c = getc(input); 266 | char* includename; 267 | if (c == '"') { 268 | includename = read_strlit(); 269 | } else if (c == '<') { 270 | includename = malloc(sizeof(char)*1024+sizeof(char)); 271 | char* slit = read_strlit_angled(); 272 | snprintf(includename, 1024, "include/%s", slit); 273 | } else { 274 | error("#include expected string literal."); 275 | } 276 | FILE* tmpf = input; 277 | input = fopen(includename, "r"); 278 | if (input == NULL) { fprintf(stderr, "%s: No such file", includename); 279 | exit(1); 280 | } 281 | vector* includetokens = lexer(); 282 | for (int i=0; ilen; i++) { 283 | vector_push(tokenss, vector_get(includetokens, i)); 284 | } 285 | fclose(input); 286 | input = tmpf; 287 | } else if (strcmp(prename, "define") == 0) { 288 | char* definename = read_ident(); 289 | vector* definetokens = new_vector(); 290 | while (true) { 291 | skip_spaces(); 292 | char c = getc(input); 293 | if (c == '\n') break; 294 | ungetc(c, input); 295 | bool cont = single_token_lexer(definetokens); 296 | if (!cont) break; 297 | } 298 | map_insert(definemap, definename, definetokens); 299 | } else { 300 | error("unsupported preprocessor."); 301 | } 302 | } 303 | 304 | bool single_token_lexer(vector* tokenss) { 305 | char c = getc(input); 306 | 307 | if (c == EOF) { 308 | return false; 309 | } else if (isdigit(c)) { // int literal 310 | char digitbuf[256]; 311 | digitbuf[0] = c; 312 | int i=1; 313 | while (true) { 314 | assert(i < 256); 315 | char nc = getc(input); 316 | if (!isdigit(nc)) { 317 | ungetc(nc, input); 318 | digitbuf[i] = 0; 319 | vector_push(tokenss, new_intlit(atoi(digitbuf))); 320 | break; 321 | } 322 | digitbuf[i] = nc; 323 | i++; 324 | } 325 | } else if (c == '#') { // preprocessor 326 | char* prename = read_ident(); 327 | preprocessor(tokenss, prename); 328 | } else if (c == '"') { // string literal 329 | vector_push(tokenss, new_strlit(read_strlit())); 330 | } else if (c == '\'') { 331 | char nc = getc(input); 332 | if (nc == '\\') { 333 | nc = getc(input); 334 | if (nc == '0') { 335 | nc = '\0'; 336 | } 337 | if (nc == 'n') { 338 | nc = '\n'; 339 | } 340 | } 341 | if (getc(input) != '\'') { 342 | error("expect end of char literal."); 343 | } 344 | vector_push(tokenss, new_intlit(nc)); 345 | } else if (c == '+') { 346 | char nc = getc(input); 347 | if (nc == '+') { 348 | vector_push(tokenss, new_token(TOKEN_INC)); 349 | } else if (nc == '=') { 350 | vector_push(tokenss, new_token(TOKEN_ADDASSIGN)); 351 | } else { 352 | ungetc(nc, input); 353 | vector_push(tokenss, new_token(TOKEN_ADD)); 354 | } 355 | } else if (c == '-') { 356 | char nc = getc(input); 357 | if (nc == '>') { 358 | vector_push(tokenss, new_token(TOKEN_ALLOW)); 359 | } else { 360 | ungetc(nc, input); 361 | vector_push(tokenss, new_token(TOKEN_SUB)); 362 | } 363 | } else if (c == '*') { 364 | char nc = getc(input); 365 | if (nc == '=') { 366 | vector_push(tokenss, new_token(TOKEN_MULASSIGN)); 367 | } else { 368 | ungetc(nc, input); 369 | vector_push(tokenss, new_token(TOKEN_MUL)); 370 | } 371 | } else if (c == '/') { 372 | char nc = getc(input); 373 | if (nc == '/') { 374 | while (true) { 375 | nc = getc(input); 376 | if (nc == EOF || nc == '\n') break; 377 | } 378 | } else if (nc == '*') { 379 | bool inasterisk = false; 380 | while (true) { 381 | nc = getc(input); 382 | if (inasterisk && nc == '/') { 383 | break; 384 | } 385 | if (nc == '*') { 386 | inasterisk = true; 387 | continue; 388 | } 389 | if (nc == EOF) break; 390 | inasterisk = false; 391 | } 392 | } else { 393 | ungetc(nc, input); 394 | vector_push(tokenss, new_token(TOKEN_DIV)); 395 | } 396 | } else if (c == '%') { 397 | vector_push(tokenss, new_token(TOKEN_MOD)); 398 | } else if (c == '<') { 399 | char nc = getc(input); 400 | if (nc == '=') { 401 | vector_push(tokenss, new_token(TOKEN_LESSEREQ)); 402 | } else { 403 | ungetc(nc, input); 404 | vector_push(tokenss, new_token(TOKEN_LESSER)); 405 | } 406 | } else if (c == '>') { 407 | char nc = getc(input); 408 | if (nc == '=') { 409 | vector_push(tokenss, new_token(TOKEN_GREATEREQ)); 410 | } else { 411 | ungetc(nc, input); 412 | vector_push(tokenss, new_token(TOKEN_GREATER)); 413 | } 414 | } else if (c == '.') { 415 | vector_push(tokenss, new_token(TOKEN_DOT)); 416 | } else if (c == '|') { 417 | char nc = getc(input); 418 | if (nc == '|') { 419 | vector_push(tokenss, new_token(TOKEN_LOR)); 420 | } else { 421 | error("unsupported | token in currently."); 422 | } 423 | } else if (c == '&') { 424 | char nc = getc(input); 425 | if (nc == '&') { 426 | vector_push(tokenss, new_token(TOKEN_LAND)); 427 | } else { 428 | ungetc(nc, input); 429 | vector_push(tokenss, new_token(TOKEN_AND)); 430 | } 431 | } else if (c == '=') { 432 | char nc = getc(input); 433 | if (nc == '=') { 434 | vector_push(tokenss, new_token(TOKEN_EQ)); 435 | } else { 436 | ungetc(nc, input); 437 | vector_push(tokenss, new_token(TOKEN_ASSIGN)); 438 | } 439 | } else if (c == '!') { 440 | char nc = getc(input); 441 | if (nc == '=') { 442 | vector_push(tokenss, new_token(TOKEN_NOTEQ)); 443 | } else { 444 | ungetc(nc, input); 445 | vector_push(tokenss, new_token(TOKEN_NOT)); 446 | } 447 | } else if (c == '(') { 448 | vector_push(tokenss, new_token(TOKEN_LPAREN)); 449 | } else if (c == ')') { 450 | vector_push(tokenss, new_token(TOKEN_RPAREN)); 451 | } else if (c == '[') { 452 | vector_push(tokenss, new_token(TOKEN_LBRACKET)); 453 | } else if (c == ']') { 454 | vector_push(tokenss, new_token(TOKEN_RBRACKET)); 455 | } else if (c == '{') { 456 | vector_push(tokenss, new_token(TOKEN_LBRACE)); 457 | } else if (c == '}') { 458 | vector_push(tokenss, new_token(TOKEN_RBRACE)); 459 | } else if (c == ',') { 460 | vector_push(tokenss, new_token(TOKEN_COMMA)); 461 | } else if (c == ';') { 462 | vector_push(tokenss, new_token(TOKEN_SEMICOLON)); 463 | } else if (c == ' ') { 464 | return true; 465 | } else if (c == '\n') { 466 | return true; 467 | } else if (isident(c)) { 468 | ungetc(c, input); 469 | char* id = read_ident(); 470 | vector* definetokens = map_get(definemap, id); 471 | if (definetokens != NULL) { 472 | for (int i=0; ilen; i++) { 473 | vector_push(tokenss, vector_get(definetokens, i)); 474 | } 475 | } else { 476 | vector_push(tokenss, new_ident(id)); 477 | } 478 | } else { 479 | fprintf(stderr, "%d", c); 480 | fprintf(stderr, "unexpected token '%c'\n", c); 481 | exit(1); 482 | } 483 | return true; 484 | } 485 | 486 | vector* lexer() { 487 | vector* tokenss = new_vector(); 488 | 489 | while (true) { 490 | bool cont = single_token_lexer(tokenss); 491 | if (!cont) break; 492 | } 493 | return tokenss; 494 | } 495 | -------------------------------------------------------------------------------- /codegen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "sncc.h" 4 | 5 | char* breaklabel; 6 | char* contlabel; 7 | 8 | void emit_asm_int(char* fmt, int x) { 9 | printf(" "); 10 | printf(fmt, x); 11 | printf("\n"); 12 | } 13 | void emit_asm1_int(char* fmt, char* s, int x) { 14 | printf(" "); 15 | printf(fmt, s, x); 16 | printf("\n"); 17 | } 18 | void emit_asm(char* fmt) { 19 | printf(" "); 20 | printf(fmt); 21 | printf("\n"); 22 | } 23 | void emit_asm1(char* fmt, char* s) { 24 | printf(" "); 25 | printf(fmt, s); 26 | printf("\n"); 27 | } 28 | void emit_asm2(char* fmt, char* a, char* b) { 29 | printf(" "); 30 | printf(fmt, a, b); 31 | printf("\n"); 32 | } 33 | 34 | void emit_label(char* label) { 35 | printf("%s:\n", label); 36 | } 37 | 38 | void emit_global(char* name) { 39 | emit_asm1(".global %s", name); 40 | } 41 | 42 | void emit_push_int(int x) { 43 | emit_asm_int("pushq $%d", x); 44 | } 45 | void emit_push(char* s) { 46 | emit_asm1("pushq %s", s); 47 | } 48 | void emit_pop(char* s) { 49 | emit_asm1("popq %s", s); 50 | } 51 | void emit_sub(char* left, char* right) { 52 | emit_asm2("subq %s, %s", left, right); 53 | } 54 | void emit_mul(char* left) { 55 | emit_asm1("imulq %s", left); 56 | } 57 | void emit_div(char* left) { 58 | emit_asm("movq $0, %%rdx"); 59 | emit_asm1("idivq %s", left); 60 | } 61 | void emit_return() { 62 | emit_asm("ret"); 63 | } 64 | void emit_call(char* name) { 65 | emit_asm1("call %s", name); 66 | } 67 | 68 | void emit_prologue(int localsize) { 69 | emit_asm("pushq %%rbp"); 70 | emit_asm("movq %%rsp, %%rbp"); 71 | emit_asm_int("subq $%d, %%rsp", localsize); 72 | } 73 | void emit_epilogue() { 74 | emit_asm("movq %%rbp, %%rsp"); 75 | emit_asm("pop %%rbp"); 76 | } 77 | 78 | void emit_localvarref(int pos) { 79 | emit_asm_int("movq -%d(%%rbp), %%rax", pos); 80 | emit_asm("pushq %%rax"); 81 | } 82 | void emit_localvarset(int pos, char* value) { 83 | emit_asm1_int("movq %s, -%d(%%rbp)", value, pos); 84 | } 85 | 86 | void codegen_lvalue(astree* ast) { 87 | if (ast->kind == AST_IDENT) { 88 | emit_asm_int("leaq -%d(%%rbp), %%rax", ast->offset); 89 | emit_push("%rax"); 90 | } else if (ast->kind == AST_GLOBALREF) { 91 | emit_asm1("leaq %s(%%rip), %%rax", ast->ident); 92 | emit_push("%rax"); 93 | } else if (ast->kind == AST_DEREF) { 94 | codegen(ast->value); 95 | } else if (ast->kind == AST_DOT) { 96 | paramtype* field = get_field(ast->structvalue->typ, ast->fieldname); 97 | codegen_lvalue(ast->structvalue); 98 | emit_pop("%rax"); 99 | emit_asm_int("addq $%d, %%rax", field->offset); 100 | emit_push("%rax"); 101 | } else { 102 | error("value isn't lvalue."); 103 | } 104 | } 105 | 106 | void codegen_movevalue(typenode* typ) { 107 | if (typ->truetype != NULL && typ->truetype->kind == TYPE_ARRAY) { 108 | } else if (typ->kind == TYPE_CHAR) { 109 | emit_pop("%rax"); 110 | emit_asm("movsbl (%%rax), %%eax"); 111 | emit_push("%rax"); 112 | } else if (typ->kind == TYPE_INT || typ->kind == TYPE_UINT) { 113 | emit_pop("%rax"); 114 | emit_asm("movl (%%rax), %%eax"); 115 | emit_push("%rax"); 116 | } else if (typ->kind == TYPE_PTR) { 117 | emit_pop("%rax"); 118 | emit_asm("movq (%%rax), %%rax"); 119 | emit_push("%rax"); 120 | } else { 121 | assert(false); 122 | } 123 | } 124 | 125 | void codegen_movereg(typenode* typ, char* reg8, char* reg32, char* reg64) { 126 | if (typ->kind == TYPE_CHAR) { 127 | emit_asm1("movb %s, (%%rax)", reg8); 128 | } else if (typ->kind == TYPE_INT || typ->kind == TYPE_UINT) { 129 | emit_asm1("movl %s, (%%rax)", reg32); 130 | } else if (typ->kind == TYPE_PTR) { 131 | emit_asm1("movq %s, (%%rax)", reg64); 132 | } else { 133 | assert(false); 134 | } 135 | } 136 | 137 | void codegen_add(typenode* typ, typenode* right) { 138 | if (typ->kind == TYPE_PTR && right->kind == TYPE_INT) { // pointer arithmetic 139 | emit_pop("%rax"); 140 | emit_asm_int("movq $%d, %%rcx", typesize(typ->ptrof)); 141 | emit_asm("imulq %%rcx"); 142 | emit_push("%rax"); 143 | } 144 | 145 | emit_pop("%rcx"); 146 | emit_pop("%rax"); 147 | emit_asm("addq %rcx, %rax"); 148 | emit_push("%rax"); 149 | } 150 | 151 | void codegen(astree* ast) { 152 | if (ast->kind == AST_IDENT) { 153 | codegen_lvalue(ast); 154 | codegen_movevalue(ast->typ); 155 | } else if (ast->kind == AST_GLOBALREF) { 156 | codegen_lvalue(ast); 157 | codegen_movevalue(ast->typ); 158 | } else if (ast->kind == AST_INTLIT) { 159 | emit_push_int(ast->intval); 160 | } else if (ast->kind == AST_ADD) { 161 | codegen(ast->left); 162 | codegen(ast->right); 163 | codegen_add(ast->left->typ, ast->right->typ); 164 | } else if (ast->kind == AST_SUB) { 165 | codegen(ast->left); 166 | codegen(ast->right); 167 | assert(ast->left->typ != NULL); 168 | if (ast->left->typ->kind == TYPE_PTR && ast->right->typ->kind == TYPE_INT) { // pointer arithmetic 169 | emit_pop("%rax"); 170 | emit_asm_int("movq $%d, %%rcx", typesize(ast->left->typ->ptrof)); 171 | emit_asm("imulq %%rcx"); 172 | emit_push("%rax"); 173 | } 174 | emit_pop("%rcx"); 175 | emit_pop("%rax"); 176 | emit_sub("%rcx", "%rax"); 177 | emit_push("%rax"); 178 | } else if (ast->kind == AST_MUL) { 179 | codegen(ast->left); 180 | codegen(ast->right); 181 | emit_pop("%rcx"); 182 | emit_pop("%rax"); 183 | emit_mul("%rcx"); 184 | emit_push("%rax"); 185 | } else if (ast->kind == AST_DIV) { 186 | codegen(ast->left); 187 | codegen(ast->right); 188 | emit_pop("%rcx"); 189 | emit_pop("%rax"); 190 | emit_div("%rcx"); 191 | emit_push("%rax"); 192 | } else if (ast->kind == AST_MOD) { 193 | codegen(ast->left); 194 | codegen(ast->right); 195 | emit_pop("%rcx"); 196 | emit_pop("%rax"); 197 | emit_div("%rcx"); 198 | emit_push("%rdx"); 199 | } else if (ast->kind == AST_LESSER) { 200 | codegen(ast->left); 201 | codegen(ast->right); 202 | emit_pop("%rcx"); 203 | emit_pop("%rax"); 204 | emit_asm("cmpq %%rcx, %%rax"); 205 | emit_asm("setl %%al"); 206 | emit_asm("movzbl %%al, %%eax"); 207 | emit_push("%rax"); 208 | } else if (ast->kind == AST_LESSEREQ) { 209 | codegen(ast->left); 210 | codegen(ast->right); 211 | emit_pop("%rcx"); 212 | emit_pop("%rax"); 213 | emit_asm("cmpq %%rcx, %%rax"); 214 | emit_asm("setle %%al"); 215 | emit_asm("movzbl %%al, %%eax"); 216 | emit_push("%rax"); 217 | } else if (ast->kind == AST_EQ) { 218 | codegen(ast->left); 219 | codegen(ast->right); 220 | emit_pop("%rcx"); 221 | emit_pop("%rax"); 222 | emit_asm("cmpq %%rcx, %%rax"); 223 | emit_asm("sete %%al"); 224 | emit_asm("movzbl %%al, %%eax"); 225 | emit_push("%rax"); 226 | } else if (ast->kind == AST_LAND) { 227 | char* falsel = gen_label(); 228 | char* endl = gen_label(); 229 | codegen(ast->left); 230 | emit_pop("%rax"); 231 | emit_asm("cmpq $0, %%rax"); 232 | emit_asm1("je %s", falsel); 233 | codegen(ast->right); 234 | emit_pop("%rax"); 235 | emit_asm("cmpq $0, %%rax"); 236 | emit_asm("setne %%al"); 237 | emit_push("%rax"); 238 | emit_asm1("jmp %s", endl); 239 | emit_label(falsel); 240 | emit_push("$0"); 241 | emit_label(endl); 242 | } else if (ast->kind == AST_BAND) { 243 | codegen(ast->left); 244 | codegen(ast->right); 245 | emit_pop("%rcx"); 246 | emit_pop("%rax"); 247 | emit_asm("andq %rcx, %rax"); 248 | emit_push("%rax"); 249 | } else if (ast->kind == AST_LOR) { 250 | char* truel = gen_label(); 251 | char* endl = gen_label(); 252 | codegen(ast->left); 253 | emit_pop("%rax"); 254 | emit_asm("cmpq $0, %%rax"); 255 | emit_asm1("jne %s", truel); 256 | codegen(ast->right); 257 | emit_pop("%rax"); 258 | emit_asm("cmpq $0, %%rax"); 259 | emit_asm("setne %%al"); 260 | emit_push("%rax"); 261 | emit_asm1("jmp %s", endl); 262 | emit_label(truel); 263 | emit_push("$1"); 264 | emit_label(endl); 265 | } else if (ast->kind == AST_MINUS) { 266 | codegen(ast->value); 267 | emit_pop("%rax"); 268 | emit_asm("negq %%rax"); 269 | emit_push("%rax"); 270 | } else if (ast->kind == AST_DOT) { 271 | codegen_lvalue(ast); 272 | codegen_movevalue(ast->typ); 273 | } else if (ast->kind == AST_ASSIGN) { 274 | codegen_lvalue(ast->left); 275 | codegen(ast->right); 276 | emit_pop("%rcx"); 277 | emit_pop("%rax"); 278 | codegen_movereg(ast->left->typ, "%cl", "%ecx", "%rcx"); 279 | } else if (ast->kind == AST_ADDASSIGN) { 280 | codegen_lvalue(ast->left); 281 | emit_pop("%rax"); 282 | emit_push("%rax"); 283 | emit_push("%rax"); 284 | codegen_movevalue(ast->left->typ); 285 | codegen(ast->right); 286 | codegen_add(ast->left->typ, ast->right->typ); 287 | emit_pop("%rcx"); 288 | emit_pop("%rax"); 289 | codegen_movereg(ast->left->typ, "%cl", "%ecx", "%rcx"); 290 | emit_push("%rcx"); 291 | } else if (ast->kind == AST_MULASSIGN) { 292 | codegen_lvalue(ast->left); 293 | emit_pop("%rax"); 294 | emit_push("%rax"); 295 | emit_push("%rax"); 296 | codegen_movevalue(ast->left->typ); 297 | codegen(ast->right); 298 | emit_pop("%rcx"); 299 | emit_pop("%rax"); 300 | emit_asm("imulq %%rcx"); 301 | emit_push("%rax"); 302 | emit_pop("%rcx"); 303 | emit_pop("%rax"); 304 | codegen_movereg(ast->left->typ, "%cl", "%ecx", "%rcx"); 305 | emit_push("%rcx"); 306 | } else if (ast->kind == AST_PREINC) { 307 | codegen_lvalue(ast->value); 308 | emit_pop("%rax"); 309 | emit_push("%rax"); 310 | emit_push("%rax"); 311 | codegen_movevalue(ast->value->typ); 312 | emit_push("$1"); 313 | codegen_add(ast->value->typ, new_typenode(TYPE_INT)); 314 | emit_pop("%rcx"); 315 | emit_pop("%rax"); 316 | codegen_movereg(ast->value->typ, "%cl", "%ecx", "%rcx"); 317 | emit_push("%rcx"); 318 | } else if (ast->kind == AST_ADDR) { 319 | codegen_lvalue(ast->value); 320 | } else if (ast->kind == AST_DEREF) { 321 | codegen(ast->value); 322 | codegen_movevalue(ast->typ); 323 | } else if (ast->kind == AST_VARDECL) { 324 | // discard 325 | } else if (ast->kind == AST_CALL && ast->call->kind == AST_IDENT) { 326 | emit_push("%rdi"); 327 | emit_push("%rsi"); 328 | emit_push("%rdx"); 329 | emit_push("%rcx"); 330 | emit_push("%r8"); 331 | emit_push("%r9"); 332 | 333 | if (ast->arguments->len > 0) { 334 | codegen(vector_get(ast->arguments, 0)); 335 | emit_pop("%rax"); 336 | emit_asm("movq %%rax, %%rdi"); 337 | } 338 | if (ast->arguments->len > 1) { 339 | codegen(vector_get(ast->arguments, 1)); 340 | emit_pop("%rax"); 341 | emit_asm("movq %%rax, %%rsi"); 342 | } 343 | if (ast->arguments->len > 2) { 344 | codegen(vector_get(ast->arguments, 2)); 345 | emit_pop("%rax"); 346 | emit_asm("movq %%rax, %%rdx"); 347 | } 348 | if (ast->arguments->len > 3) { 349 | codegen(vector_get(ast->arguments, 3)); 350 | emit_pop("%rax"); 351 | emit_asm("movq %%rax, %%rcx"); 352 | } 353 | if (ast->arguments->len > 4) { 354 | codegen(vector_get(ast->arguments, 4)); 355 | emit_pop("%rax"); 356 | emit_asm("movq %%rax, %%r8"); 357 | } 358 | if (ast->arguments->len > 5) { 359 | codegen(vector_get(ast->arguments, 5)); 360 | emit_pop("%rax"); 361 | emit_asm("movq %%rax, %%r9"); 362 | } 363 | 364 | if (ast->arguments->len-6 >= 1) { 365 | emit_asm_int("subq $%d, %%rsp", (ast->arguments->len-6)*8); 366 | } 367 | for (int i=6; iarguments->len; i++) { 368 | codegen(vector_get(ast->arguments, i)); 369 | emit_pop("%rax"); 370 | emit_asm_int("movq %%rax, %d(%%rsp)", (i-6)*8); 371 | } 372 | emit_asm("movq $0, %%rax"); 373 | emit_call(ast->call->ident); 374 | if (ast->arguments->len-6 >= 1) { 375 | emit_asm_int("addq $%d, %%rsp", (ast->arguments->len-6)*8); 376 | } 377 | 378 | emit_pop("%r9"); 379 | emit_pop("%r8"); 380 | emit_pop("%rcx"); 381 | emit_pop("%rdx"); 382 | emit_pop("%rsi"); 383 | emit_pop("%rdi"); 384 | 385 | emit_push("%rax"); 386 | } else if (ast->kind == AST_STATEMENTS) { 387 | for (int i=0; istmts->len; i++) { 388 | astree* e = vector_get(ast->stmts, i); 389 | codegen(e); 390 | } 391 | } else if (ast->kind == AST_RETURN) { 392 | if (ast->value != NULL){ 393 | codegen(ast->value); 394 | emit_pop("%rax"); 395 | } 396 | emit_epilogue(); 397 | emit_asm("ret"); 398 | } else if (ast->kind == AST_IF) { 399 | codegen(ast->ifcond); 400 | char* endl = gen_label(); 401 | char* nextl = gen_label(); 402 | emit_asm("pop %%rax"); 403 | emit_asm("cmpq $0, %%rax"); 404 | emit_asm1("je %s", nextl); 405 | codegen(ast->ifbody); 406 | emit_asm1("jmp %s", endl); 407 | for (int i=0; ielifconds->len; i++) { 408 | astree* cond = vector_get(ast->elifconds, i); 409 | astree* body = vector_get(ast->elifbodies, i); 410 | emit_label(nextl); 411 | codegen(cond); 412 | emit_asm("pop %%rax"); 413 | emit_asm("cmpq $0, %%rax"); 414 | nextl = gen_label(); 415 | emit_asm1("je %s", nextl); 416 | codegen(body); 417 | emit_asm1("jmp %s", endl); 418 | } 419 | emit_label(nextl); 420 | if (ast->elsebody != NULL) { 421 | codegen(ast->elsebody); 422 | } 423 | emit_label(endl); 424 | } else if (ast->kind == AST_WHILE) { 425 | char* startl = gen_label(); 426 | char* endl = gen_label(); 427 | char* prevcont = contlabel; 428 | char* prevbreak = breaklabel; 429 | contlabel = startl; 430 | breaklabel = endl; 431 | emit_label(startl); 432 | codegen(ast->whilecond); 433 | emit_asm("pop %%rax"); 434 | emit_asm("cmpq $0, %%rax"); 435 | emit_asm1("je %s", endl); 436 | codegen(ast->whilebody); 437 | emit_asm1("jmp %s", startl); 438 | emit_label(endl); 439 | contlabel = prevcont; 440 | breaklabel = prevbreak; 441 | } else if (ast->kind == AST_FOR) { 442 | char* startl = gen_label(); 443 | char* nextl = gen_label(); 444 | char* endl = gen_label(); 445 | char* prevcont = contlabel; 446 | char* prevbreak = breaklabel; 447 | contlabel = nextl; 448 | breaklabel = endl; 449 | codegen(ast->forinit); 450 | emit_label(startl); 451 | codegen(ast->forcond); 452 | emit_asm("pop %%rax"); 453 | emit_asm("cmpq $0, %%rax"); 454 | emit_asm1("je %s", endl); 455 | codegen(ast->forbody); 456 | emit_label(nextl); 457 | codegen(ast->fornext); 458 | emit_asm1("jmp %s", startl); 459 | emit_label(endl); 460 | contlabel = prevcont; 461 | breaklabel = prevbreak; 462 | } else if (ast->kind == AST_BREAK) { 463 | emit_asm1("jmp %s", breaklabel); 464 | } else if (ast->kind == AST_CONTINUE) { 465 | emit_asm1("jmp %s", contlabel); 466 | } else { 467 | error("unsupported kind in codegen"); 468 | } 469 | } 470 | 471 | void codegen_funcdecl(toplevel* fdecl) { 472 | if (fdecl->body == NULL) return; 473 | breaklabel = NULL; 474 | contlabel = NULL; 475 | 476 | emit_global(fdecl->fdecl->name); 477 | emit_label(fdecl->fdecl->name); 478 | emit_prologue(fdecl->stacksize); 479 | int argpos = 0; 480 | for (int i=0; iargdecls->len; i++) { 481 | paramtype* argparam = vector_get(fdecl->argdecls, i); 482 | int offset = argparam->offset; 483 | emit_asm_int("leaq -%d(%%rbp), %%rax", offset); 484 | if (i == 0) { 485 | codegen_movereg(argparam->typ, "%dil", "%edi", "%rdi"); 486 | } else if (i == 1) { 487 | codegen_movereg(argparam->typ, "%sil", "%esi", "%rsi"); 488 | } else if (i == 2) { 489 | codegen_movereg(argparam->typ, "%dl", "%edx", "%rdx"); 490 | } else if (i == 3) { 491 | codegen_movereg(argparam->typ, "%cl", "%ecx", "%rcx"); 492 | } else if (i == 4) { 493 | codegen_movereg(argparam->typ, "%r8b", "%r8d", "%r8"); 494 | } else if (i == 5) { 495 | codegen_movereg(argparam->typ, "%r9b", "%r9d", "%r9"); 496 | } else { 497 | argpos += 8; 498 | emit_asm_int("movq -%d(%%rbp), %%rcx", argpos); 499 | codegen_movereg(argparam->typ, "%cl", "%ecx", "%rcx"); 500 | } 501 | } 502 | for (int i=0; ibody->len; i++) { 503 | codegen(vector_get(fdecl->body, i)); 504 | } 505 | emit_epilogue(fdecl->stacksize); 506 | emit_return(); 507 | } 508 | 509 | void codegen_strlits() { 510 | printf(".data\n"); 511 | for (int i=0; ilen; i++) { 512 | strlitinfo* info = vector_get(strlits, i); 513 | emit_label(info->label); 514 | emit_asm1(".ascii \"%s\\0\"", info->strval); 515 | } 516 | } 517 | 518 | void codegen_toplevel(toplevel* top) { 519 | if (top->kind == TOP_NONE) { 520 | // discard 521 | } else if (top->kind == TOP_FUNCDECL) { 522 | printf(".text\n"); 523 | codegen_funcdecl(top); 524 | } else if (top->kind == TOP_EXTERN) { 525 | printf(".data\n"); 526 | emit_global(top->vdecl->name); 527 | } else if (top->kind == TOP_GLOBALVAR) { 528 | printf(".data\n"); 529 | emit_global(top->vdecl->name); 530 | emit_label(top->vdecl->name); 531 | if (top->vinit != NULL) { 532 | if (top->vinit->kind == AST_INTLIT) { 533 | emit_asm_int(".int %d", top->vinit->intval); 534 | } else if (top->vinit->kind == AST_MINUS) { 535 | emit_asm_int(".int -%d", top->vinit->value->intval); 536 | } else if (top->vinit->kind == AST_STRLIT) { 537 | emit_asm1(".ascii \"%s\\0\"", top->vinit->strval); 538 | } 539 | } else { 540 | emit_asm_int(".zero %d", typesize(top->vdecl->typ)); 541 | } 542 | } else if (top->kind == TOP_STRUCT) { 543 | // discard 544 | } else { 545 | assert(false); 546 | } 547 | } 548 | 549 | -------------------------------------------------------------------------------- /parser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "sncc.h" 5 | 6 | map* structmap; 7 | map* enummap; 8 | map* typedefmap; 9 | map* constmap; 10 | 11 | void init_parser() { 12 | structmap = new_map(); 13 | enummap = new_map(); 14 | typedefmap = new_map(); 15 | constmap = new_map(); 16 | } 17 | 18 | bool eq_ident(token* id, char* s) { 19 | return id != NULL && id->kind == TOKEN_IDENT && strcmp(id->ident, s) == 0; 20 | } 21 | 22 | void expect_token(token* t, tokenkind kind) { 23 | if (t == NULL || t->kind != kind) error("unexpected token."); 24 | } 25 | 26 | // 27 | // ast 28 | // 29 | 30 | astree* new_ast(astkind kind) { 31 | astree* ast = malloc(sizeof(struct _astree)); 32 | ast->kind = kind; 33 | ast->typ = NULL; 34 | return ast; 35 | } 36 | 37 | astree* new_ast_prefix(astkind kind, astree* value) { 38 | astree* ast = new_ast(kind); 39 | ast->value = value; 40 | return ast; 41 | } 42 | 43 | astree* new_ast_infix(astkind kind, astree* left, astree* right) { 44 | astree* ast = new_ast(kind); 45 | ast->left = left; 46 | ast->right = right; 47 | return ast; 48 | } 49 | 50 | astree* new_ast_intlit(int x) { 51 | astree* ast = new_ast(AST_INTLIT); 52 | ast->intval = x; 53 | return ast; 54 | } 55 | 56 | astree* new_ast_strlit(char* s) { 57 | astree* ast = new_ast(AST_STRLIT); 58 | ast->strval = s; 59 | return ast; 60 | } 61 | 62 | astree* new_ast_ident(char* id) { 63 | astree* ast = new_ast(AST_IDENT); 64 | ast->ident = id; 65 | return ast; 66 | } 67 | 68 | char* ast_to_kindstr(astree* ast) { 69 | if (ast->kind == AST_ADD) { 70 | return "AST_ADD"; 71 | } else if (ast->kind == AST_SUB) { 72 | return "AST_SUB"; 73 | } else if (ast->kind == AST_MUL) { 74 | return "AST_MUL"; 75 | } else if (ast->kind == AST_DIV) { 76 | return "AST_DIV"; 77 | } else if (ast->kind == AST_MINUS) { 78 | return "AST_MINUS"; 79 | } else if (ast->kind == AST_LESSER) { 80 | return "AST_LESSER"; 81 | } else if (ast->kind == AST_LESSEREQ) { 82 | return "AST_LESSEREQ"; 83 | } else if (ast->kind == AST_ASSIGN) { 84 | return "AST_ASSIGN"; 85 | } else if (ast->kind == AST_PREINC) { 86 | return "AST_PREINC"; 87 | } else if (ast->kind == AST_POSTINC) { 88 | return "AST_POSTINC"; 89 | } else if (ast->kind == AST_EQ) { 90 | return "AST_EQ"; 91 | } else if (ast->kind == AST_SIZEOF_EXPR) { 92 | return "AST_SIZEOF_EXPR"; 93 | } else if (ast->kind == AST_SIZEOF_TYPE) { 94 | return "AST_SIZEOF_TYPE"; 95 | } else if (ast->kind == AST_DOT) { 96 | return "AST_DOT"; 97 | } else if (ast->kind == AST_ADDR) { 98 | return "AST_ADDR"; 99 | } else if (ast->kind == AST_DEREF) { 100 | return "AST_DEREF"; 101 | } else if (ast->kind == AST_VARDECL) { 102 | return "AST_VARDECL"; 103 | } else if (ast->kind == AST_CALL) { 104 | return "AST_CALL"; 105 | } else if (ast->kind == AST_STATEMENTS) { 106 | return "AST_STATEMENTS"; 107 | } else if (ast->kind == AST_INTLIT) { 108 | return "AST_INTLIT"; 109 | } else if (ast->kind == AST_STRLIT) { 110 | return "AST_STRLIT"; 111 | } else if (ast->kind == AST_IDENT) { 112 | return "AST_IDENT"; 113 | } else if (ast->kind == AST_RETURN) { 114 | return "AST_RETURN"; 115 | } else if (ast->kind == AST_IF) { 116 | return "AST_IF"; 117 | } else if (ast->kind == AST_WHILE) { 118 | return "AST_WHILE"; 119 | } else if (ast->kind == AST_FOR) { 120 | return "AST_FOR"; 121 | } else if (ast->kind == AST_BREAK) { 122 | return "AST_BREAK"; 123 | } else if (ast->kind == AST_CONTINUE) { 124 | return "AST_CONTINUE"; 125 | } else { 126 | assert(0); 127 | } 128 | } 129 | 130 | // 131 | // typenode 132 | // 133 | 134 | typenode* new_typenode(typekind kind) { 135 | typenode* tn = malloc(sizeof(struct _typenode)); 136 | tn->kind = kind; 137 | tn->ptrof = NULL; 138 | tn->truetype = NULL; 139 | return tn; 140 | } 141 | 142 | typenode* new_ptrnode(typenode* typ) { 143 | typenode* tn = new_typenode(TYPE_PTR); 144 | tn->ptrof = typ; 145 | return tn; 146 | } 147 | 148 | typenode* new_arraynode(typenode* typ, int size) { 149 | typenode* tn = new_typenode(TYPE_PTR); 150 | tn->ptrof = typ; 151 | tn->truetype = new_typenode(TYPE_ARRAY); 152 | tn->truetype->ptrof = typ; 153 | tn->truetype->arraysize = size; 154 | return tn; 155 | } 156 | 157 | // 158 | // tokenstream 159 | // 160 | 161 | tokenstream* new_tokenstream(vector* tokens) { 162 | tokenstream* ts = malloc(sizeof(struct _tokenstream)); 163 | ts->tokens = tokens; 164 | ts->pos = 0; 165 | return ts; 166 | } 167 | token* get_token(tokenstream* ts) { 168 | if (ts->pos >= ts->tokens->len) { 169 | return NULL; 170 | } 171 | return vector_get(ts->tokens, ts->pos); 172 | } 173 | void next_token(tokenstream* ts) { 174 | ts->pos++; 175 | } 176 | 177 | // 178 | // parser 179 | // 180 | 181 | typenode* parse_pointer(tokenstream* ts, typenode* basetype) { 182 | typenode* tn = basetype; 183 | while (true) { 184 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_MUL) { 185 | next_token(ts); 186 | tn = new_ptrnode(tn); 187 | } else { 188 | break; 189 | } 190 | } 191 | return tn; 192 | } 193 | 194 | typenode* parse_arraydecl(tokenstream* ts, typenode* basetype) { 195 | typenode* tn = basetype; 196 | while (true) { 197 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_LBRACKET) break; 198 | next_token(ts); 199 | expect_token(get_token(ts), TOKEN_INTLIT); 200 | int arraysize = get_token(ts)->intval; next_token(ts); 201 | tn = new_arraynode(tn, arraysize); // FIXME: 202 | expect_token(get_token(ts), TOKEN_RBRACKET); next_token(ts); 203 | } 204 | return tn; 205 | } 206 | 207 | vector* parse_struct_body(tokenstream* ts) { 208 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_LBRACE) return NULL; 209 | next_token(ts); 210 | vector* fields = new_vector(); 211 | while (true) { 212 | paramtype* field = parse_paramtype(ts); 213 | if (field == NULL) break; 214 | vector_push(fields, field); 215 | expect_token(get_token(ts), TOKEN_SEMICOLON); next_token(ts); 216 | } 217 | expect_token(get_token(ts), TOKEN_RBRACE); next_token(ts); 218 | return fields; 219 | } 220 | 221 | typenode* parse_typespec(tokenstream* ts) { 222 | typenode* tn; 223 | if (eq_ident(get_token(ts), "int")) { 224 | next_token(ts); 225 | tn = new_typenode(TYPE_INT); 226 | } else if (eq_ident(get_token(ts), "unsigned")) { 227 | next_token(ts); 228 | if (eq_ident(get_token(ts), "int")) next_token(ts); 229 | tn = new_typenode(TYPE_UINT); 230 | } else if (eq_ident(get_token(ts), "char")) { 231 | next_token(ts); 232 | tn = new_typenode(TYPE_CHAR); 233 | } else if (eq_ident(get_token(ts), "void")) { 234 | next_token(ts); 235 | tn = new_typenode(TYPE_VOID); 236 | } else if (eq_ident(get_token(ts), "struct")) { 237 | next_token(ts); 238 | tn = new_typenode(TYPE_STRUCT); 239 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_IDENT) { 240 | tn->tname = get_token(ts)->ident; next_token(ts); 241 | } else { 242 | tn->tname = NULL; 243 | } 244 | char* tname = tn->tname; 245 | tn->fields = parse_struct_body(ts); 246 | if (tn->fields == NULL) { 247 | tn = map_get(structmap, tn->tname); 248 | if (tn == NULL) { 249 | tn = new_typenode(TYPE_INCOMPLETE_STRUCT); 250 | tn->tname = tname; 251 | map_insert(structmap, tname, tn); 252 | } 253 | } 254 | } else if (eq_ident(get_token(ts), "enum")) { 255 | next_token(ts); 256 | expect_token(get_token(ts), TOKEN_IDENT); 257 | // char* tname = get_token(ts)->ident; next_token(ts); 258 | next_token(ts); 259 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_LBRACE) { 260 | tn = new_typenode(TYPE_INT); 261 | } else { 262 | tn = new_typenode(TYPE_INT); 263 | expect_token(get_token(ts), TOKEN_LBRACE); next_token(ts); 264 | int i = 0; 265 | while (true) { 266 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_IDENT) break; 267 | char* constname = get_token(ts)->ident; next_token(ts); 268 | int* constint = malloc(sizeof(int)); 269 | *constint = i; 270 | map_insert(constmap, constname, constint); 271 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_COMMA) next_token(ts); 272 | i++; 273 | } 274 | expect_token(get_token(ts), TOKEN_RBRACE); next_token(ts); 275 | } 276 | } else { 277 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_IDENT) return NULL; 278 | char* tname = get_token(ts)->ident; 279 | typenode* searched = map_get(typedefmap, tname); 280 | if (searched == NULL) return NULL; 281 | next_token(ts); 282 | tn = searched; 283 | } 284 | return tn; 285 | } 286 | 287 | typenode* parse_typeexpr(tokenstream* ts) { 288 | return parse_pointer(ts, parse_typespec(ts)); 289 | } 290 | 291 | astree* gen_ptrderef(astree* value, astree* index) { 292 | return new_ast_prefix(AST_DEREF, new_ast_infix(AST_ADD, value, index)); 293 | } 294 | 295 | astree* factor(tokenstream* ts) { 296 | token* t = get_token(ts); 297 | if (t == NULL) error("require more token"); 298 | 299 | if (t->kind == TOKEN_LPAREN) { 300 | next_token(ts); 301 | astree* ret = expression(ts); 302 | token* newt = get_token(ts); 303 | if (newt == NULL || newt->kind != TOKEN_RPAREN) error("\"(\" should be ended by \")\"."); 304 | next_token(ts); 305 | return ret; 306 | } else if (t->kind == TOKEN_INTLIT) { 307 | next_token(ts); 308 | return new_ast_intlit(t->intval); 309 | } else if (t->kind == TOKEN_STRLIT) { 310 | next_token(ts); 311 | return new_ast_strlit(t->strval); 312 | } else if (t->kind == TOKEN_IDENT) { 313 | next_token(ts); 314 | int* constint = map_get(constmap, t->ident); 315 | if (constint == NULL) { 316 | return new_ast_ident(t->ident); 317 | } else { 318 | return new_ast_intlit(*constint); 319 | } 320 | } else { 321 | return expression(ts); 322 | } 323 | } 324 | 325 | astree* callexpr(tokenstream* ts) { 326 | astree* call = factor(ts); 327 | token* lparen = get_token(ts); 328 | if (lparen == NULL) return call; 329 | if (lparen->kind != TOKEN_LPAREN) return call; 330 | next_token(ts); 331 | 332 | vector* args = new_vector(); 333 | if (get_token(ts)-> kind != TOKEN_RPAREN) { 334 | vector_push(args, expression(ts)); 335 | while (true) { 336 | if (get_token(ts)->kind == TOKEN_RPAREN) break; 337 | token* t = get_token(ts); next_token(ts); 338 | if (t->kind != TOKEN_COMMA) error("expected comma by call"); 339 | vector_push(args, expression(ts)); 340 | } 341 | } 342 | 343 | token* rparen = get_token(ts); next_token(ts); 344 | if (rparen == NULL || rparen->kind != TOKEN_RPAREN) error("function call expected )rparen."); 345 | 346 | astree* ast = new_ast(AST_CALL); 347 | ast->call = call; 348 | ast->arguments = args; 349 | return ast; 350 | } 351 | 352 | astree* postfix_op(tokenstream* ts) { 353 | astree* value = callexpr(ts); 354 | while (true) { 355 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_LBRACKET) { 356 | next_token(ts); 357 | astree* index = expression(ts); 358 | value = gen_ptrderef(value, index); 359 | expect_token(get_token(ts), TOKEN_RBRACKET); next_token(ts); 360 | } else if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_INC) { 361 | next_token(ts); 362 | value = new_ast_prefix(AST_POSTINC, value); 363 | } else if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_DOT) { 364 | next_token(ts); 365 | astree* newast = new_ast(AST_DOT); 366 | newast->structvalue = value; 367 | expect_token(get_token(ts), TOKEN_IDENT); 368 | newast->fieldname = get_token(ts)->ident; next_token(ts); 369 | value = newast; 370 | } else if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_ALLOW) { 371 | next_token(ts); 372 | astree* newast = new_ast(AST_DOT); 373 | newast->structvalue = new_ast_prefix(AST_DEREF, value); 374 | expect_token(get_token(ts), TOKEN_IDENT); 375 | newast->fieldname = get_token(ts)->ident; next_token(ts); 376 | value = newast; 377 | } else { 378 | break; 379 | } 380 | } 381 | return value; 382 | } 383 | 384 | astree* prefix_op(tokenstream* ts) { 385 | token* t = get_token(ts); 386 | if (eq_ident(get_token(ts), "sizeof")) { 387 | next_token(ts); 388 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_LPAREN) next_token(ts); 389 | astree* ast; 390 | typenode* typ = parse_typeexpr(ts); 391 | if (typ == NULL) { 392 | ast = new_ast(AST_SIZEOF_EXPR); 393 | ast->value = expression(ts); 394 | } else { 395 | ast = new_ast(AST_SIZEOF_TYPE); 396 | ast->typedesc = typ; 397 | } 398 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_RPAREN) next_token(ts); 399 | return ast; 400 | } else if (t != NULL && t->kind == TOKEN_SUB) { 401 | next_token(ts); 402 | astree* value = prefix_op(ts); 403 | return new_ast_prefix(AST_MINUS, value); 404 | } else if (t != NULL && t->kind == TOKEN_MUL) { 405 | next_token(ts); 406 | astree* value = prefix_op(ts); 407 | return new_ast_prefix(AST_DEREF, value); 408 | } else if (t != NULL && t->kind == TOKEN_INC) { 409 | next_token(ts); 410 | astree* value = prefix_op(ts); 411 | return new_ast_prefix(AST_PREINC, value); 412 | } else if (t != NULL && t->kind == TOKEN_AND) { 413 | next_token(ts); 414 | astree* value = prefix_op(ts); 415 | return new_ast_prefix(AST_ADDR, value); 416 | } else if (t != NULL && t->kind == TOKEN_NOT) { 417 | next_token(ts); 418 | astree* value = prefix_op(ts); 419 | return new_ast_infix(AST_EQ, value, new_ast_intlit(0)); 420 | } else { 421 | return postfix_op(ts); 422 | } 423 | } 424 | 425 | astree* infix_muldiv(tokenstream* ts) { 426 | astree* left = prefix_op(ts); 427 | while (true) { 428 | token* t = get_token(ts); 429 | if (t == NULL) break; 430 | if (t->kind == TOKEN_MUL) { 431 | next_token(ts); 432 | astree* right = prefix_op(ts); 433 | left = new_ast_infix(AST_MUL, left, right); 434 | } else if (t->kind == TOKEN_DIV) { 435 | next_token(ts); 436 | astree* right = prefix_op(ts); 437 | left = new_ast_infix(AST_DIV, left, right); 438 | } else if (t->kind == TOKEN_MOD) { 439 | next_token(ts); 440 | astree* right = prefix_op(ts); 441 | left = new_ast_infix(AST_MOD, left, right); 442 | } else { 443 | break; 444 | } 445 | } 446 | return left; 447 | } 448 | 449 | astree* infix_addsub(tokenstream* ts) { 450 | astree* left = infix_muldiv(ts); 451 | while (true) { 452 | token* t = get_token(ts); 453 | if (t == NULL) break; 454 | if (t->kind == TOKEN_ADD) { 455 | next_token(ts); 456 | astree* right = infix_muldiv(ts); 457 | left = new_ast_infix(AST_ADD, left, right); 458 | } else if (t->kind == TOKEN_SUB) { 459 | next_token(ts); 460 | astree* right = infix_muldiv(ts); 461 | left = new_ast_infix(AST_SUB, left, right); 462 | } else { 463 | break; 464 | } 465 | } 466 | return left; 467 | } 468 | 469 | astree* infix_eq(tokenstream* ts) { 470 | astree* left = infix_addsub(ts); 471 | while (true) { 472 | token* t = get_token(ts); 473 | if (t == NULL) break; 474 | if (t->kind == TOKEN_EQ) { 475 | next_token(ts); 476 | astree* right = infix_addsub(ts); 477 | left = new_ast_infix(AST_EQ, left, right); 478 | } else if (t->kind == TOKEN_NOTEQ) { 479 | next_token(ts); 480 | astree* right = infix_addsub(ts); 481 | left = new_ast_infix(AST_EQ, new_ast_infix(AST_EQ, left, right), new_ast_intlit(0)); 482 | } else { 483 | break; 484 | } 485 | } 486 | return left; 487 | } 488 | 489 | // infix parser for lesser, greater, and lesser/greater equal. 490 | astree* infix_lge(tokenstream* ts) { 491 | astree* left = infix_eq(ts); 492 | while (true) { 493 | token* t = get_token(ts); 494 | if (t == NULL) break; 495 | if (t->kind == TOKEN_LESSER) { 496 | next_token(ts); 497 | astree* right = infix_eq(ts); 498 | left = new_ast_infix(AST_LESSER, left, right); 499 | } else if (t->kind == TOKEN_GREATER) { 500 | next_token(ts); 501 | astree* right = infix_eq(ts); 502 | left = new_ast_infix(AST_LESSER, right, left); 503 | } else if (t->kind == TOKEN_LESSEREQ) { 504 | next_token(ts); 505 | astree* right = infix_eq(ts); 506 | left = new_ast_infix(AST_LESSEREQ, left, right); 507 | } else if (t->kind == TOKEN_GREATEREQ) { 508 | next_token(ts); 509 | astree* right = infix_eq(ts); 510 | left = new_ast_infix(AST_LESSEREQ, right, left); 511 | } else { 512 | break; 513 | } 514 | } 515 | return left; 516 | } 517 | 518 | astree* infix_bit_and(tokenstream* ts) { 519 | astree* left = infix_lge(ts); 520 | while (true) { 521 | token* t = get_token(ts); 522 | if (t == NULL) break; 523 | if (t->kind == TOKEN_AND) { 524 | next_token(ts); 525 | astree* right = infix_lge(ts); 526 | left = new_ast_infix(AST_BAND, left, right); 527 | } else { 528 | break; 529 | } 530 | } 531 | return left; 532 | } 533 | 534 | astree* infix_logic_and(tokenstream* ts) { 535 | astree* left = infix_bit_and(ts); 536 | while (true) { 537 | token* t = get_token(ts); 538 | if (t == NULL) break; 539 | if (t->kind == TOKEN_LAND) { 540 | next_token(ts); 541 | astree* right = infix_lge(ts); 542 | left = new_ast_infix(AST_LAND, left, right); 543 | } else { 544 | break; 545 | } 546 | } 547 | return left; 548 | } 549 | 550 | astree* infix_logic_or(tokenstream* ts) { 551 | astree* left = infix_logic_and(ts); 552 | while (true) { 553 | token* t = get_token(ts); 554 | if (t == NULL) break; 555 | if (t->kind == TOKEN_LOR) { 556 | next_token(ts); 557 | astree* right = infix_logic_and(ts); 558 | left = new_ast_infix(AST_LOR, left, right); 559 | } else { 560 | break; 561 | } 562 | } 563 | return left; 564 | } 565 | 566 | astree* infix_assign(tokenstream* ts) { 567 | astree* left = infix_logic_or(ts); 568 | while (true) { 569 | token* t = get_token(ts); 570 | if (t == NULL) break; 571 | if (t->kind == TOKEN_ASSIGN) { 572 | next_token(ts); 573 | astree* right = expression(ts); 574 | left = new_ast_infix(AST_ASSIGN, left, right); 575 | } else if (t->kind == TOKEN_ADDASSIGN) { 576 | next_token(ts); 577 | astree* right = expression(ts); 578 | left = new_ast_infix(AST_ADDASSIGN, left, right); 579 | } else if (t->kind == TOKEN_MULASSIGN) { 580 | next_token(ts); 581 | astree* right = expression(ts); 582 | left = new_ast_infix(AST_MULASSIGN, left, right); 583 | } else { 584 | break; 585 | } 586 | } 587 | return left; 588 | } 589 | 590 | astree* expression(tokenstream* ts) { 591 | return infix_assign(ts); 592 | } 593 | 594 | astree* parse_return(tokenstream* ts) { 595 | if (!eq_ident(get_token(ts), "return")) return NULL; 596 | next_token(ts); 597 | 598 | astree* ast = new_ast(AST_RETURN); 599 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) { 600 | next_token(ts); 601 | ast->value = NULL; 602 | return ast; 603 | } 604 | ast->value = expression(ts); 605 | expect_token(get_token(ts), TOKEN_SEMICOLON); next_token(ts); 606 | 607 | return ast; 608 | } 609 | 610 | astree* parse_if(tokenstream* ts) { 611 | if (!eq_ident(get_token(ts), "if")) return NULL; 612 | next_token(ts); 613 | 614 | astree* ast = new_ast(AST_IF); 615 | 616 | expect_token(get_token(ts), TOKEN_LPAREN); next_token(ts); 617 | ast->ifcond = expression(ts); 618 | expect_token(get_token(ts), TOKEN_RPAREN); next_token(ts); 619 | ast->ifbody = parse_compound(ts); 620 | 621 | ast->elifconds = new_vector(); 622 | ast->elifbodies = new_vector(); 623 | ast->elsebody = NULL; 624 | while (true) { 625 | if (!eq_ident(get_token(ts), "else")) break; 626 | next_token(ts); 627 | if (eq_ident(get_token(ts), "if")) { 628 | next_token(ts); 629 | expect_token(get_token(ts), TOKEN_LPAREN); next_token(ts); 630 | vector_push(ast->elifconds, expression(ts)); 631 | expect_token(get_token(ts), TOKEN_RPAREN); next_token(ts); 632 | vector_push(ast->elifbodies, parse_compound(ts)); 633 | } else { 634 | ast->elsebody = parse_compound(ts); 635 | } 636 | } 637 | 638 | return ast; 639 | } 640 | 641 | astree* parse_while(tokenstream* ts) { 642 | if (!eq_ident(get_token(ts), "while")) return NULL; 643 | next_token(ts); 644 | 645 | astree* ast = new_ast(AST_WHILE); 646 | 647 | expect_token(get_token(ts), TOKEN_LPAREN); next_token(ts); 648 | ast->whilecond = expression(ts); 649 | expect_token(get_token(ts), TOKEN_RPAREN); next_token(ts); 650 | ast->whilebody = parse_compound(ts); 651 | 652 | return ast; 653 | } 654 | 655 | astree* parse_for(tokenstream* ts) { 656 | if (!eq_ident(get_token(ts), "for")) return NULL; 657 | next_token(ts); 658 | 659 | astree* ast = new_ast(AST_FOR); 660 | 661 | expect_token(get_token(ts), TOKEN_LPAREN); next_token(ts); 662 | ast->forinit = parse_statement(ts); 663 | ast->forcond = parse_statement(ts); 664 | ast->fornext = parse_statement(ts); 665 | expect_token(get_token(ts), TOKEN_RPAREN); next_token(ts); 666 | ast->forbody = parse_compound(ts); 667 | 668 | return ast; 669 | } 670 | 671 | vector* parse_declarator(tokenstream* ts) { 672 | vector* v = new_vector(); 673 | typenode* typ = parse_typespec(ts); 674 | if (typ == NULL) return v; 675 | while (true) { 676 | typenode* decltyp = parse_pointer(ts, typ); 677 | paramtype* pt = malloc(sizeof(paramtype)); 678 | expect_token(get_token(ts), TOKEN_IDENT); 679 | pt->name = get_token(ts)->ident; next_token(ts); 680 | // pt->typ = decltyp; 681 | pt->typ = parse_arraydecl(ts, decltyp); 682 | vector_push(v, pt); 683 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_COMMA) break; 684 | next_token(ts); 685 | } 686 | return v; 687 | } 688 | 689 | astree* parse_vardecl(tokenstream* ts) { 690 | vector* decls = parse_declarator(ts); 691 | if (decls->len == 0) return NULL; 692 | astree* ast = new_ast(AST_STATEMENTS); 693 | ast->stmts = new_vector(); 694 | for (int i=0; ilen; i++) { 695 | astree* varast = new_ast(AST_VARDECL); 696 | varast->vardecl = vector_get(decls, i); 697 | varast->varinit = NULL; 698 | vector_push(ast->stmts, varast); 699 | } 700 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_ASSIGN) { 701 | next_token(ts); 702 | for (int i=0; istmts->len; i++) { 703 | astree* vast = vector_get(ast->stmts, i); 704 | vast->varinit = expression(ts); 705 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_COMMA) break; 706 | next_token(ts); 707 | } 708 | } 709 | return ast; 710 | } 711 | 712 | astree* parse_statement(tokenstream* ts) { 713 | astree* returnast = parse_return(ts); 714 | if (returnast != NULL) { 715 | return returnast; 716 | } 717 | 718 | astree* ifast = parse_if(ts); 719 | if (ifast != NULL) { 720 | return ifast; 721 | } 722 | 723 | astree* whileast = parse_while(ts); 724 | if (whileast != NULL) { 725 | return whileast; 726 | } 727 | 728 | if (eq_ident(get_token(ts), "break")) { 729 | next_token(ts); 730 | return new_ast(AST_BREAK); 731 | } 732 | if (eq_ident(get_token(ts), "continue")) { 733 | next_token(ts); 734 | return new_ast(AST_CONTINUE); 735 | } 736 | 737 | astree* forast = parse_for(ts); 738 | if (forast != NULL) { 739 | return forast; 740 | } 741 | 742 | astree* declast = parse_vardecl(ts); 743 | if (declast != NULL) { 744 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) next_token(ts); 745 | return declast; 746 | } 747 | 748 | astree* e = expression(ts); 749 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) next_token(ts); 750 | return e; 751 | } 752 | 753 | vector* parse_statements(tokenstream* ts) { 754 | vector* v = new_vector(); 755 | while (true) { 756 | if (get_token(ts) == NULL || get_token(ts)->kind == TOKEN_RBRACE) break; 757 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) { 758 | next_token(ts); 759 | continue; 760 | } 761 | vector_push(v, parse_statement(ts)); 762 | } 763 | return v; 764 | } 765 | 766 | astree* parse_compound(tokenstream* ts) { 767 | if (get_token(ts) == NULL) return NULL; 768 | if (get_token(ts)->kind == TOKEN_LBRACE) { 769 | next_token(ts); 770 | astree* ast = new_ast(AST_STATEMENTS); 771 | ast->stmts = parse_statements(ts); 772 | expect_token(get_token(ts), TOKEN_RBRACE); next_token(ts); 773 | return ast; 774 | } else { 775 | astree* ast = parse_statement(ts); 776 | return ast; 777 | } 778 | } 779 | 780 | // 781 | // funcdecl 782 | // 783 | 784 | paramtype* parse_paramtype(tokenstream* ts) { 785 | typenode* tn = parse_typeexpr(ts); 786 | if (tn == NULL) return NULL; 787 | if (get_token(ts) == NULL || get_token(ts)->kind != TOKEN_IDENT) { 788 | paramtype* pt = malloc(sizeof(paramtype)); 789 | pt->typ = tn; 790 | pt->name = NULL; 791 | return pt; 792 | } 793 | token* t = get_token(ts); next_token(ts); 794 | if (t->kind != TOKEN_IDENT) error("expected identifier in parameter."); 795 | tn = parse_arraydecl(ts, tn); 796 | paramtype* pt = malloc(sizeof(paramtype)); 797 | pt->typ = tn; 798 | pt->name = t->ident; 799 | return pt; 800 | } 801 | 802 | vector* parse_paramtype_list(tokenstream* ts) { 803 | vector* ptlist = new_vector(); 804 | while (true) { 805 | if (get_token(ts) == NULL) break; 806 | if (get_token(ts)->kind != TOKEN_IDENT) break; 807 | paramtype* pt = parse_paramtype(ts); 808 | if (pt == NULL) error("expect type declaration in parameters."); 809 | vector_push(ptlist, pt); 810 | token* t = get_token(ts); 811 | if (t == NULL) error("require more token."); 812 | if (t->kind != TOKEN_COMMA) break; 813 | next_token(ts); 814 | } 815 | return ptlist; 816 | } 817 | 818 | paramtype* parse_paramtype(tokenstream* ts); 819 | vector* parse_paramtype_list(tokenstream* ts); 820 | 821 | toplevel* parse_toplevel(tokenstream* ts) { 822 | toplevel* top = malloc(sizeof(toplevel)); 823 | 824 | if (eq_ident(get_token(ts), "typedef")) { 825 | next_token(ts); 826 | typenode* typ = parse_typeexpr(ts); 827 | if (typ->kind == TYPE_STRUCT) { 828 | top->kind = TOP_STRUCT; 829 | top->structtype = typ; 830 | typenode* alreadystruct = map_get(structmap, top->structtype->tname); 831 | if (alreadystruct != NULL) { 832 | alreadystruct->kind = top->structtype->kind; 833 | alreadystruct->tname = top->structtype->tname; 834 | alreadystruct->fields = top->structtype->fields; 835 | alreadystruct->structsize = top->structtype->structsize; 836 | alreadystruct->maxalign = top->structtype->maxalign; 837 | top->structtype = alreadystruct; 838 | } else { 839 | map_insert(structmap, top->structtype->tname, top->structtype); 840 | } 841 | } else { 842 | top->kind = TOP_NONE; 843 | } 844 | expect_token(get_token(ts), TOKEN_IDENT); 845 | char* typedefname = get_token(ts)->ident; next_token(ts); 846 | map_insert(typedefmap, typedefname, typ); 847 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) next_token(ts); 848 | return top; 849 | } 850 | 851 | if (eq_ident(get_token(ts), "extern")) { 852 | next_token(ts); 853 | paramtype* pt = parse_paramtype(ts); 854 | top->kind = TOP_EXTERN; 855 | top->vdecl = pt; 856 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) next_token(ts); 857 | return top; 858 | } 859 | 860 | paramtype* pt = parse_paramtype(ts); 861 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_LPAREN) { 862 | next_token(ts); 863 | top->kind = TOP_FUNCDECL; 864 | top->fdecl = pt; 865 | top->argdecls = parse_paramtype_list(ts); 866 | expect_token(get_token(ts), TOKEN_RPAREN); next_token(ts); 867 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) { 868 | top->body = NULL; 869 | } else { 870 | expect_token(get_token(ts), TOKEN_LBRACE); next_token(ts); 871 | top->body = parse_statements(ts); 872 | expect_token(get_token(ts), TOKEN_RBRACE); next_token(ts); 873 | } 874 | } else if (pt->name != NULL) { 875 | top->kind = TOP_GLOBALVAR; 876 | top->vdecl = pt; 877 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_ASSIGN) { 878 | next_token(ts); 879 | top->vinit = expression(ts); 880 | } else { 881 | top->vinit = NULL; 882 | } 883 | } else { 884 | if (pt->typ->kind == TYPE_STRUCT) { 885 | top->kind = TOP_STRUCT; 886 | top->structtype = pt->typ; 887 | typenode* alreadystruct = map_get(structmap, top->structtype->tname); 888 | if (alreadystruct != NULL) { 889 | alreadystruct->kind = top->structtype->kind; 890 | alreadystruct->tname = top->structtype->tname; 891 | alreadystruct->fields = top->structtype->fields; 892 | alreadystruct->structsize = top->structtype->structsize; 893 | alreadystruct->maxalign = top->structtype->maxalign; 894 | top->structtype = alreadystruct; 895 | } else { 896 | map_insert(structmap, top->structtype->tname, top->structtype); 897 | } 898 | } else { 899 | top->kind = TOP_NONE; 900 | } 901 | } 902 | 903 | if (get_token(ts) != NULL && get_token(ts)->kind == TOKEN_SEMICOLON) next_token(ts); 904 | 905 | return top; 906 | } 907 | --------------------------------------------------------------------------------