OSDN Git Service

<identify>、<number>、<boolean>を解釈するそれぞれの部分字句解析を行うLexerを追加。
[simplecms/utakata.git] / src / lexer / number_lexer.cpp
1 #include "src/lexeme.h"
2 #include "src/exception_macro.h"
3 #include "src/encoding_reader.h"
4 #include "src/lexer/term_checker.h"
5 #include "src/lexer/term_lexer.h"
6 #include "src/lexer/number_lexer.h"
7 #include "src/lexer/number_lexer_detail_templates.h"
8 #include "src/unicode.h"
9
10 namespace lexer = utakata::lexer;
11 namespace reader = utakata::reader;
12 namespace term = utakata::lexer::term;
13 namespace unicode = utakata::unicode;
14
15 // 宣言のコメントを参照してください。
16 bool lexer::detail::MantissaWidthLexer::Lex(reader::EncodingReader* reader,
17                                             unicode::UniString* string) {
18   lexer::TermLexer<term::NumberDigit<10> > digit_10;
19
20   unicode::UniChar ch(reader->Peek());
21   if (ch.rawcode() != '|') {
22     return true;
23   }
24
25   unicode::UniString code(ch, 1);
26   while (!reader->IsEof()) {
27     if (!digit_10.CheckToken(reader)) {
28       break;
29     }
30     unicode::Append(code, reader->Read(digit_10.ReadToken(reader)));
31   }
32
33   const int kMantissaSize = 2;
34   if (code.GetSize() < static_cast<unsigned int>(kMantissaSize)) {
35     THROW_EXCEPTION_(lexer::LexException,
36         unicode::Convert("must one or more digits that after `|' "));
37   }
38
39   string->Append(code);
40   return true;
41 }
42
43 // 宣言のコメントを参照してください。
44 bool lexer::detail::SuffixLexer::Lex(reader::EncodingReader* reader,
45                                      unicode::UniString* string) {
46   lexer::TermLexer<term::ExponentMarker> marker;
47   if (!marker.CheckToken(reader)) {
48     return true;
49   }
50
51   unicode::UniString code(unicode::Convert(
52       reader->Read(marker.ReadToken(reader))));
53
54   lexer::TermLexer<term::Sign> sign;
55   lexer::TermLexer<term::NumberDigit<10> > digit_10;
56
57   if (!sign.CheckToken(reader)) {
58     THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
59         "must have sign after `exponent marker'"));
60   }
61   code.Append(unicode::Convert(
62       reader->Read(marker.ReadToken(reader))));
63
64   if (!digit_10.CheckToken(reader)) {
65     THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
66         "must have digit[0-9] after `sign'"));
67   }
68
69   while (!reader->IsEof()) {
70     if (!digit_10.CheckToken(reader)) {
71       break;
72     }
73     code.Append(unicode::Convert(
74         reader->Read(marker.ReadToken(reader))));
75   }
76
77   string->Append(code);
78   return true;
79 }
80
81
82 // 宣言のコメントを参照してください。
83 bool lexer::detail::DecimalLexer::Lex(reader::EncodingReader* reader,
84                                       unicode::UniString* string) {
85   UIntegerLexer<10> uint_lexer;
86   unicode::UniString code;
87
88   if (uint_lexer.Lex(reader, &code)) {
89     SuffixLexer suffix;
90     unicode::UniString suffix_string;
91     suffix.Lex(reader, &suffix_string);
92
93     if (!suffix_string.IsEmpty()) {
94       string->Append(code);
95       string->Append(suffix_string);
96     } else {
97       InnerLexFloating(reader, &code);
98     }
99     string->Append(code);
100     return true;
101   } else {
102     lexer::TermLexer<term::NumberDigit<10> > digit;
103     SuffixLexer suffix;
104     
105     unicode::UniChar ch(reader->Peek());
106     if (ch.rawcode() != '.') {
107       return false;
108     }
109
110     code.Append(ch);
111
112     unicode::UniString digit_string;
113     while (!reader->IsEof() && digit.CheckToken(reader)) {
114       unicode::Append(digit_string, reader->Read(digit.ReadToken(reader)));
115     }
116
117     if (digit_string.IsEmpty()) {
118       THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
119           "complex format error that nessesary one of more digits after ."));
120     }
121     code.Append(digit_string);
122
123     if (!suffix.Lex(reader, &code)) {
124       THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
125           ". <digit> nessesary after suffix"));
126     }
127     string->Append(code);
128     return true;
129   }
130
131   return false;
132 }
133
134 // 宣言のコメントを参照してください。
135 bool lexer::detail::DecimalLexer::InnerLexFloating(
136     reader::EncodingReader* reader, unicode::UniString* string) {
137   lexer::TermLexer<term::NumberDigit<10> > digit;
138   SuffixLexer suffix;
139   unicode::UniString code;
140
141   unicode::UniChar ch(reader->Peek());
142
143   if (ch.rawcode() != '.') {
144     return false;
145   }
146
147   reader->Read();
148   code.Append(ch);
149
150   while (!reader->IsEof() && digit.CheckToken(reader)) {
151     unicode::Append(code, reader->Read(digit.ReadToken(reader)));
152   }
153
154   if (!suffix.Lex(reader, &code)) {
155     THROW_EXCEPTION_(lexer::LexException, unicode::Convert(
156         ". <digit> nessesary after suffix"));
157   }
158   string->Append(code);
159   return true;
160 }
161
162
163 // <number>の字句要素を解釈します。解釈されない場合、NULLが返されます。
164 // 字句構文違反があった場合、LexException例外が発生します。
165 lexer::Lexeme* lexer::NumberLexer::Lex(reader::EncodingReader* reader) {
166   lexer::detail::NumLexer<2> binary;
167   lexer::detail::NumLexer<8> oct;
168   lexer::detail::NumLexer<10> decimal;
169   lexer::detail::NumLexer<16> hex;
170
171   unicode::UniString number_string;
172   if (binary.Lex(reader, &number_string)) {
173     return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
174   } else if (oct.Lex(reader, &number_string)) {
175     return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
176   } else if (decimal.Lex(reader, &number_string)) {
177     return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
178   } else if (hex.Lex(reader, &number_string)) {
179     return new lexer::Lexeme(number_string, lexer::Lexeme::kNumber);
180   }
181
182   return NULL;
183 }