Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
426 additions
and
400 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 not shown.
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()); | ||
} | ||
|
Oops, something went wrong.