0
|
1 #ifndef __COMPILER_H__
|
|
2 #define __COMPILER_H__
|
|
3
|
|
4 #include "script-parser.hh"
|
|
5 #include "vm.h"
|
|
6 #include "node.h"
|
|
7 #include <string>
|
|
8 #include <vector>
|
|
9
|
|
10 // Forward declarations.
|
|
11 class compiler;
|
|
12
|
|
13 // flexの関数宣言
|
|
14 #define YY_DECL \
|
|
15 yy::script_parser::token_type \
|
|
16 yylex(yy::script_parser::semantic_type* yylval, \
|
|
17 yy::script_parser::location_type* yylloc, \
|
|
18 compiler& driver)
|
|
19
|
|
20 YY_DECL;
|
|
21
|
|
22 // 仮想マシンコード生成用
|
|
23
|
|
24 class CVMCode {
|
|
25 public:
|
|
26 CVMCode(unsigned char op)
|
|
27 : size_(1), op_(op), arg1_(0)
|
|
28 {
|
|
29 }
|
|
30 CVMCode(unsigned char op, int arg1)
|
|
31 : size_(5), op_(op), arg1_(arg1)
|
|
32 {
|
|
33 }
|
|
34
|
|
35 unsigned char *Get(unsigned char *p) const
|
|
36 {
|
|
37 if (op_ != VM_MAXCOMMAND) { // ラベルのダミーコマンド
|
|
38 *p++ = op_;
|
|
39 if (size_ > 1) {
|
|
40 *(int *)p = arg1_;
|
|
41 p += 4;
|
|
42 }
|
|
43 }
|
|
44 return p;
|
|
45 }
|
|
46
|
|
47 public:
|
|
48 unsigned char size_;
|
|
49 unsigned char op_;
|
|
50 int arg1_;
|
|
51 } ;
|
|
52
|
|
53 // ラベル
|
|
54
|
|
55 class CLabel {
|
|
56 public:
|
|
57 CLabel(int index)
|
|
58 : index_(index), pos_(0)
|
|
59 {
|
|
60 }
|
|
61 ~CLabel()
|
|
62 {
|
|
63 }
|
|
64
|
|
65 public:
|
|
66 int index_;
|
|
67 int pos_;
|
|
68 } ;
|
|
69
|
|
70 // 変数テーブル
|
|
71
|
|
72 class CValueTag {
|
|
73 public:
|
|
74 CValueTag(): addr_(-1), type_(TYPE_INTEGER), size_(1), global_(false)
|
|
75 {
|
|
76 }
|
|
77 CValueTag(int addr, int type, int size, bool global)
|
|
78 : addr_(addr), type_(type), size_(size), global_(global)
|
|
79 {
|
|
80 }
|
|
81
|
|
82 public:
|
|
83 int addr_;
|
|
84 int type_;
|
|
85 int size_;
|
|
86 bool global_;
|
|
87 } ;
|
|
88
|
|
89 class CValueTable {
|
|
90 private:
|
|
91 typedef std::map<std::string, CValueTag>::iterator iter;
|
|
92 typedef std::map<std::string, CValueTag>::const_iterator const_iter;
|
|
93
|
|
94 public:
|
|
95 CValueTable(int start_addr=0): addr_(start_addr), global_(false)
|
|
96 {
|
|
97 }
|
|
98
|
|
99 void set_global()
|
|
100 {
|
|
101 global_ = true;
|
|
102 }
|
|
103
|
|
104 bool add(int type, const std::string &name, int size=1)
|
|
105 {
|
|
106 std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr_, type, size, global_)));
|
|
107 if (result.second) {
|
|
108 addr_ += size;
|
|
109 return true;
|
|
110 }
|
|
111 return false;
|
|
112 }
|
|
113
|
|
114 const CValueTag *find(const std::string &name) const
|
|
115 {
|
|
116 const_iter it = variables_.find(name);
|
|
117 if (it != variables_.end())
|
|
118 return &it->second;
|
|
119 return NULL;
|
|
120 }
|
|
121
|
|
122 bool add_arg(int type, const std::string &name, int addr)
|
|
123 {
|
|
124 std::pair<iter, bool> result = variables_.insert(make_pair(name, CValueTag(addr, type, 1, false)));
|
|
125 return result.second;
|
|
126 }
|
|
127
|
|
128 int size() const { return addr_; }
|
|
129 void clear()
|
|
130 {
|
|
131 variables_.clear();
|
|
132 addr_ = 0;
|
|
133 }
|
|
134
|
|
135 #ifdef _DEBUG
|
|
136 struct dump_action {
|
|
137 void operator()(const std::pair<std::string, CValueTag> &it)
|
|
138 {
|
|
139 std::cout << it.first << ", addr = " << it.second.addr_ << ", type = " << it.second.type_ << ", size = " << it.second.size_ << ", global = " << it.second.global_ << std::endl;
|
|
140 }
|
|
141 } ;
|
|
142
|
|
143 void dump() const
|
|
144 {
|
|
145 std::cout << "-------- value --------" << std::endl;
|
|
146 std::for_each(variables_.begin(), variables_.end(), dump_action());
|
|
147 }
|
|
148 #endif
|
|
149
|
|
150 private:
|
|
151 std::map<std::string, CValueTag> variables_;
|
|
152 int addr_;
|
|
153 bool global_;
|
|
154 } ;
|
|
155
|
|
156 // 関数定義用
|
|
157
|
|
158 class CFunctionTag {
|
|
159 private:
|
|
160 enum {
|
|
161 flag_declaration = 1 << 0,
|
|
162 flag_definition = 1 << 1,
|
|
163 flag_system = 1 << 2,
|
|
164 } ;
|
|
165
|
|
166 public:
|
|
167 CFunctionTag()
|
|
168 {
|
|
169 }
|
|
170 CFunctionTag(int type)
|
|
171 : type_(type), flags_(0), index_(0)
|
|
172 {
|
|
173 }
|
|
174
|
|
175 void SetArg(int type)
|
|
176 {
|
|
177 args_.push_back((char)type);
|
|
178 }
|
|
179
|
|
180 void SetArgs(const CArgList *args)
|
|
181 {
|
|
182 if (args) {
|
|
183 size_t size = args->size();
|
|
184 for (size_t i=0; i < size; i++) {
|
|
185 args_.push_back((char)args->get(i)->type());
|
|
186 }
|
|
187 }
|
|
188 }
|
|
189
|
|
190 bool SetArgs(const char *args)
|
|
191 {
|
|
192 if (args) {
|
|
193 for (int i=0; args[i] != 0; i++) {
|
|
194 switch (args[i]) {
|
|
195 case 'I': case 'i':
|
|
196 args_.push_back(TYPE_INTEGER);
|
|
197 break;
|
|
198
|
|
199 case 'S': case 's':
|
|
200 args_.push_back(TYPE_STRING);
|
|
201 break;
|
|
202
|
|
203 default:
|
|
204 return false;
|
|
205 }
|
|
206 }
|
|
207 }
|
|
208 return true;
|
|
209 }
|
|
210
|
|
211 bool ChkArgList(const CArgList *args) const
|
|
212 {
|
|
213 // 引数が無い場合
|
|
214 if (args == 0)
|
|
215 return args_.empty();
|
|
216
|
|
217 // 引数の個数が異なる
|
|
218 if (args_.size() != args->size())
|
|
219 return false;
|
|
220
|
|
221 // 全引数の型をチェック
|
|
222 size_t size = args_.size();
|
|
223 for (size_t i=0; i < size; i++) {
|
|
224 if (args->get(i)->type() != (int)args_[i])
|
|
225 return false;
|
|
226 }
|
|
227 return true;
|
|
228 }
|
|
229
|
|
230 // 指定の引数の型を得る
|
|
231
|
|
232 int GetArg(int index) const
|
|
233 {
|
|
234 return args_[index];
|
|
235 }
|
|
236
|
|
237 int ArgSize() const { return args_.size(); }
|
|
238
|
|
239 void SetIndex(int index) { index_ = index; }
|
|
240 void SetDeclaration() { flags_ |= flag_declaration; } // 宣言
|
|
241 void SetDefinition() { flags_ |= flag_definition; } // 定義
|
|
242 void SetSystem() { flags_ |= flag_system; }
|
|
243
|
|
244 int GetIndex() const { return index_; }
|
|
245 bool IsDeclaration() const { return (flags_ & flag_declaration) != 0; }
|
|
246 bool IsDefinition() const { return (flags_ & flag_definition) != 0; }
|
|
247 bool IsSystem() const { return (flags_ & flag_system) != 0; }
|
|
248
|
|
249 public:
|
|
250 int type_;
|
|
251 int flags_;
|
|
252 int index_;
|
|
253 std::vector<char> args_;
|
|
254 } ;
|
|
255
|
|
256 class CFunctionTable {
|
|
257 private:
|
|
258 typedef std::map<std::string, CFunctionTag>::iterator iter;
|
|
259 typedef std::map<std::string, CFunctionTag>::const_iterator const_iter;
|
|
260
|
|
261 public:
|
|
262 CFunctionTable()
|
|
263 {
|
|
264 }
|
|
265
|
|
266 CFunctionTag *add(const std::string &name, const CFunctionTag &tag)
|
|
267 {
|
|
268 std::pair<iter, bool> result = functions_.insert(make_pair(name, tag));
|
|
269 if (result.second)
|
|
270 return &result.first->second;
|
|
271 return NULL;
|
|
272 }
|
|
273
|
|
274 const CFunctionTag *find(const std::string &name) const
|
|
275 {
|
|
276 const_iter it = functions_.find(name);
|
|
277 if (it != functions_.end())
|
|
278 return &it->second;
|
|
279 return NULL;
|
|
280 }
|
|
281
|
|
282 CFunctionTag *find(const std::string &name)
|
|
283 {
|
|
284 iter it = functions_.find(name);
|
|
285 if (it != functions_.end())
|
|
286 return &it->second;
|
|
287 return NULL;
|
|
288 }
|
|
289
|
|
290 void clear()
|
|
291 {
|
|
292 functions_.clear();
|
|
293 }
|
|
294
|
|
295 private:
|
|
296 std::map<std::string, CFunctionTag> functions_;
|
|
297 } ;
|
|
298
|
|
299 // コンパイラ
|
|
300
|
|
301 class compiler {
|
|
302 public:
|
|
303 compiler();
|
|
304 virtual ~compiler();
|
|
305
|
|
306 std::string &get_filename() { return file; }
|
|
307 bool compile(const std::string &f, vm::data &data);
|
|
308 #ifdef _DEBUG
|
|
309 void debug_dump();
|
|
310 #endif
|
|
311
|
|
312 bool add_function(int index, int type, const char *name, const char *args);
|
|
313
|
|
314 void DefineValue(const yy::location& l, int type, CValueList *value_list);
|
|
315 void DefineFunction(const yy::location& l, int type, const std::string *name, CArgList *args);
|
|
316 void AddFunction(const yy::location& l, int type, const std::string *name, CArgList *args, CStateBlock *states);
|
|
317
|
|
318 // 変数の検索、内側のブロックから検索する。
|
|
319 const CValueTag *GetValueTag(const std::string &name) const
|
|
320 {
|
|
321 int size = (int)variables.size();
|
|
322 for (int i=size-1; i>=0; i--) {
|
|
323 const CValueTag *tag = variables[i].find(name);
|
|
324 if (tag)
|
|
325 return tag;
|
|
326 }
|
|
327 return NULL;
|
|
328 }
|
|
329
|
|
330 // 関数の検索
|
|
331 const CFunctionTag *GetFunctionTag(const std::string &name) const
|
|
332 {
|
|
333 return functions.find(name);
|
|
334 }
|
|
335
|
|
336 // for code generator.
|
|
337 #define VM_CREATE
|
|
338 #include "vm_code.h"
|
|
339 #undef VM_CREATE
|
|
340
|
|
341 void BlockIn();
|
|
342 void BlockOut();
|
|
343 void AllocStack();
|
|
344 int LabelSetting();
|
|
345
|
|
346 int SetBreakLabel(int label)
|
|
347 {
|
|
348 int old_index = break_index;
|
|
349 break_index = label;
|
|
350 return old_index;
|
|
351 }
|
|
352 bool JmpBreakLabel();
|
|
353
|
|
354 int MakeLabel();
|
|
355
|
|
356 void AddValue(const yy::location& l, int type, const std::string &name, const CNode *node);
|
|
357
|
|
358 void SetLabel(int label);
|
|
359
|
|
360 void PushString(const std::string &name);
|
|
361 int GetFunctionType() const { return current_function_type; }
|
|
362 bool CraeteData(vm::data &data, int code_size);
|
|
363
|
|
364 // Error handling.
|
|
365 void error(const yy::location& l, const std::string& m);
|
|
366 void error(const std::string& m);
|
|
367
|
|
368 // cout, cerrの出力先がない環境用
|
|
369 int error_message_size() const
|
|
370 {
|
|
371 return message.size();
|
|
372 }
|
|
373 const std::string &error_message(int no) const
|
|
374 {
|
|
375 return message[no];
|
|
376 }
|
|
377
|
|
378 private:
|
|
379 void scan_begin();
|
|
380 void scan_end();
|
|
381
|
|
382 private:
|
|
383 CFunctionTable functions;
|
|
384 std::vector<CValueTable> variables;
|
|
385 std::vector<CVMCode> statement;
|
|
386 std::vector<CLabel> labels;
|
|
387 std::vector<char> text_table;
|
|
388
|
|
389 int break_index;
|
|
390 int error_count;
|
|
391
|
|
392 std::string current_function_name;
|
|
393 int current_function_type;
|
|
394
|
|
395 std::string file;
|
|
396
|
|
397 std::vector<std::string> message;
|
|
398 } ;
|
|
399
|
|
400 #endif
|