-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
148 lines (128 loc) · 3.89 KB
/
main.cpp
File metadata and controls
148 lines (128 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
using namespace std;
#define BFK_ARRAY_SIZE 3000
#define BFK_MAX_LOOP_DEPTH 100
int main(int argc, char *argv[]){
if(argc == 1){
cerr << "[error]実行するファイルを指定してください." << endl;
return 1;
}
else if(argc > 2){
cout << "[warning]引数が多すぎます.2番目以降の引数は無視されます." << endl;
}
// ソースファイルの存在確認,オープン
FILE *bfk_source;
if((bfk_source = fopen(argv[1], "r")) == NULL){
cerr << "[error] " << argv[1] << " は存在しません" << endl;
return 1;
}
// brainfuckで使用する配列,ポインタの準備
char bfk_array[BFK_ARRAY_SIZE] = {0,};
const char *initial_bfk_pointer = bfk_array;
char *bfk_pointer = bfk_array;
// ソースコードの読み込み・実行用変数
char current_char;
unsigned int loop_depth = 0;
fpos_t previous_pos;
fgetpos(bfk_source, &previous_pos); // init
fpos_t loop_start_pos[BFK_MAX_LOOP_DEPTH] = {0,};
fpos_t loop_end_pos[BFK_MAX_LOOP_DEPTH] = {-1,};
bool jumped = false;
unsigned long long program_step=1;
unsigned int inside_loop = 0;
// ソースコード処理開始
while((current_char = fgetc(bfk_source)) != EOF){
switch(current_char){
case '>':
if(bfk_pointer < initial_bfk_pointer+BFK_ARRAY_SIZE-1){
bfk_pointer++;
}
else{
cerr << "[error] " << program_step + 1 << " ステップ目の>で配列の最大範囲を超えました.プログラムの実行を停止します." ;
return 1;
}
break;
case '<':
if(bfk_pointer > initial_bfk_pointer){
bfk_pointer--;
}
else{
cerr << "[error] " << program_step + 1 << " ステップ目の<で配列の最小範囲を超えました.プログラムの実行を停止します." << program_step ;
return 1;
}
break;
case '+':
(*bfk_pointer)++;
break;
case '-':
(*bfk_pointer)--;
break;
case '.':
cout << *bfk_pointer << flush;
break;
case ',':
cout << "代入する値を入力してください:";
cin >> *bfk_pointer;
break;
case '[':
// ループの深さ限界をチェック
if(loop_depth == BFK_MAX_LOOP_DEPTH){
cerr << "[error] " << program_step + 1 << " ステップ目の[でループのネストの深さの最大を超えました.プログラムの実行を停止します." ;
return 1;
}
// ループ開始位置の記録
if(!jumped){
loop_start_pos[loop_depth] = previous_pos;
}
jumped = false;
// ポインタが0なら対応する]まで進む
if(*bfk_pointer == 0){
inside_loop = 0;
while(1){
current_char = fgetc(bfk_source);
switch(current_char){
case EOF:
cerr << "[error] " << program_step + 1 << " ステップ目の[に対応する]が存在しません.プログラムの実行を停止します." ;
return 1;
case ']':
if(inside_loop == 0){
goto FINISH_PROCESSING_LOOP;
}
inside_loop--;
break;
case '[':
inside_loop++;
break;
}
}
FINISH_PROCESSING_LOOP:
break;
}
// ループの深さを更新
loop_depth++;
break;
case ']':
// 前の[まで戻り,ループの深さを更新
if(loop_depth == 0){
cerr << "[error] " << program_step + 1 << " ステップ目の]より前に[は存在しません.プログラムの実行を停止します." ;
return 1;
}
// ループ開始位置へジャンプ
fsetpos(bfk_source, &loop_start_pos[loop_depth-1]);
jumped = true;
loop_depth--;
break;
default:
// 他の文字はコメントとして読み飛ばす
program_step--;
break;
}
// 現在の位置を記憶
fgetpos(bfk_source, &previous_pos);
program_step++;
}
// 終了処理・正常終了通知
fclose(bfk_source);
cout << "\nプログラムは正常に終了しました." << endl;
return 0;
}