Skip to content

Commit

Permalink
一文字のローカル変数
Browse files Browse the repository at this point in the history
  • Loading branch information
arato-make committed Nov 25, 2020
1 parent b11e845 commit d361759
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 43 deletions.
105 changes: 93 additions & 12 deletions 9cc.c
@@ -1,12 +1,8 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "9cc.h"

typedef enum {
TK_RESERVED,
TK_IDENT,
TK_NUM,
TK_EOF,
} TokenKind;
Expand Down Expand Up @@ -70,6 +66,12 @@ int expect_number() {
return val;
}

int get_offset() {
int offset = (token->str[0] - 'a' + 1) * 8;
token = token->next;
return offset;
}

bool at_eof() {
return token->kind == TK_EOF;
}
Expand Down Expand Up @@ -104,7 +106,7 @@ Token *tokenize(char *p) {
continue;
}

if (strchr("+-*/()<>", *p)) {
if (strchr("+-*/()<>=;", *p)) {
cur = new_token(TK_RESERVED, cur, p++, 1);
continue;
}
Expand All @@ -115,6 +117,11 @@ Token *tokenize(char *p) {
continue;
}

if('a' <= *p && *p <= 'z') {
cur = new_token(TK_IDENT, cur, p++, 1);
continue;
}

error_at(p, "トークナイズできません");
}

Expand All @@ -131,7 +138,9 @@ typedef enum {
ND_EQ,
ND_NEQ,
ND_LT,
ND_LTE
ND_LTE,
ND_ASSIGN,
ND_LVAR,
} NodeKind;

typedef struct Node Node;
Expand All @@ -141,6 +150,7 @@ struct Node {
Node *lhs;
Node *rhs;
int val;
int offset;
};

Node *new_node(NodeKind kind, Node *lhs, Node *rhs) {
Expand All @@ -158,16 +168,48 @@ Node *new_node_num(int val) {
return node;
}

Node *new_node_ident(int offset) {
Node *node = calloc(1,sizeof(Node));
node->kind = ND_LVAR;
node->offset = offset;
return node;
}

Node *code[100];

Node *program();
Node *stmt();
Node *expr();
Node *assign();
Node *equality();
Node *relational();
Node *add();
Node *mul();
Node *primary();
Node *unary();

Node *program() {
int i = 0;
while (!at_eof())
code[i++] = stmt();
code[i] = NULL;
}

Node *stmt() {
Node *node = expr();
expect(";");
return node;
}

Node *expr() {
return assign();
}

Node *assign() {
Node *node = equality();
if (consume("="))
node = new_node(ND_ASSIGN, node, assign());
return node;
}

Node *equality() {
Expand Down Expand Up @@ -233,6 +275,10 @@ Node *primary() {
return node;
}

if (token->kind == TK_IDENT) {
return new_node_ident(get_offset());
}

return new_node_num(expect_number());
}

Expand All @@ -244,10 +290,36 @@ Node *unary() {
return primary();
}

void gen_lval(Node *node) {
if (node->kind != ND_LVAR)
error("代入の左辺値が変数ではありません");

printf(" mov rax, rbp\n");
printf(" sub rax, %d\n", node->offset);
printf(" push rax\n");
}

void gen(Node *node) {
if (node->kind == ND_NUM) {
switch (node->kind)
{
case ND_NUM:
printf(" push %d\n", node->val);
return;
case ND_LVAR:
gen_lval(node);
printf(" pop rax\n");
printf(" mov rax, [rax]\n");
printf(" push rax\n");
return;
case ND_ASSIGN:
gen_lval(node->lhs);
gen(node->rhs);

printf(" pop rdi\n");
printf(" pop rax\n");
printf(" mov [rax], rdi\n");
printf(" push rdi\n");
return;
}

gen(node->lhs);
Expand Down Expand Up @@ -304,15 +376,24 @@ int main(int argc, char **argv) {
user_input = argv[1];
token = tokenize(user_input);

Node *node = expr();
program();

printf(".intel_syntax noprefix\n");
printf(".globl main\n");
printf("main:\n");

gen(node);
printf(" push rbp\n");
printf(" mov rbp, rsp\n");
printf(" sub rsp, 208\n");

printf(" pop rax\n");
for (int i = 0; code[i]; i++) {
gen(code[i]);

printf(" pop rax\n");
}

printf(" mov rsp, rbp\n");
printf(" pop rbp\n");
printf(" ret\n");
return 0;
}
6 changes: 6 additions & 0 deletions 9cc.h
@@ -0,0 +1,6 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
7 changes: 6 additions & 1 deletion Makefile
@@ -1,6 +1,11 @@
CFLAGS=-std=c11 -g -static
SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)

9cc: 9cc.c
9cc: $(OBJS)
$(CC) -o 9cc $(OBJS) $(LDFLAGS)

$(OBJS): 9cc.h

test: 9cc
./test.sh
Expand Down
64 changes: 34 additions & 30 deletions test.sh
Expand Up @@ -16,35 +16,39 @@ assert() {
fi
}

assert 0 0
assert 42 42
assert 21 "5+20-4"
assert 41 " 12 + 34 - 5"
assert 47 '5+6*7'
assert 15 '5*(9-6)'
assert 4 '(3+5)/2'
assert 5 '6 + -1'
assert 1 '- - 1'
assert 1 '-5 + 6'

assert 0 '0==1'
assert 1 '42==42'
assert 1 '0!=1'
assert 0 '42!=42'

assert 1 '0<1'
assert 0 '1<1'
assert 0 '2<1'
assert 1 '0<=1'
assert 1 '1<=1'
assert 0 '2<=1'

assert 1 '1>0'
assert 0 '1>1'
assert 0 '1>2'
assert 1 '1>=0'
assert 1 '1>=1'
assert 0 '1>=2'
assert 1 '100-50*2 == 10*3-15*2'
assert 0 '0;'
assert 42 '42;'
assert 21 "5+20-4;"
assert 41 " 12 + 34 - 5;"
assert 47 '5+6*7;'
assert 15 '5*(9-6);'
assert 4 '(3+5)/2;'
assert 5 '6 + -1;'
assert 1 '- - 1;'
assert 1 '-5 + 6;'

assert 0 '0==1;'
assert 1 '42==42;'
assert 1 '0!=1;'
assert 0 '42!=42;'

assert 1 '0<1;'
assert 0 '1<1;'
assert 0 '2<1;'
assert 1 '0<=1;'
assert 1 '1<=1;'
assert 0 '2<=1;'

assert 1 '1>0;'
assert 0 '1>1;'
assert 0 '1>2;'
assert 1 '1>=0;'
assert 1 '1>=1;'
assert 0 '1>=2;'
assert 1 '100-50*2 == 10*3-15*2;'
assert 3 'a=3;'
assert 10 'z=2*5;'
assert 13 'z=2*5;a=3;c=a+z;'


echo OK

0 comments on commit d361759

Please sign in to comment.