18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_DATEPARSER_H_ 6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_DATEPARSER_H_ 7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/allocation.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/char-predicates.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/parsing/scanner.h" 11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 { 13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal { 14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DateParser : public AllStatic { 16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Parse the string as a date. If parsing succeeds, return true after 18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // filling out the output array as follows (all integers are Smis): 19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [0]: year 20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [1]: month (0 = Jan, 1 = Feb, ...) 21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [2]: day 22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [3]: hour 23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [4]: minute 24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // [5]: second 256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // [6]: millisecond 266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // [7]: UTC offset in seconds, or null value if no timezone specified 27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // If parsing fails, return false (content of output array is not defined). 28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block template <typename Char> 298b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch static bool Parse(Vector<Char> str, FixedArray* output, UnicodeCache* cache); 30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block enum { 326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, UTC_OFFSET, OUTPUT_SIZE 33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Range testing 37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static inline bool Between(int x, int lo, int hi) { 38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo); 39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Indicates a missing value. 42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kNone = kMaxInt; 43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Maximal number of digits used to build the value of a numeral. 453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Remaining digits are ignored. 463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static const int kMaxSignificantDigits = 9; 473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 48a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // InputReader provides basic string parsing and character classification. 49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block template <typename Char> 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class InputReader BASE_EMBEDDED { 51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 528b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch InputReader(UnicodeCache* unicode_cache, Vector<Char> s) 53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block : index_(0), 54a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block buffer_(s), 558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch unicode_cache_(unicode_cache) { 56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Next(); 57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int position() { return index_; } 603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Advance to the next character of the string. 623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void Next() { 633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ch_ = (index_ < buffer_.length()) ? buffer_[index_] : 0; 643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch index_++; 65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Read a string of digits as an unsigned number. Cap value at 683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // kMaxSignificantDigits, but skip remaining digits if the numeral 693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // is longer. 703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int ReadUnsignedNumeral() { 718a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang int n = 0; 723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int i = 0; 733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch while (IsAsciiDigit()) { 743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (i < kMaxSignificantDigits) n = n * 10 + ch_ - '0'; 753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch i++; 763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Next(); 778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return n; 798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 81a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Read a word (sequence of chars. >= 'A'), fill the given buffer with a 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // lower-case prefix, and pad any remainder of the buffer with zeroes. 83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return word length. 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int ReadWord(uint32_t* prefix, int prefix_size) { 85a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int len; 86a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (len = 0; IsAsciiAlphaOrAbove(); Next(), len++) { 879ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick if (len < prefix_size) prefix[len] = AsciiAlphaToLower(ch_); 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = len; i < prefix_size; i++) prefix[i] = 0; 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return len; 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // The skip methods return whether they actually skipped something. 948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang bool Skip(uint32_t c) { 958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang if (ch_ == c) { 968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Next(); 978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return true; 988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang return false; 1008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 102014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline bool SkipWhiteSpace(); 103014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch inline bool SkipParentheses(); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Character testing/classification. Non-ASCII digits are not supported. 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Is(uint32_t c) const { return ch_ == c; } 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsEnd() const { return ch_ == 0; } 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsAsciiDigit() const { return IsDecimalDigit(ch_); } 109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsAsciiAlphaOrAbove() const { return ch_ >= 'A'; } 110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsAsciiSign() const { return ch_ == '+' || ch_ == '-'; } 111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return 1 for '+' and -1 for '-'. 113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); } 114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 116a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index_; 117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Vector<Char> buffer_; 118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block uint32_t ch_; 1198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch UnicodeCache* unicode_cache_; 120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch enum KeywordType { 1233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch INVALID, MONTH_NAME, TIME_ZONE_NAME, TIME_SEPARATOR, AM_PM 1243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 1253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch struct DateToken { 1273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 1283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsInvalid() { return tag_ == kInvalidTokenTag; } 1293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsUnknown() { return tag_ == kUnknownTokenTag; } 1303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsNumber() { return tag_ == kNumberTag; } 1313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsSymbol() { return tag_ == kSymbolTag; } 1323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsWhiteSpace() { return tag_ == kWhiteSpaceTag; } 1333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsEndOfInput() { return tag_ == kEndOfInputTag; } 1343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsKeyword() { return tag_ >= kKeywordTagStart; } 1353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int length() { return length_; } 1373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int number() { 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsNumber()); 1403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return value_; 1413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch KeywordType keyword_type() { 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsKeyword()); 1443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return static_cast<KeywordType>(tag_); 1453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int keyword_value() { 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsKeyword()); 1483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return value_; 1493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch char symbol() { 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsSymbol()); 1523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return static_cast<char>(value_); 1533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsSymbol(char symbol) { 1553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return IsSymbol() && this->symbol() == symbol; 1563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsKeywordType(KeywordType tag) { 1583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return tag_ == tag; 1593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsFixedLengthNumber(int length) { 1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return IsNumber() && length_ == length; 1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsAsciiSign() { 1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return tag_ == kSymbolTag && (value_ == '-' || value_ == '+'); 1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int ascii_sign() { 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(IsAsciiSign()); 1683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return 44 - value_; 1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsKeywordZ() { 1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return IsKeywordType(TIME_ZONE_NAME) && length_ == 1 && value_ == 0; 1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsUnknown(int character) { 1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return IsUnknown() && value_ == character; 1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Factory functions. 1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken Keyword(KeywordType tag, int value, int length) { 1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(tag, length, value); 1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken Number(int value, int length) { 1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kNumberTag, length, value); 1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken Symbol(char symbol) { 1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kSymbolTag, 1, symbol); 1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken EndOfInput() { 1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kEndOfInputTag, 0, -1); 1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken WhiteSpace(int length) { 1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kWhiteSpaceTag, length, -1); 1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken Unknown() { 1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kUnknownTokenTag, 1, -1); 1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateToken Invalid() { 1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return DateToken(kInvalidTokenTag, 0, -1); 1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 198589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch enum TagType { 2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kInvalidTokenTag = -6, 2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kUnknownTokenTag = -5, 2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kWhiteSpaceTag = -4, 2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kNumberTag = -3, 2053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kSymbolTag = -2, 2063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kEndOfInputTag = -1, 2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch kKeywordTagStart = 0 2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken(int tag, int length, int value) 2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : tag_(tag), 2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch length_(length), 2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch value_(value) { } 2133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int tag_; 2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int length_; // Number of characters. 2163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch int value_; 2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 2183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch template <typename Char> 2203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch class DateStringTokenizer { 2213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch public: 2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch explicit DateStringTokenizer(InputReader<Char>* in) 2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : in_(in), next_(Scan()) { } 2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken Next() { 2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken result = next_; 2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_ = Scan(); 2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return result; 2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken Peek() { 2313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return next_; 2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool SkipSymbol(char symbol) { 2343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (next_.IsSymbol(symbol)) { 2353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch next_ = Scan(); 2363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return true; 2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 2393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 240589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken Scan(); 2433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch InputReader<Char>* in_; 2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DateToken next_; 2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch }; 2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static int ReadMilliseconds(DateToken number); 249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // KeywordTable maps names of months, time zones, am/pm to numbers. 251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class KeywordTable : public AllStatic { 252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Look up a word in the keyword table and return an index. 254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // 'pre' contains a prefix of the word, zero-padded to size kPrefixLength 255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // and 'len' is the word length. 256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static int Lookup(const uint32_t* pre, int len); 257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the type of the keyword at index i. 258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static KeywordType GetType(int i) { 259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return static_cast<KeywordType>(array[i][kTypeOffset]); 260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the value of the keyword at index i. 262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static int GetValue(int i) { return array[i][kValueOffset]; } 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kPrefixLength = 3; 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kTypeOffset = kPrefixLength; 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kValueOffset = kTypeOffset + 1; 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kEntrySize = kValueOffset + 1; 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int8_t array[][kEntrySize]; 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class TimeZoneComposer BASE_EMBEDDED { 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TimeZoneComposer() : sign_(kNone), hour_(kNone), minute_(kNone) {} 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void Set(int offset_in_hours) { 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block sign_ = offset_in_hours < 0 ? -1 : 1; 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block hour_ = offset_in_hours * sign_; 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block minute_ = 0; 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetSign(int sign) { sign_ = sign < 0 ? -1 : 1; } 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetAbsoluteHour(int hour) { hour_ = hour; } 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetAbsoluteMinute(int minute) { minute_ = minute; } 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsExpecting(int n) const { 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n); 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsUTC() const { return hour_ == 0 && minute_ == 0; } 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Write(FixedArray* output); 2873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool IsEmpty() { return hour_ == kNone; } 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private: 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int sign_; 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int hour_; 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int minute_; 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class TimeComposer BASE_EMBEDDED { 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block TimeComposer() : index_(0), hour_offset_(kNone) {} 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsEmpty() const { return index_ == 0; } 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsExpecting(int n) const { 2996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block return (index_ == 1 && IsMinute(n)) || 3006ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (index_ == 2 && IsSecond(n)) || 3016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block (index_ == 3 && IsMillisecond(n)); 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Add(int n) { 304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return index_ < kSize ? (comp_[index_++] = n, true) : false; 305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool AddFinal(int n) { 307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (!Add(n)) return false; 308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block while (index_ < kSize) comp_[index_++] = 0; 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return true; 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetHourOffset(int n) { hour_offset_ = n; } 312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Write(FixedArray* output); 313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool IsMinute(int x) { return Between(x, 0, 59); } 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool IsHour(int x) { return Between(x, 0, 23); } 316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool IsSecond(int x) { return Between(x, 0, 59); } 317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch 3183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 3193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static bool IsHour12(int x) { return Between(x, 0, 12); } 3206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static bool IsMillisecond(int x) { return Between(x, 0, 999); } 321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block static const int kSize = 4; 323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comp_[kSize]; 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index_; 325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int hour_offset_; 326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block class DayComposer BASE_EMBEDDED { 329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 3303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch DayComposer() : index_(0), named_month_(kNone), is_iso_date_(false) {} 331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool IsEmpty() const { return index_ == 0; } 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Add(int n) { 3333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (index_ < kSize) { 3343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch comp_[index_] = n; 3353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch index_++; 3363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return true; 3373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 3383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void SetNamedMonth(int n) { named_month_ = n; } 341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block bool Write(FixedArray* output); 3423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch void set_iso_date() { is_iso_date_ = true; } 343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool IsMonth(int x) { return Between(x, 1, 12); } 344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static bool IsDay(int x) { return Between(x, 1, 31); } 345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch private: 347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block static const int kSize = 3; 348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int comp_[kSize]; 349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int index_; 350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int named_month_; 3513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // If set, ensures that data is always parsed in year-month-date order. 3523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_iso_date_; 353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block }; 3543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Tries to parse an ES5 Date Time String. Returns the next token 3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // to continue with in the legacy date string parser. If parsing is 3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // complete, returns DateToken::EndOfInput(). If terminally unsuccessful, 3583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // returns DateToken::Invalid(). Otherwise parsing continues in the 3593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // legacy parser. 3603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch template <typename Char> 3613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch static DateParser::DateToken ParseES5DateTime( 362014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DateStringTokenizer<Char>* scanner, DayComposer* day, TimeComposer* time, 3633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch TimeZoneComposer* tz); 364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 367014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 368014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif // V8_DATEPARSER_H_ 371