Skip to content

Commit

Permalink
変数を実装
Browse files Browse the repository at this point in the history
  • Loading branch information
corgi0901 committed Aug 10, 2020
1 parent 7241371 commit dd7ed9e
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 7 deletions.
5 changes: 3 additions & 2 deletions BNF.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
program = add ("," add | "\n" add)*
program = expr ("," expr | "\n" expr)*
expr = ident "=" add | add
add = mul ("+" mul | "-" mul)*
mul = unary ("*" unary | "/" unary)*
unary = ("+" | "-")? primary
primary = num | "(" add ")"
primary = ident | num | "(" add ")"
63 changes: 62 additions & 1 deletion generator.cpp
Original file line number Diff line number Diff line change
@@ -1,15 +1,55 @@
#include <cstring>
#include <iostream>
#include <vector>
#include "generator.hpp"
#include "rook.hpp"

using namespace std;

bool Generator::findVar(const char* name, int len)
{
vector<Variable>::iterator itr;

for(itr = vars.begin(); itr != vars.end(); itr++){
if(strncmp(name, itr->name, len) == 0){
return true;
}
}

return false;
};

Variable Generator::getVar(const char* name, int len)
{
vector<Variable>::iterator itr;

for(itr = vars.begin(); itr != vars.end(); itr++){
if(strncmp(name, itr->name, len) == 0){
break;
}
}

return *itr;
};

void Generator::gen_var(Node* node)
{
if(findVar(node->name, node->len)){
Variable var = getVar(node->name, node->len);
operations.push_back( Operation{ OP_PUSH_I, var.offset } );
}
else{
Variable var = { node->name, node->len, offset++ };
vars.push_back(var);
operations.push_back( Operation{ OP_PUSH_I, var.offset } );
}
};

void Generator::gen(Node* node)
{
switch(node->kind){
case ND_NUM:
operations.push_back( Operation{ OP_PUSH, node->val } );
operations.push_back( Operation{ OP_PUSH_I, node->val } );
break;

case ND_ADD:
Expand Down Expand Up @@ -52,13 +92,34 @@ void Generator::gen(Node* node)

break;

case ND_ASSIGN:
gen_var(node->left);
gen(node->right);

operations.push_back( Operation{ OP_POP, REG_GR1 } );
operations.push_back( Operation{ OP_POP, REG_GR0 } );
operations.push_back( Operation{ OP_STORE, REG_GR0, REG_GR1 } );
operations.push_back( Operation{ OP_PUSH, REG_GR1 } );

break;

case ND_IDENT:
gen_var(node);

operations.push_back( Operation{ OP_POP, REG_GR0 } );
operations.push_back( Operation{ OP_LOAD, REG_GR1, REG_GR0 } );
operations.push_back( Operation{ OP_PUSH, REG_GR1 } );

break;

default:
break;
}
};

