28 #ifndef V8_DATEPARSER_INL_H_
29 #define V8_DATEPARSER_INL_H_
36 template <
typename Char>
41 InputReader<Char> in(unicode_cache, str);
42 DateStringTokenizer<Char> scanner(&in);
95 DateToken next_unhandled_token = ParseES5DateTime(&scanner, &day, &time, &tz);
96 if (next_unhandled_token.IsInvalid())
return false;
97 bool has_read_number = !day.IsEmpty();
99 for (DateToken token = next_unhandled_token;
100 !token.IsEndOfInput();
101 token = scanner.Next()) {
102 if (token.IsNumber()) {
103 has_read_number =
true;
104 int n = token.number();
105 if (scanner.SkipSymbol(
':')) {
106 if (scanner.SkipSymbol(
':')) {
108 if (!time.IsEmpty())
return false;
113 if (!time.Add(n))
return false;
114 if (scanner.Peek().IsSymbol(
'.')) scanner.Next();
116 }
else if (scanner.SkipSymbol(
'.') && time.IsExpecting(n)) {
118 if (!scanner.Peek().IsNumber())
return false;
119 int n = ReadMilliseconds(scanner.Next());
120 if (n < 0)
return false;
122 }
else if (tz.IsExpecting(n)) {
123 tz.SetAbsoluteMinute(n);
124 }
else if (time.IsExpecting(n)) {
128 DateToken peek = scanner.Peek();
129 if (!peek.IsEndOfInput() &&
130 !peek.IsWhiteSpace() &&
131 !peek.IsKeywordZ() &&
132 !peek.IsAsciiSign())
return false;
134 if (!day.Add(n))
return false;
135 scanner.SkipSymbol(
'-');
137 }
else if (token.IsKeyword()) {
139 KeywordType
type = token.keyword_type();
140 int value = token.keyword_value();
141 if (type == AM_PM && !time.IsEmpty()) {
142 time.SetHourOffset(value);
143 }
else if (type == MONTH_NAME) {
144 day.SetNamedMonth(value);
145 scanner.SkipSymbol(
'-');
146 }
else if (type == TIME_ZONE_NAME && has_read_number) {
150 if (has_read_number)
return false;
153 if (scanner.Peek().IsNumber())
return false;
155 }
else if (token.IsAsciiSign() && (tz.IsUTC() || !time.IsEmpty())) {
157 tz.SetSign(token.ascii_sign());
160 if (scanner.Peek().IsNumber()) {
161 n = scanner.Next().number();
163 has_read_number =
true;
165 if (scanner.Peek().IsSymbol(
':')) {
166 tz.SetAbsoluteHour(n);
167 tz.SetAbsoluteMinute(kNone);
169 tz.SetAbsoluteHour(n / 100);
170 tz.SetAbsoluteMinute(n % 100);
172 }
else if ((token.IsAsciiSign() || token.IsSymbol(
')')) &&
181 return day.Write(out) && time.Write(out) && tz.Write(out);
185 template<
typename CharType>
186 DateParser::DateToken DateParser::DateStringTokenizer<CharType>::Scan() {
187 int pre_pos = in_->position();
188 if (in_->IsEnd())
return DateToken::EndOfInput();
189 if (in_->IsAsciiDigit()) {
190 int n = in_->ReadUnsignedNumeral();
191 int length = in_->position() - pre_pos;
192 return DateToken::Number(n, length);
199 if (in_->IsAsciiAlphaOrAbove()) {
200 ASSERT(KeywordTable::kPrefixLength == 3);
201 uint32_t buffer[3] = {0, 0, 0};
202 int length = in_->ReadWord(buffer, 3);
203 int index = KeywordTable::Lookup(buffer, length);
204 return DateToken::Keyword(KeywordTable::GetType(index),
205 KeywordTable::GetValue(index),
208 if (in_->SkipWhiteSpace()) {
209 return DateToken::WhiteSpace(in_->position() - pre_pos);
211 if (in_->SkipParentheses()) {
212 return DateToken::Unknown();
215 return DateToken::Unknown();
219 template <
typename Char>
220 DateParser::DateToken DateParser::ParseES5DateTime(
221 DateStringTokenizer<Char>* scanner,
224 TimeZoneComposer* tz) {
230 if (scanner->Peek().IsAsciiSign()) {
233 DateToken sign_token = scanner->Next();
234 if (!scanner->Peek().IsFixedLengthNumber(6))
return sign_token;
235 int sign = sign_token.ascii_sign();
236 int year = scanner->Next().number();
237 if (sign < 0 && year == 0)
return sign_token;
238 day->Add(sign * year);
239 }
else if (scanner->Peek().IsFixedLengthNumber(4)) {
240 day->Add(scanner->Next().number());
242 return scanner->Next();
244 if (scanner->SkipSymbol(
'-')) {
245 if (!scanner->Peek().IsFixedLengthNumber(2) ||
246 !DayComposer::IsMonth(scanner->Peek().number()))
return scanner->Next();
247 day->Add(scanner->Next().number());
248 if (scanner->SkipSymbol(
'-')) {
249 if (!scanner->Peek().IsFixedLengthNumber(2) ||
250 !DayComposer::IsDay(scanner->Peek().number()))
return scanner->Next();
251 day->Add(scanner->Next().number());
255 if (!scanner->Peek().IsKeywordType(TIME_SEPARATOR)) {
256 if (!scanner->Peek().IsEndOfInput())
return scanner->Next();
260 if (!scanner->Peek().IsFixedLengthNumber(2) ||
261 !Between(scanner->Peek().number(), 0, 24)) {
262 return DateToken::Invalid();
265 bool hour_is_24 = (scanner->Peek().number() == 24);
266 time->Add(scanner->Next().number());
267 if (!scanner->SkipSymbol(
':'))
return DateToken::Invalid();
268 if (!scanner->Peek().IsFixedLengthNumber(2) ||
269 !TimeComposer::IsMinute(scanner->Peek().number()) ||
270 (hour_is_24 && scanner->Peek().number() > 0)) {
271 return DateToken::Invalid();
273 time->Add(scanner->Next().number());
274 if (scanner->SkipSymbol(
':')) {
275 if (!scanner->Peek().IsFixedLengthNumber(2) ||
276 !TimeComposer::IsSecond(scanner->Peek().number()) ||
277 (hour_is_24 && scanner->Peek().number() > 0)) {
278 return DateToken::Invalid();
280 time->Add(scanner->Next().number());
281 if (scanner->SkipSymbol(
'.')) {
282 if (!scanner->Peek().IsNumber() ||
283 (hour_is_24 && scanner->Peek().number() > 0)) {
284 return DateToken::Invalid();
287 time->Add(ReadMilliseconds(scanner->Next()));
291 if (scanner->Peek().IsKeywordZ()) {
294 }
else if (scanner->Peek().IsSymbol(
'+') ||
295 scanner->Peek().IsSymbol(
'-')) {
296 tz->SetSign(scanner->Next().symbol() ==
'+' ? 1 : -1);
297 if (scanner->Peek().IsFixedLengthNumber(4)) {
299 int hourmin = scanner->Next().number();
300 int hour = hourmin / 100;
301 int min = hourmin % 100;
302 if (!TimeComposer::IsHour(hour) || !TimeComposer::IsMinute(min)) {
303 return DateToken::Invalid();
305 tz->SetAbsoluteHour(hour);
306 tz->SetAbsoluteMinute(min);
309 if (!scanner->Peek().IsFixedLengthNumber(2) ||
310 !TimeComposer::IsHour(scanner->Peek().number())) {
311 return DateToken::Invalid();
313 tz->SetAbsoluteHour(scanner->Next().number());
314 if (!scanner->SkipSymbol(
':'))
return DateToken::Invalid();
315 if (!scanner->Peek().IsFixedLengthNumber(2) ||
316 !TimeComposer::IsMinute(scanner->Peek().number())) {
317 return DateToken::Invalid();
319 tz->SetAbsoluteMinute(scanner->Next().number());
322 if (!scanner->Peek().IsEndOfInput())
return DateToken::Invalid();
325 if (tz->IsEmpty()) tz->Set(0);
327 return DateToken::EndOfInput();
333 #endif // V8_DATEPARSER_INL_H_
static bool Parse(Vector< Char > str, FixedArray *output, UnicodeCache *cache)
#define ASSERT(condition)
IN DWORD64 OUT PDWORD64 OUT PIMAGEHLP_SYMBOL64 Symbol