OSDN Git Service

object表現であったobject.cppを削除し、datum.cppとして再定義した。
[simplecms/utakata.git] / src / parser / parser.cpp.bk
1 #include <sstream>
2 #include <stack>
3
4 #include "parser.h"
5 #include "lexeme.h"
6 #include "lexeme_data.h"
7 #include "lexer.h"
8 #include "lexeme_id.h"
9 #include "datum_id.h"
10 #include "reader.h"
11 #include "object.h"
12 #include "gc.h"
13 #include "primitive.h"
14 #include "primitive_class.h"
15 #include "primitive_util.h"
16 #include "data_castor.h"
17
18 using namespace utakata;
19 using namespace utakata::parser;
20 using namespace utakata::lexeme;
21 using namespace utakata::interpreter;
22
23 parser::DatumException::DatumException(std::string str) : str_()
24 {
25     // エラーメッセージを定義する。
26     std::stringstream ss;
27     ss << "datum error ! -- message : [" << str << "]" << std::endl;
28     str_ = ss.str();
29 }
30
31 const char* parser::DatumException::what() const throw()
32 {
33     return str_.c_str();
34 }
35
36 ////////////////////////////
37 // Parser Implementations //
38 ///////////////////////////
39
40 parser::Parser::Parser(smart_ptr<lexer::Lexer> l) : lexer_(l),
41                                                     handler_()
42 {
43     // 初期状態用ハンドラの設定
44     std::pair<PARSERSTATUS, smart_ptr<IParserHandler> > p;
45     p.first = PS_INIT;
46     p.second.add(new InitHandler);
47     handler_.insert(p);
48
49     // リスト内部用ハンドラの設定
50     p.first = PS_LIST;
51     p.second.add(new ListHandler);
52     handler_.insert(p);
53
54     // .内用ハンドラの設定
55     p.first = PS_END_DOT;
56     p.second.add(new DotEndHandler);
57     handler_.insert(p);
58
59     // abbreviation 用ハンドラの設定
60     p.first = PS_ABBREVIATION;
61     p.second.add(new AbbrevHandler);
62     handler_.insert(p);
63
64     // error 用のハンドラの設定
65     p.first = PS_ERROR;
66     p.second.add(new ErrorHandler);
67     handler_.insert(p);
68 }
69
70 smart_ptr<data::Object> parser::Parser::parse(smart_ptr<reader::StreamReader>& strm,
71                                               gc::GarbageCollector& gc)
72 {
73     HandlerData data(gc);
74     data.status.push(PS_INIT);
75
76     while(!data.status.empty()) {
77
78         if(data.status.top() != PS_ERROR)
79         {
80             if (data.chain)
81             {
82                 data.chain = false;
83             }
84             else
85             {
86                 data.lexm = lexer_->lex(strm);
87             }
88             
89             if(data.lexm.isNull() ||
90                data.lexm->getID() == lexeme::LexemeID::eos)
91             {
92                 break;
93             }
94             // 基本的にすべてハンドラに任せる。
95             handler_[data.status.top()]->exec(data);
96         }
97         else
98         {
99             // ERROR だったら、強制的にハンドラを回してループから抜ける。
100             handler_[data.status.top()]->exec(data);
101         }
102     }
103
104     // stackのtopにはmainが殘ったままなので、data.stackのtopを追加してやる。
105     smart_ptr<data::Object> ret(new data::Object(data.stack.top()));
106     return ret;
107 }
108
109 bool parser::isAbbrev(smart_ptr<lexeme::ILexeme> l)
110 {
111     // abbreviation かどうかを判別する。
112     switch(l->getID().toEnum())
113     {
114     case lexeme::LexemeID::BACKQUOTE:        return true;
115     case lexeme::LexemeID::QUOTE:            return true;
116     case lexeme::LexemeID::UNQUOTE:          return true;
117     case lexeme::LexemeID::UNQUOTESPLICING:  return true;
118     case lexeme::LexemeID::SYNTAX:           return true;
119     case lexeme::LexemeID::QUASISYNTAX:      return true;
120     case lexeme::LexemeID::UNSYNTAX:         return true;
121     case lexeme::LexemeID::UNSYNTAXSPLICING: return true;
122     default:
123         return false;
124     }
125 }
126
127 interpreter::IObject* parser::makePrimitiveFromLexeme(smart_ptr<lexeme::ILexeme> l)
128 {
129     // 各lexemeに対応した固定lexemeを返す。
130     interpreter::IObject* o = NULL;
131     switch (l->getID().toEnum())
132     {
133     case lexeme::LexemeID::STRING:
134         return util::makeString(l->getData()->string->str);
135     case lexeme::LexemeID::CHARACTOR:
136         return util::makeCharactor(l->getData()->charactor->spec);
137     case lexeme::LexemeID::IDENTIFIER:
138         return util::makeSymbol(l->getData()->symbol->id);
139     case lexeme::LexemeID::BOOLEAN:
140         return util::makeBoolean(l->getData()->boolean->boolean);
141     case lexeme::LexemeID::NUMBER:
142     {
143         lexeme::NumberData& t = *(l->getData()->number);
144         return util::makeNumber(t.real, t.imagin, t.exact,
145                                 t.radix);
146     }
147     case lexeme::LexemeID::BACKQUOTE:
148         return util::Abbrev<primitive::Quasiquote>::make();
149     case lexeme::LexemeID::QUOTE:
150         return util::Abbrev<primitive::Quote>::make();
151     case lexeme::LexemeID::UNQUOTE:
152         return util::Abbrev<primitive::Unquote>::make();
153     case lexeme::LexemeID::UNQUOTESPLICING:
154         return util::Abbrev<primitive::UnquoteSplicing>::make();
155     case lexeme::LexemeID::SYNTAX:
156         return util::Abbrev<primitive::Syntax>::make();
157     case lexeme::LexemeID::QUASISYNTAX:
158         return util::Abbrev<primitive::Quasisyntax>::make();
159     case lexeme::LexemeID::UNSYNTAX:
160         return util::Abbrev<primitive::Unsyntax>::make();
161     case lexeme::LexemeID::UNSYNTAXSPLICING:
162         return util::Abbrev<primitive::UnsyntaxSplicing>::make();
163     default:
164         break;
165     }
166
167     return o;
168 }
169
170 /////////////////////
171 // parser handlers //
172 /////////////////////
173
174 bool InitHandler::exec_(HandlerData& data)
175 {
176     data.status.pop();
177     // 初期状態の解釈処理を行う。
178     if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
179     {
180         // 開き括弧である場合、compoundsに新しくpushして返る。
181         data.compounds.push(std::vector<data::Object>());
182         data.status.push(PS_LIST);
183     }
184     else if(data.lexm->getID() == lexeme::LexemeID::string ||
185             data.lexm->getID() == lexeme::LexemeID::number ||
186             data.lexm->getID() == lexeme::LexemeID::identifier ||
187             data.lexm->getID() == lexeme::LexemeID::charactor ||
188             data.lexm->getID() == lexeme::LexemeID::boolean)
189     {
190         // それぞれの場合、単純にstackに各オブジェクトをpushする。
191
192         data::Object o = data::Object(false,
193                                       data.gc.add(makePrimitiveFromLexeme(data.lexm)));
194         if (data.compounds.empty())
195         {
196             data.stack.push(o);
197         }
198         else
199         {
200             data.compounds.top().push_back(o);
201         }
202     }
203     else if(isAbbrev(data.lexm))
204     {
205         // abbreviation である場合には、 全体をリストに展開するため、carまでは
206         // 設定された状態にする。
207         std::vector<data::Object> v;
208         v.push_back(data::Object(false,
209                                  data.gc.add(makePrimitiveFromLexeme(data.lexm))));
210
211         data.compounds.push(v);
212
213         // status stack に、 PS_ABBREVIATIONとPS_INITを積む。
214         data.status.push(PS_ABBREVIATION);
215         data.status.push(PS_INIT);
216     }
217     else
218     {
219         throw DatumException("datum の開始記号ではありません");
220     }
221
222     return true;
223 }
224
225 // List 内部処理のハンドリング
226
227 bool ListHandler::exec_(HandlerData& data)
228 {
229     // list の開始部分である場合。
230     if(data.lexm->getID() == lexeme::LexemeID::openParenthesis)
231     {
232         // 更にcompoundsに追加して積む。
233         data.compounds.push(std::vector<data::Object>());
234         data.status.push(PS_LIST);
235     }
236     else if(data.lexm->getID() == lexeme::LexemeID::closeParenthesis)
237     {
238         // 原則として、閉括弧が来た時点で終了とするだけでよい。
239         // 現在のtopにあるcompoundsが、データであるとされているため、
240         // とりあえずtopにあるvectorをConsの繋がりに変換する。
241
242         std::vector<data::Object> v = data.compounds.top(); data.compounds.pop();
243         // vectorをConsへと変換するには、次のようにして後ろからやっていく
244         // 方式が一番面倒がない。
245         // 1. cdrをnil、carをvectorの末尾であるデータとしたconsを作成する。
246         // 2. vectorの次のデータをcar、前のconsをcdrとしたconsを作成する。
247         // 3. 先頭まで続ける。
248
249         if (v.size() == 0)
250         {
251             // サイズが0の場合には、nilを設定する。
252             data::Object o = data::Object(false,
253                                           data.gc.add(util::makeNil()));
254             pushList(data, o);
255         }
256         else
257         {
258             // 後ろから前に向かっていく。
259             std::vector<data::Object>::reverse_iterator begin = v.rbegin(),
260                 end = v.rend();
261             // ちょっと面倒すぎるなこれ。
262             data::Object o = data::Object(
263                 false, data.gc.add(
264                     util::makeCons(*begin,
265                                    data::Object(false, data.gc.add(util::makeNil()))))
266                 );
267             ++begin;
268             for (; begin != end; ++begin)
269             {
270                 // 順次oに再設定していく。
271                 o = data::Object(
272                     false, data.gc.add(
273                         util::makeCons(*begin, o)));
274             }
275             pushList(data, o);
276         }
277
278         data.status.pop();
279     }
280     else if (data.lexm->getID() == lexeme::LexemeID::string ||
281              data.lexm->getID() == lexeme::LexemeID::number ||
282              data.lexm->getID() == lexeme::LexemeID::identifier ||
283              data.lexm->getID() == lexeme::LexemeID::charactor ||
284              data.lexm->getID() == lexeme::LexemeID::boolean)
285     {
286         // データスタックの頂上にあるvectorに追加する。
287         data.compounds.top().push_back(
288             data::Object(
289                 false, data.gc.add(makePrimitiveFromLexeme(data.lexm))));
290     }
291     else if(isAbbrev(data.lexm))
292     {
293         // abbreviation は、結論としてはリストに展開される。carは常にabbreviationである
294         // とすることで問題は無いので、作成したconsを、topに置くことで実現する。
295
296         std::vector<data::Object> v;
297         v.push_back(data::Object(false,
298                                  data.gc.add(makePrimitiveFromLexeme(data.lexm))));
299
300         data.compounds.push(v);
301
302         // status stack に、 PS_ABBREVIATION と PS_INIT を積む。
303         data.status.push(PS_ABBREVIATION);
304         data.status.push(PS_INIT);
305     }
306     else if(data.lexm->getID() == lexeme::LexemeID::dot)
307     {
308         // .が来た場合で、topのvectorがemptyだったらどうしようもなくなるので終了。
309         
310         if (data.compounds.top().empty())
311         {
312             data.status.push(PS_ERROR);
313             data.error = "necessary one datum previous dot";
314         }
315         else
316         {
317             // この時点で、終わり方が確定したため、別のハンドラに任せる。
318             // ただし、compoundの方は特に変化は必要が無いので、そちらはそのまま。
319             data.status.pop();
320             data.status.push(PS_END_DOT);
321             data.status.push(PS_INIT);
322         }
323     }
324     else
325     {
326         // 上記以外は許容しない。
327         data.status.push(PS_ERROR);
328     }
329
330     return true;
331 }
332
333 void ListHandler::pushList(HandlerData& data, data::Object& o)
334 {
335     if (!data.compounds.empty())
336     {
337         data.compounds.top().push_back(o);
338     }
339     else
340     {
341         data.stack.push(o);
342     }
343 }
344
345 bool DotEndHandler::exec_(HandlerData& data)
346 {
347     // .後の) を待つ部分のハンドラ。
348     // このハンドラでは、) 以外が来た場合にはすべて構文エラーとなる。
349     data.status.pop();
350     if(data.lexm->getID() == lexeme::LexemeID::closeParenthesis)
351     {
352         // stackの頂点とcompoundsのトップを取得する。
353         std::vector<data::Object> v = data.compounds.top(); data.compounds.pop();
354         // vectorをConsへと変換するには、次のようにして後ろからやっていく
355         // 方式が一番面倒がない。
356         // 1. cdrをstackのtop、carをvectorの末尾であるデータとしたconsを作成する。
357         // 2. vectorの次のデータをcar、前のconsをcdrとしたconsを作成する。
358         // 3. 先頭まで続ける。
359
360         {
361             // 後ろから前に向かっていく。
362             std::vector<data::Object>::reverse_iterator begin = v.rbegin(),
363                 end = v.rend();
364             // ちょっと面倒すぎるなこれ。
365             // cdrにcompoundsの末尾を、carにその前を設定する。
366             data::Object o = data::Object(
367                 false, data.gc.add(
368                         util::makeCons(begin[1], begin[0]))
369                 );
370             begin += 2;
371             for (; begin != end; ++begin)
372             {
373                 // 順次oに再設定していく。
374                 o = data::Object(
375                     false, data.gc.add(
376                         util::makeCons(*begin, o)));
377             }
378
379             if (!data.compounds.empty())
380             {
381                 data.compounds.top().push_back(o);
382             }
383             else
384             {
385                 data.stack.push(o);
386             }
387         }
388
389         // ここまでは、すべてDataSpace内部のDataEntityを対象に処理しているため、
390         // Objectで正しく受け渡しができていれば問題は発生しない。
391     }
392     else
393     {
394         // 上記以外は許容しない。
395         data.status.push(PS_ERROR);
396     }
397
398     return true;
399 }
400
401 // Abbreviation 処理のハンドリング。
402
403 bool AbbrevHandler::exec_(HandlerData& data)
404 {
405     // abbreviationの場合、すでにPS_INITを事前に積んであるため、
406     // 一つ分のdatumが来ていることが確定している。
407     // すでにabbreviation分のObjectはcompoundのtopに積んであるため、
408     // consを作成して、compoundかstackのtopに積むだけ。
409
410     std::vector<data::Object> v = data.compounds.top(); data.compounds.pop();
411
412     if (v.size() != 2)
413     {
414         data.status.push(PS_ERROR);
415     }
416     else
417     {
418         // まだcompoundsが存在している場合には、これを返すようにする。
419         data::Object c = data::Object(
420             false, data.gc.add(util::makeCons(
421                                    v[1],
422                                    data::Object(false, data.gc.add(util::makeNil()))
423                                    )));
424         data::Object o =
425             data::Object(false,
426                          data.gc.add(util::makeCons(v[0], c)));
427         if (!data.compounds.empty())
428         {
429             data.compounds.top().push_back(o);
430         }
431         else
432         {
433             data.stack.push(o);
434         }
435     }
436
437     data.status.pop();
438     data.chain = true;
439
440     return true;
441 }
442
443 // syntax error のハンドリング
444
445 bool ErrorHandler::exec_(HandlerData& data)
446 {
447     // 基本的にはエラーのハンドリングを行うだけ。
448     // 一応発生した前後の位置と発生した lexeme くらいは表示したいかな。
449     std::stringstream ss;
450     ss << "syntax error:" << data.error;
451     throw DatumException(ss.str());
452
453     return true;
454 }