18b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch// Copyright 2011 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifndef V8_DATEPARSER_H_
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define V8_DATEPARSER_H_
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "allocation.h"
328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#include "char-predicates-inl.h"
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
34a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace v8 {
35a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocknamespace internal {
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
37a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass DateParser : public AllStatic {
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Parse the string as a date. If parsing succeeds, return true after
40a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // filling out the output array as follows (all integers are Smis):
41a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [0]: year
42a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [1]: month (0 = Jan, 1 = Feb, ...)
43a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [2]: day
44a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [3]: hour
45a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [4]: minute
46a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [5]: second
476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // [6]: millisecond
486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block  // [7]: UTC offset in seconds, or null value if no timezone specified
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // If parsing fails, return false (content of output array is not defined).
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  template <typename Char>
518b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  static bool Parse(Vector<Char> str, FixedArray* output, UnicodeCache* cache);
52a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
53a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum {
546ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND, UTC_OFFSET, OUTPUT_SIZE
55a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
56a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
58a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Range testing
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline bool Between(int x, int lo, int hi) {
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return static_cast<unsigned>(x - lo) <= static_cast<unsigned>(hi - lo);
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
63a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Indicates a missing value.
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kNone = kMaxInt;
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Maximal number of digits used to build the value of a numeral.
673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Remaining digits are ignored.
683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static const int kMaxSignificantDigits = 9;
693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // InputReader provides basic string parsing and character classification.
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  template <typename Char>
72a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class InputReader BASE_EMBEDDED {
73a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
748b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    InputReader(UnicodeCache* unicode_cache, Vector<Char> s)
75a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        : index_(0),
76a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          buffer_(s),
778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch          unicode_cache_(unicode_cache) {
78a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Next();
79a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
80a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int position() { return index_; }
823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Advance to the next character of the string.
843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    void Next() {
853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ch_ = (index_ < buffer_.length()) ? buffer_[index_] : 0;
863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      index_++;
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Read a string of digits as an unsigned number. Cap value at
903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // kMaxSignificantDigits, but skip remaining digits if the numeral
913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // is longer.
923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int ReadUnsignedNumeral() {
938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      int n = 0;
943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      int i = 0;
953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      while (IsAsciiDigit()) {
963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        if (i < kMaxSignificantDigits) n = n * 10 + ch_ - '0';
973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        i++;
983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        Next();
998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
1008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return n;
1018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
1028a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Read a word (sequence of chars. >= 'A'), fill the given buffer with a
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // lower-case prefix, and pad any remainder of the buffer with zeroes.
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return word length.
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int ReadWord(uint32_t* prefix, int prefix_size) {
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int len;
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (len = 0; IsAsciiAlphaOrAbove(); Next(), len++) {
1099ac36c9faca11611ada13b4054edbaa0738661d0Iain Merrick        if (len < prefix_size) prefix[len] = AsciiAlphaToLower(ch_);
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int i = len; i < prefix_size; i++) prefix[i] = 0;
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return len;
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // The skip methods return whether they actually skipped something.
1168a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    bool Skip(uint32_t c) {
1178a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      if (ch_ == c) {
1188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        Next();
1198a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        return true;
1208a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
1218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return false;
1228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang    }
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool SkipWhiteSpace() {
1258b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      if (unicode_cache_->IsWhiteSpace(ch_)) {
1268a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        Next();
1278a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang        return true;
1288a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      }
1298a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang      return false;
130a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool SkipParentheses() {
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (ch_ != '(') return false;
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int balance = 0;
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      do {
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (ch_ == ')') --balance;
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        else if (ch_ == '(') ++balance;
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        Next();
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } while (balance > 0 && ch_);
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Character testing/classification. Non-ASCII digits are not supported.
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Is(uint32_t c) const { return ch_ == c; }
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsEnd() const { return ch_ == 0; }
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsAsciiDigit() const { return IsDecimalDigit(ch_); }
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsAsciiAlphaOrAbove() const { return ch_ >= 'A'; }
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsAsciiSign() const { return ch_ == '+' || ch_ == '-'; }
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Return 1 for '+' and -1 for '-'.
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int GetAsciiSignValue() const { return 44 - static_cast<int>(ch_); }
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int index_;
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Vector<Char> buffer_;
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uint32_t ch_;
1578b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch    UnicodeCache* unicode_cache_;
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  enum KeywordType {
1613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      INVALID, MONTH_NAME, TIME_ZONE_NAME, TIME_SEPARATOR, AM_PM
1623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
1633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  struct DateToken {
1653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   public:
1663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsInvalid() { return tag_ == kInvalidTokenTag; }
1673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsUnknown() { return tag_ == kUnknownTokenTag; }
1683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsNumber() { return tag_ == kNumberTag; }
1693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsSymbol() { return tag_ == kSymbolTag; }
1703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsWhiteSpace() { return tag_ == kWhiteSpaceTag; }
1713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsEndOfInput() { return tag_ == kEndOfInputTag; }
1723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsKeyword() { return tag_ >= kKeywordTagStart; }
1733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int length() { return length_; }
1753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
1763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int number() {
1773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsNumber());
1783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return value_;
1793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    KeywordType keyword_type() {
1813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsKeyword());
1823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return static_cast<KeywordType>(tag_);
1833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int keyword_value() {
1853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsKeyword());
1863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return value_;
1873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    char symbol() {
1893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsSymbol());
1903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return static_cast<char>(value_);
1913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsSymbol(char symbol) {
1933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return IsSymbol() && this->symbol() == symbol;
1943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsKeywordType(KeywordType tag) {
1963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return tag_ == tag;
1973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
1983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsFixedLengthNumber(int length) {
1993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return IsNumber() && length_ == length;
2003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsAsciiSign() {
2023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return tag_ == kSymbolTag && (value_ == '-' || value_ == '+');
2033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int ascii_sign() {
2053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      ASSERT(IsAsciiSign());
2063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return 44 - value_;
2073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsKeywordZ() {
2093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return IsKeywordType(TIME_ZONE_NAME) && length_ == 1 && value_ == 0;
2103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsUnknown(int character) {
2123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return IsUnknown() && value_ == character;
2133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // Factory functions.
2153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken Keyword(KeywordType tag, int value, int length) {
2163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(tag, length, value);
2173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken Number(int value, int length) {
2193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kNumberTag, length, value);
2203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken Symbol(char symbol) {
2223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kSymbolTag, 1, symbol);
2233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken EndOfInput() {
2253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kEndOfInputTag, 0, -1);
2263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken WhiteSpace(int length) {
2283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kWhiteSpaceTag, length, -1);
2293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken Unknown() {
2313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kUnknownTokenTag, 1, -1);
2323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static DateToken Invalid() {
2343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return DateToken(kInvalidTokenTag, 0, -1);
2353fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
236589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   private:
2383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    enum TagType {
2393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kInvalidTokenTag = -6,
2403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kUnknownTokenTag = -5,
2413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kWhiteSpaceTag = -4,
2423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kNumberTag = -3,
2433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kSymbolTag = -2,
2443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kEndOfInputTag = -1,
2453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      kKeywordTagStart = 0
2463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    };
2473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DateToken(int tag, int length, int value)
2483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        : tag_(tag),
2493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          length_(length),
2503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch          value_(value) { }
2513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int tag_;
2533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int length_;  // Number of characters.
2543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    int value_;
2553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
2563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  template <typename Char>
2583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  class DateStringTokenizer {
2593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   public:
2603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    explicit DateStringTokenizer(InputReader<Char>* in)
2613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        : in_(in), next_(Scan()) { }
2623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DateToken Next() {
2633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DateToken result = next_;
2643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      next_ = Scan();
2653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return result;
2663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DateToken Peek() {
2693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return next_;
2703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
2713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool SkipSymbol(char symbol) {
2723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (next_.IsSymbol(symbol)) {
2733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        next_ = Scan();
2743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return true;
2753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
2763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return false;
2773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    }
278589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
2793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   private:
2803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DateToken Scan();
2813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    InputReader<Char>* in_;
2833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DateToken next_;
2843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  };
2853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
2863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static int ReadMilliseconds(DateToken number);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // KeywordTable maps names of months, time zones, am/pm to numbers.
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class KeywordTable : public AllStatic {
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Look up a word in the keyword table and return an index.
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // 'pre' contains a prefix of the word, zero-padded to size kPrefixLength
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // and 'len' is the word length.
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static int Lookup(const uint32_t* pre, int len);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the type of the keyword at index i.
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static KeywordType GetType(int i) {
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return static_cast<KeywordType>(array[i][kTypeOffset]);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    // Get the value of the keyword at index i.
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static int GetValue(int i) { return array[i][kValueOffset]; }
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kPrefixLength = 3;
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kTypeOffset = kPrefixLength;
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kValueOffset = kTypeOffset + 1;
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kEntrySize = kValueOffset + 1;
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int8_t array[][kEntrySize];
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class TimeZoneComposer BASE_EMBEDDED {
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TimeZoneComposer() : sign_(kNone), hour_(kNone), minute_(kNone) {}
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void Set(int offset_in_hours) {
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      sign_ = offset_in_hours < 0 ? -1 : 1;
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      hour_ = offset_in_hours * sign_;
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      minute_ = 0;
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void SetSign(int sign) { sign_ = sign < 0 ? -1 : 1; }
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void SetAbsoluteHour(int hour) { hour_ = hour; }
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void SetAbsoluteMinute(int minute) { minute_ = minute; }
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsExpecting(int n) const {
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return hour_ != kNone && minute_ == kNone && TimeComposer::IsMinute(n);
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsUTC() const { return hour_ == 0 && minute_ == 0; }
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Write(FixedArray* output);
3253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool IsEmpty() { return hour_ == kNone; }
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   private:
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int sign_;
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int hour_;
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int minute_;
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class TimeComposer BASE_EMBEDDED {
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    TimeComposer() : index_(0), hour_offset_(kNone) {}
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsEmpty() const { return index_ == 0; }
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsExpecting(int n) const {
3376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block      return (index_ == 1 && IsMinute(n)) ||
3386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block             (index_ == 2 && IsSecond(n)) ||
3396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block             (index_ == 3 && IsMillisecond(n));
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Add(int n) {
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return index_ < kSize ? (comp_[index_++] = n, true) : false;
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool AddFinal(int n) {
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (!Add(n)) return false;
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      while (index_ < kSize) comp_[index_++] = 0;
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void SetHourOffset(int n) { hour_offset_ = n; }
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Write(FixedArray* output);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static bool IsMinute(int x) { return Between(x, 0, 59); }
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static bool IsHour(int x) { return Between(x, 0, 23); }
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static bool IsSecond(int x) { return Between(x, 0, 59); }
355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch
3563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   private:
3573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    static bool IsHour12(int x) { return Between(x, 0, 12); }
3586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static bool IsMillisecond(int x) { return Between(x, 0, 999); }
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block    static const int kSize = 4;
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int comp_[kSize];
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int index_;
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int hour_offset_;
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  class DayComposer BASE_EMBEDDED {
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block   public:
3683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    DayComposer() : index_(0), named_month_(kNone), is_iso_date_(false) {}
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool IsEmpty() const { return index_ == 0; }
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Add(int n) {
3713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      if (index_ < kSize) {
3723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        comp_[index_] = n;
3733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        index_++;
3743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch        return true;
3753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      }
3763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      return false;
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    void SetNamedMonth(int n) { named_month_ = n; }
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool Write(FixedArray* output);
3803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    void set_iso_date() { is_iso_date_ = true; }
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static bool IsMonth(int x) { return Between(x, 1, 12); }
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static bool IsDay(int x) { return Between(x, 1, 31); }
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
3843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch   private:
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    static const int kSize = 3;
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int comp_[kSize];
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int index_;
388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int named_month_;
3893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    // If set, ensures that data is always parsed in year-month-date order.
3903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch    bool is_iso_date_;
391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  };
3923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch
3933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // Tries to parse an ES5 Date Time String. Returns the next token
3943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // to continue with in the legacy date string parser. If parsing is
3953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // complete, returns DateToken::EndOfInput(). If terminally unsuccessful,
3963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // returns DateToken::Invalid(). Otherwise parsing continues in the
3973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  // legacy parser.
3983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  template <typename Char>
3993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch  static DateParser::DateToken ParseES5DateTime(
4003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DateStringTokenizer<Char>* scanner,
4013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      DayComposer* day,
4023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      TimeComposer* time,
4033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch      TimeZoneComposer* tz);
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} }  // namespace v8::internal
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // V8_DATEPARSER_H_
410