comparison WindowsOnly/WinScript/compiler.h @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:db40c85cad7a
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