Skip to content

Commit

Permalink
main.cを複数ファイルへ分割
Browse files Browse the repository at this point in the history
  • Loading branch information
lvlnaga committed Jan 7, 2023
1 parent e89c0bb commit 1214df1
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 400 deletions.
Binary file removed 9cc-memo.xmind
Binary file not shown.
401 changes: 2 additions & 399 deletions 9cc.c

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions 9cc.h
@@ -0,0 +1,81 @@
#include <ctype.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//
// tokenize.c
//

// トークンの種類
typedef enum
{
TK_RESERVED, // 記号
TK_NUM, // 整数トークン
TK_EOF, // 入力の終わりを表すトークン
} TokenKind;

// トークン型
typedef struct Token Token;
struct Token
{
TokenKind kind; // トークンの型
Token *next; // 次の入力トークン
int val; // kindがTK_NUMの場合、その数値
char *str; // トークン文字列
int len; // トークンの長さ
};

// 関数プロトタイプ宣言
void error(char *fmt, ...);
void error_at(char *loc, char *fmt, ...);
bool consume(char *op);
void expect(char *op);
int expect_number();
bool at_eof();
Token *tokenize();

//
// parse.c
//

// 抽象構文木のノードの種類
typedef enum
{
ND_ADD, // +
ND_SUB, // -
ND_MUL, // *
ND_DIV, // /
ND_EQ, // ==
ND_NE, // !=
ND_LT, // <
ND_LE, // <=
ND_NUM // 整数
} NodeKind;

// 抽象構文木のノードの型
typedef struct Node Node;
struct Node
{
NodeKind kind; // ノードの型
Node *lhs; // 左辺
Node *rhs; // 右辺
int val; // kindがND_NUMの場合のみ使う
};

Node *expr();

//
// codegen.c
//
void codegen(Node *node);


// グローバル変数
// 入力プログラム
char *user_input;

// 現在着目しているトークン
Token *token;
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
69 changes: 69 additions & 0 deletions codegen.c
@@ -0,0 +1,69 @@
#include "9cc.h"

static void gen(Node *node)
{
if (node->kind == ND_NUM)
{
printf(" push %d\n", node->val);
return;
}

gen(node->lhs);
gen(node->rhs);

printf(" pop rdi\n");
printf(" pop rax\n");

switch (node->kind)
{
case ND_ADD:
printf(" add rax, rdi\n");
break;
case ND_SUB:
printf(" sub rax, rdi\n");
break;
case ND_MUL:
printf(" imul rax, rdi\n");
break;
case ND_DIV:
printf(" cqo\n");
printf(" idiv rdi\n");
break;
case ND_EQ:
printf(" cmp rax, rdi\n");
printf(" sete al\n");
printf(" movzb rax, al\n");
break;
case ND_NE:
printf(" cmp rax, rdi\n");
printf(" setne al\n");
printf(" movzb rax, al\n");
break;
case ND_LT:
printf(" cmp rax, rdi\n");
printf(" setl al\n");
printf(" movzb rax, al\n");
break;
case ND_LE:
printf(" cmp rax, rdi\n");
printf(" setle al\n");
printf(" movzb rax, al\n");
break;
}

printf(" push rax\n");
}

void codegen(Node *node)
{
// アセンブリ前半部分を出力
printf(".intel_syntax noprefix\n");
printf(".globl main\n");
printf("main:\n");

// 抽象構文木を下りながらコード生成
gen(node);

printf(" pop rax\n");
printf(" ret\n");
}
Binary file added docs/9cc-memo.xmind
Binary file not shown.
File renamed without changes.
135 changes: 135 additions & 0 deletions parse.c
@@ -0,0 +1,135 @@
#include "9cc.h"

static Node *equality();
static Node *relational();
static Node *add();
static Node *mul();
static Node *unary();
static Node *primary();

Node *new_node(NodeKind kind)
{
Node *node = calloc(1, sizeof(Node));
node->kind = kind;
return node;
}

// ノード作成関数for2項演算子
Node *new_binary(NodeKind kind, Node *lhs, Node *rhs)
{
Node *node = new_node(kind);
node->kind = kind;
node->lhs = lhs;
node->rhs = rhs;
return node;
}

// ノード作成関数for数値
// 左辺, 右辺は設定不要
Node *new_num(int val)
{
Node *node = new_node(ND_NUM);
node->kind = ND_NUM;
node->val = val;
return node;
}

// expr = mul ("+" mul | "-" mul)*
// +,- : 左結合演算子
// expr = equality
Node *expr()
{
return equality();
}

// equality = relational ("==" relational | "!=" relational)*
static Node *equality()
{
Node *node = relational();
for (;;)
{
if (consume("=="))
node = new_binary(ND_EQ, node, relational());
else if (consume("!="))
node = new_binary(ND_NE, node, relational());
else
return node;
}
}

// relational = add ("<" add | "<=" add | ">" add | ">=" add)*
static Node *relational()
{
Node *node = add();
for (;;)
{
if (consume("<"))
node = new_binary(ND_LT, node, add());
else if (consume("<="))
node = new_binary(ND_LE, node, add());
else if (consume(">"))
node = new_binary(ND_LT, add(), node); // "<" へ変換し 左右項をひっくり返している
else if (consume(">="))
node = new_binary(ND_LE, add(), node); // "<=" へ変換し 左右項をひっくり返している
else
return node;
}
}

// add = mul ("+" mul | "-" mul)*
static Node *add()
{
Node *node = mul();
for (;;)
{
if (consume("+"))
node = new_binary(ND_ADD, node, mul());
else if (consume("-"))
node = new_binary(ND_SUB, node, mul());
else
return node;
}
}

// mul = unary ("*" unary | "/" unary)*
// *,/ : 左結合演算子
static Node *mul()
{
Node *node = unary();
for (;;)
{
if (consume("*"))
node = new_binary(ND_MUL, node, unary());
else if (consume("/"))
node = new_binary(ND_DIV, node, unary());
else
return node;
}
}

// unary = ("+" | "-")? primary
// TODO Referenceだと違うが、テキストに合わせる
static Node *unary()
{
if (consume("+"))
return primary();
if (consume("-"))
return new_binary(ND_SUB, new_num(0), primary());
return primary();
}

// primary = num | "(" expr ")"
static Node *primary()
{
// 次のトークンが"("なら、"(" expr ")"のはず
if (consume("("))
{
Node *node = expr();
expect(")");
return node;
}

// そうでなければ数値のはず
return new_num(expect_number());
}

0 comments on commit 1214df1

Please sign in to comment.