vector<Operation> Generator::codegen(vector<Node*> &nodes)
{
offset = 0;
vector<Node*>::iterator node;

for(node = nodes.begin(); node != nodes.end(); node++){
Expand Down
6 changes: 6 additions & 0 deletions generator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ class Generator
{
private:
vector<Operation> operations;
vector<Variable> vars;
int offset;

void gen(Node* node);
void gen_var(Node* node);
bool findVar(const char* name, int len);
Variable getVar(const char* name, int len);

public:
vector<Operation> codegen(vector<Node*> &nodes);
Expand Down
28 changes: 26 additions & 2 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,31 @@ vector<Node*> Parser::program(void)
{
vector<Node*> nodes;

nodes.push_back(add());
nodes.push_back(expr());

while(consume(",") || consume("\n")){
nodes.push_back(add());
nodes.push_back(expr());
}

return nodes;
};

Node* Parser::expr(void)
{
if(TK_IDENT == token->kind && strncmp((token+1)->str, "=", 1) == 0){
Node* ident = new Node();
ident->kind = ND_IDENT;
ident->name = token->str;
ident->len = token->len;
token++;
expect("=");
Node* setNode = new Node{ ND_ASSIGN, ident, add() };
return setNode;
}

return add();
};

Node* Parser::num(void)
{
if(TK_NUM != token->kind){
Expand Down Expand Up @@ -92,6 +108,14 @@ Node* Parser::primary(void)
expect(")");
return addNode;
}
else if(TK_IDENT == token->kind){
Node* ident = new Node();
ident->kind = ND_IDENT;
ident->name = token->str;
ident->len = token->len;
token++;
return ident;
}
else{
return num();
}
Expand Down
1 change: 1 addition & 0 deletions parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Parser
vector<Token>::iterator token; // 現在注目しているトークン

vector<Node*> program(void);
Node* expr(void);
Node* num(void);
Node* add(void);
Node* mul(void);
Expand Down
17 changes: 16 additions & 1 deletion rook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
typedef enum {
TK_NUM, // 数値
TK_RESERVED, // 記号
TK_IDENT, // 識別子
TK_EOF, // 終端
} TokenKind;

Expand All @@ -26,6 +27,8 @@ typedef enum {
ND_SUB, // -
ND_MUL, // *
ND_DIV, // /
ND_ASSIGN, // =
ND_IDENT, // 識別子
} NodeKind;

typedef struct Node Node;
Expand All @@ -35,17 +38,22 @@ struct Node {
Node *left; // 左辺
Node *right; // 右辺
int val; // ND_NUMのときに使う
char* name; // 変数名(ND_IDENTのときに使う)
int len; // 名前長(ND_IDENTのときに使う)
};


// 命令関連の定義
typedef enum {
OP_PUSH, // Push
OP_PUSH, // Push(レジスタ値)
OP_PUSH_I, // Push(即値)
OP_POP, // Pop
OP_ADD, // 加算
OP_SUB, // 減算
OP_MUL, // 乗算
OP_DIV, // 除算
OP_STORE, // レジスタ→メモリへの書き込み
OP_LOAD, // メモリ→レジスタへの読み込み
} OP_CODE;

typedef struct {
Expand All @@ -55,6 +63,13 @@ typedef struct {
} Operation;


// 変数定義
typedef struct {
char* name; // 変数名
int len; // 名前長
int offset; // データ格納先のオフセット
} Variable;

// レジスタ関連定義
typedef enum {
REG_GR0 = 0,
Expand Down
5 changes: 5 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,10 @@ test 5 "1++4"
test 21 "(-10+3)*-3"
test -7 "-(3+4)"
test 12 "1+2, 4*3"
test 1 "a=1"
test 9 "num = 3, num * num"
test 10 "a = 5, b = 2, c = a * b"
test 2 "a = -3, a + 5"
test 12 "n = 2, ret = 3 * (n + 2)"

echo "OK"
20 changes: 20 additions & 0 deletions tokenizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@

using namespace std;

bool Tokenizer::isAlnum(char c)
{
if(isalnum(c) || '_' == c){
return true;
}
else{
return false;
}
};

vector<Token> Tokenizer::tokenize(char* input)
{
vector<Token> tokens;
Expand Down Expand Up @@ -56,11 +66,21 @@ vector<Token> Tokenizer::tokenize(char* input)
tokens.push_back(token);
input++;
}
else if(strncmp(input, "=", 1) == 0){
Token token = { TK_RESERVED, input, 1 };
tokens.push_back(token);
input++;
}
else if(isdigit(*input)){
Token token = { TK_NUM, input, 0 };
for(; isdigit(*input); input++) token.len++;
tokens.push_back(token);
}
else if(isAlnum(*input)){
Token token = { TK_IDENT, input, 0 };
for(; isAlnum(*input); input++) token.len++;
tokens.push_back(token);
}
else{
cerr << "Invalid character : " << *input << endl;
exit(1);
Expand Down
3 changes: 3 additions & 0 deletions tokenizer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ using namespace std;

class Tokenizer
{
private:
bool isAlnum(char c);

public:
vector<Token> tokenize(char* input);
};
Expand Down
18 changes: 17 additions & 1 deletion vm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ using namespace std;

VM::VM()
{
sp = stack;
bp = stack;
sp = &stack[16];
};

void VM::push(DWORD val)
Expand All @@ -27,6 +28,11 @@ DWORD VM::run(vector<Operation>& code)
while(op != code.end()){
switch(op->opcode){
case OP_PUSH:
{
push(reg[op->operand]);
break;
}
case OP_PUSH_I:
{
push(op->operand);
break;
Expand Down Expand Up @@ -56,6 +62,16 @@ DWORD VM::run(vector<Operation>& code)
push(reg[op->operand] / reg[op->operand2]);
break;
}
case OP_STORE:
{
bp[reg[op->operand]] = reg[op->operand2];
break;
}
case OP_LOAD:
{
reg[op->operand] = bp[reg[op->operand2]];
break;
}
default:
break;
}
Expand Down
1 change: 1 addition & 0 deletions vm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class VM
private:
DWORD stack[STACK_SIZE]; // スタック
DWORD* sp; // スタックポインタ
DWORD* bp; // ベースポインタ

DWORD reg[REG_NUM]; // レジスタ

Expand Down

0 comments on commit dd7ed9e

Please sign in to comment.