6 #include "utf8_string.h"
8 #include "sublexer_impl.h"
9 #include "lexeme_impl.h"
10 #include "delimiter.h"
11 #include "number_lexer.h"
14 using namespace utakata;
15 using namespace utakata::utf8_string;
17 smart_ptr<lexeme::ILexeme> sublexer::FirstLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
18 smart_ptr<sublexer::ISubLexer>& next)
20 // chにはlexerから渡された、今回読みだした文字が渡されている。
24 // 最初に実行されるので、最初の空白を読み飛ばす。
25 UTF8Char ch(stream->read());
27 lexer_delimiter::Whitespace sps;
32 // ここまで来た段階で、chには調べる対象となる文字が入っている。
34 // ()[]`'が最初だった場合、それぞれを返してやる。
35 if (ch.toUTF16Code() == '(' || ch.toUTF16Code() == '[')
37 return lexeme::makeOpenParen();
39 else if (ch.toUTF16Code() == ')' || ch.toUTF16Code() == ']')
41 return lexeme::makeCloseParen();
43 else if (ch.toUTF16Code() == '`')
45 return lexeme::makeBackQuote();
47 else if (ch.toUTF16Code() == '\'')
49 return lexeme::makeQuote();
51 else if (ch.toUTF16Code() == '.')
53 // 次の文字がデリミタで終了していなければならない。
54 if (lexer_delimiter::Normal()(UTF8Char(stream->peek())))
56 return lexeme::makeDot();
59 else if (utf8_string::is_numeric(ch))
61 // 先頭が数値だった場合、これは10進数だと判断して次に進む。
62 next.add(new sublexer::NumberLexer(UTF8String(ch.getBytes())));
63 return smart_ptr<lexeme::ILexeme>();
65 else if (utf8_string::is_alpha(ch) ||
66 ch.toUTF16Code() == '!' || ch.toUTF16Code() == '$' ||
67 ch.toUTF16Code() == '%' || ch.toUTF16Code() == '&' ||
68 ch.toUTF16Code() == '*' || ch.toUTF16Code() == '/' ||
69 ch.toUTF16Code() == ':' || ch.toUTF16Code() == '<' ||
70 ch.toUTF16Code() == '>' || ch.toUTF16Code() == '?' ||
71 ch.toUTF16Code() == '^' || ch.toUTF16Code() == '_' ||
72 ch.toUTF16Code() == '~' || ch.toUTF16Code() == '+' ||
73 ch.toUTF16Code() == '.')
75 // やたらと多いが、上記のどれかである場合には、identityとして解析を
77 next.add(new sublexer::IdentifierLexer(UTF8String(ch.getBytes())));
78 return smart_ptr<lexeme::ILexeme>();
80 else if (ch.toUTF16Code() == ';')
82 // 一行コメントになるため、そちらに任せる。
83 next.add(new sublexer::OneLineCommentLexer());
85 else if (str[0].toUTF16Code() == '"')
87 // 先頭が"の場合、stringと判断される。
88 next.add(new sublexer::StringLexer());
92 // ここ以降になると、決定するまで読んでから決定させる。
94 smart_ptr<lexeme::ILexeme> l = lex_(str, stream, next);
100 // ここに来る場合、次の解析結果が存在する場合のみである。
103 throw sublexer::LexException(stream->pos(), "構文エラー");
105 return smart_ptr<lexeme::ILexeme>();
108 smart_ptr<lexeme::ILexeme> sublexer::FirstLexer::lex_(const utakata::utf8_string::UTF8String& str,
109 smart_ptr<utakata::utf8::UTF8InputStream> stream,
110 smart_ptr<ISubLexer>& next)
112 if (str[0].toUTF16Code() == ',')
114 UTF8Char ch = stream->peek();
116 if (ch.toUTF16Code() == '@')
119 return lexeme::makeUnquoteSplicing(str + ch);
123 // 次の文字が@では無い場合、とりあえず,で返す。
124 return lexeme::makeUnquote();
127 else if (str[0].toUTF16Code() == '#')
129 // コメントなどに繋がる時もあるため、面倒。
130 UTF8Char ch = stream->peek();
131 if (ch.toUTF16Code() == '\'')
133 return lexeme::makeSyntax();
137 return lexeme::makeQuasiSyntax();
139 else if (ch.toUTF16Code() == ',')
144 if (ch.toUTF16Code() == '@')
147 return lexeme::makeUnsyntaxSplicing();
151 return lexeme::makeUnsyntax();
154 else if (ch.toUTF16Code() == '|')
156 // ネストコメントの開始という判断がなされ、ネストコメント
159 next.add(new sublexer::NestedCommentLexer(str + ch));
161 else if (ch.toUTF16Code() == 'e' || ch.toUTF16Code() == 'E' ||
162 ch.toUTF16Code() == 'i' || ch.toUTF16Code() == 'I' ||
163 ch.toUTF16Code() == 'b' || ch.toUTF16Code() == 'B' ||
164 ch.toUTF16Code() == 'o' || ch.toUTF16Code() == 'O' ||
165 ch.toUTF16Code() == 'd' || ch.toUTF16Code() == 'D' ||
166 ch.toUTF16Code() == 'x' || ch.toUTF16Code() == 'X')
168 // 数値のプレフィックス、もしくはexactnessになるため、これは
171 next.add(new sublexer::NumberLexer(str + ch));
173 else if (ch.toUTF16Code() == '\\')
175 // #\の場合、次には文字が出てくるはずなので、そのまま進む。
177 next.add(new sublexer::CharactorLexer());
180 else if (str[0].toUTF16Code() == '-')
182 // 先頭が-の場合、次の文字を見てから決める。
183 // 基本的には数値だが、次の文字によってはidentifierになりうる。
184 UTF8Char ch(stream->peek());
185 lexer_delimiter::Normal nor;
186 if (ch.toUTF16Code() == '>' || nor(ch))
188 next.add(new sublexer::IdentifierLexer(str));
192 next.add(new sublexer::NumberLexer(str));
196 return smart_ptr<lexeme::ILexeme>();
200 //================================================================================
202 smart_ptr<lexeme::ILexeme> sublexer::StringLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
203 smart_ptr<sublexer::ISubLexer>& next)
207 lexer_delimiter::Normal nor;
208 lexer_delimiter::String st;
209 lexer_delimiter::Whitespace w;
210 utf8_string::UTF8String str;
212 while (!stream->isEOF()) {
213 UTF8Char tmp(stream->peek());
214 if (nor(tmp) || st(tmp)) {
218 if (tmp.toUTF16Code() == '\\')
221 while (!stream->isEOF() &&
222 (w(tmp) || nor(tmp))) {}
224 str += stream->read();
228 return smart_ptr<lexeme::ILexeme>();
231 //================================================================================
233 smart_ptr<lexeme::ILexeme> sublexer::NestedCommentLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
234 smart_ptr<sublexer::ISubLexer>& next)
236 // ネストしたコメントを解釈する。基本的には改行も関係無く処理する。
238 while (!stream->isEOF() && count > 0) {
239 utf8_string::UTF8Char tmp(stream->read());
241 if (tmp.toUTF16Code() == '#')
244 utf8_string::UTF8Char t2(stream->read());
245 if (t2.toUTF16Code() == '|')
250 else if (tmp.toUTF16Code() == '|')
253 utf8_string::UTF8Char t2(stream->read());
254 if (t2.toUTF16Code() == '#')
261 return smart_ptr<lexeme::ILexeme>();
264 //================================================================================
266 sublexer::NumberLexer::NumberLexer(const utf8_string::UTF8String& str) :
267 BINARY(2), OCTET(8), DECIMAL(10), HEX(16),
268 str_(new utf8_string::UTF8String(str)), exact_(false), prefix_(0)
272 smart_ptr<lexeme::ILexeme> sublexer::NumberLexer::innerLex_(smart_ptr<utf8::UTF8InputStream> stream,
273 smart_ptr<sublexer::ISubLexer>& next,
274 const utf8_string::UTF8String& str)
276 // prefixをチェックして、返すべきものを決定する。
277 if (prefix_ == BINARY)
279 return number::Number<2>().lex(stream, next, exact_);
281 else if (prefix_ == OCTET)
283 return number::Number<8>().lex(stream, next, exact_);
285 else if (prefix_ == DECIMAL)
287 return number::Number<10>().lex(stream, next, exact_);
289 else if (prefix_ == HEX)
291 return number::Number<16>().lex(stream, next, exact_);
295 return smart_ptr<lexeme::ILexeme>();
299 void sublexer::NumberLexer::checkExactness_(const utf8_string::UTF8String& str)
301 // 正確性をチェックする。2文字目だけを調べればそれですむ。
302 if (str[1].toUTF16Code() == 'e' || str[1].toUTF16Code() == 'E')
306 else if (str[1].toUTF16Code() == 'i' || str [1].toUTF16Code() == 'I')
312 unsigned char sublexer::NumberLexer::getPrefix_(const utf8_string::UTF8String& str)
315 if (str[1].toUTF16Code() == 'b' ||
316 str[1].toUTF16Code() == 'B')
320 else if (str[1].toUTF16Code() == 'o' ||
321 str[1].toUTF16Code() == 'O')
325 else if (str[1].toUTF16Code() == 'd' ||
326 str[1].toUTF16Code() == 'D')
330 else if (str[1].toUTF16Code() == 'x' ||
331 str[1].toUTF16Code() == 'X')
339 smart_ptr<lexeme::ILexeme> sublexer::NumberLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
340 smart_ptr<sublexer::ISubLexer>& next)
343 lexer_delimiter::Exactness e;
344 lexer_delimiter::Prefix p;
347 // 先頭はすでに読みとばされている。次に続く可能性があるため、継続して調査をしてみる。
351 prefix_ = getPrefix_(*str_);
352 // 次にexactnessが続いているかどうかを調べる。
353 utf8_string::UTF8String s = utf8_string::substring(*str_, 2);
356 // Exactnessである場合、実際にそうであるかどうかをチェックする。
359 s = utf8_string::substring(s, 2);
360 return innerLex_(stream, next, s);
364 // Exactnessであるため、次にprefixの必要がある。
365 checkExactness_(*str_);
367 utf8_string::UTF8String s = utf8_string::substring(*str_, 2);
370 prefix_ = getPrefix_(s);
376 return innerLex_(stream, next, s);
380 // どっちでもない場合、基本的に10進数として処理する。
382 return innerLex_(stream, next, *str_);
386 //================================================================================
388 sublexer::IdentifierLexer::IdentifierLexer(const utf8_string::UTF8String& str) :
389 str_(new utf8_string::UTF8String(str))
392 smart_ptr<lexeme::ILexeme> sublexer::IdentifierLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
393 smart_ptr<sublexer::ISubLexer>& next)
395 // Identityを解析する。解釈自体は結構簡単。
397 // 一文字目はすでに判定されているため、二文字目以降で判定する。
398 // 二文字名以降でなければ判定できないものもあるため、一度まとめてみる。
399 lexer_delimiter::Normal nor;
400 utf8_string::UTF8String& str = *str_;
401 if (str[0].toUTF16Code() == '+')
403 return lexeme::makeIdentifier(str);
405 else if (str[0].toUTF16Code() == '-')
407 // 次の文字がデリミタの場合には、そのまま返す。
408 UTF8Char next(stream->peek());
411 return lexeme::makeIdentifier(str);
413 else if (next.toUTF16Code() == '>')
419 while (!stream->isEOF()) {
420 UTF8Char tmp(stream->peek());
424 str += stream->read();
427 return lexeme::makeIdentifier(str);
430 //================================================================================
432 smart_ptr<lexeme::ILexeme> sublexer::CharactorLexer::lex(smart_ptr<utf8::UTF8InputStream> stream,
433 smart_ptr<sublexer::ISubLexer>& next)
435 // #\に続く文字名、あるいは#\xに続く16進数のチェックを行なう。
436 // ここに来た時点で、#\までは読まれている。
437 UTF8Char ch(stream->read());
438 bool flag = ch.toUTF16Code() == 'x' ? true : false;
440 // Hexを解釈する。解釈部分を書くと面倒になるため、単純な別関数にしておく。
441 UTF8String str(ch.getBytes());
442 lexer_delimiter::Normal nor;
443 lexer_delimiter::HexValue hex;
444 while (!stream->isEOF()) {
445 UTF8Char tmp(stream->peek());
450 else if (flag && !hex(tmp))
452 // hex valueではなかった場合には、これはエラーであると
454 std::stringstream ss;
455 ss << tmp.toStr() << "は16進数中の文字名として利用できません";
456 throw sublexer::LexException(stream->pos(), ss.str());
458 str += stream->read();
461 return lexeme::makeCharactor(str);
464 //================================================================================
467 smart_ptr<lexeme::ILexeme> sublexer::OneLineCommentLexer::lex(
468 smart_ptr<utf8::UTF8InputStream> stream,
469 smart_ptr<sublexer::ISubLexer>& next)
474 // なおコメントは原則として全て読み飛ばされるため、解釈が完了した
475 // 後、FirstLexerが再び返される。
476 lexer_delimiter::LineEnding end;
477 while (!stream->isEOF()) {
478 // 改行が出力されるまで全て読み飛ばす。
479 UTF8Char ch = stream->read();
482 // この時点で、読み飛ばしまで行われている。
483 next.add(new sublexer::FirstLexer());
487 return smart_ptr<lexeme::ILexeme>();
491 //================================================================================
493 sublexer::LexException::LexException(size_t pos, std::string str) : pos_(pos),
497 std::stringstream ss;
498 ss << "lex error ! -- pos : [" << pos << "] message : [" << str << "]" << std::endl;
502 const char* sublexer::LexException::what() const throw()