Ignore:
Timestamp:
Jun 21, 2009, 4:02:13 PM (16 years ago)
Author:
[email protected]
Message:

Bug 26587: Support JSON.parse
<https://bugs.webkit.org/show_bug.cgi?id=26587>

Reviewed by Darin Adler and Cameron Zwarich.

Extend the LiteralParser to support the full strict JSON
grammar, fix a few places where the grammar was incorrectly
lenient. Doesn't yet support the JSON.parse reviver function
but that does not block the JSON.parse functionality itself.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/LiteralParser.cpp

    r44644 r44923  
    2929#include "JSArray.h"
    3030#include "JSString.h"
     31#include "Lexer.h"
    3132#include <wtf/ASCIICType.h>
    3233
    3334namespace JSC {
    34 
    35 static bool isSafeStringCharacter(UChar c)
    36 {
    37     return (c >= ' ' && c <= 0xff && c != '\\') || c == '\t';
    38 }
    3935
    4036LiteralParser::TokenType LiteralParser::Lexer::lex(LiteralParserToken& token)
     
    8581            return TokColon;
    8682        case '"':
    87             return lexString(token);
    88 
     83            if (m_mode == StrictJSON)
     84                return lexString<StrictJSON>(token);
     85            return lexString<NonStrictJSON>(token);
     86        case 't':
     87            if (m_end - m_ptr >= 4 && m_ptr[1] == 'r' && m_ptr[2] == 'u' && m_ptr[3] == 'e') {
     88                m_ptr += 4;
     89                token.type = TokTrue;
     90                token.end = m_ptr;
     91                return TokTrue;
     92            }
     93            break;
     94        case 'f':
     95            if (m_end - m_ptr >= 5 && m_ptr[1] == 'a' && m_ptr[2] == 'l' && m_ptr[3] == 's' && m_ptr[4] == 'e') {
     96                m_ptr += 5;
     97                token.type = TokFalse;
     98                token.end = m_ptr;
     99                return TokFalse;
     100            }
     101            break;
     102        case 'n':
     103            if (m_end - m_ptr >= 4 && m_ptr[1] == 'u' && m_ptr[2] == 'l' && m_ptr[3] == 'l') {
     104                m_ptr += 4;
     105                token.type = TokNull;
     106                token.end = m_ptr;
     107                return TokNull;
     108            }
     109            break;   
    89110        case '-':
    90111        case '0':
     
    103124}
    104125
    105 LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
     126static inline bool isSafeStringCharacter(UChar c)
     127{
     128    return (c >= ' ' && c <= 0xff && c != '\\' && c != '"') || c == '\t';
     129}
     130
     131template <LiteralParser::ParserMode mode> LiteralParser::TokenType LiteralParser::Lexer::lexString(LiteralParserToken& token)
    106132{
    107133    ++m_ptr;
    108     while (m_ptr < m_end && isSafeStringCharacter(*m_ptr) && *m_ptr != '"')
    109         ++m_ptr;
    110     if (m_ptr >= m_end || *m_ptr != '"') {
    111         token.type = TokError;
    112         token.end = ++m_ptr;
     134    const UChar* runStart;
     135    token.stringToken = UString();
     136    do {
     137        runStart = m_ptr;
     138        while (m_ptr < m_end && isSafeStringCharacter(*m_ptr))
     139            ++m_ptr;
     140        if (runStart < m_ptr)
     141            token.stringToken.append(runStart, m_ptr - runStart);
     142        if ((mode == StrictJSON) && m_ptr < m_end && *m_ptr == '\\') {
     143            ++m_ptr;
     144            if (m_ptr >= m_end)
     145                return TokError;
     146            switch (*m_ptr) {
     147                case '"':
     148                    token.stringToken.append('"');
     149                    m_ptr++;
     150                    break;
     151                case '\\':
     152                    token.stringToken.append('\\');
     153                    m_ptr++;
     154                    break;
     155                case '/':
     156                    token.stringToken.append('/');
     157                    m_ptr++;
     158                    break;
     159                case 'b':
     160                    token.stringToken.append('\b');
     161                    m_ptr++;
     162                    break;
     163                case 'f':
     164                    token.stringToken.append('\f');
     165                    m_ptr++;
     166                    break;
     167                case 'n':
     168                    token.stringToken.append('\n');
     169                    m_ptr++;
     170                    break;
     171                case 'r':
     172                    token.stringToken.append('\r');
     173                    m_ptr++;
     174                    break;
     175                case 't':
     176                    token.stringToken.append('\t');
     177                    m_ptr++;
     178                    break;
     179
     180                case 'u':
     181                    if ((m_end - m_ptr) < 5) // uNNNN == 5 characters
     182                        return TokError;
     183                    for (int i = 1; i < 5; i++) {
     184                        if (!isASCIIHexDigit(m_ptr[i]))
     185                            return TokError;
     186                    }
     187                    token.stringToken.append(JSC::Lexer::convertUnicode(m_ptr[1], m_ptr[2], m_ptr[3], m_ptr[4]));
     188                    m_ptr += 5;
     189                    break;
     190
     191                default:
     192                    return TokError;
     193            }
     194        }
     195    } while ((mode == StrictJSON) && m_ptr != runStart && (m_ptr < m_end) && *m_ptr != '"');
     196
     197    if (m_ptr >= m_end || *m_ptr != '"')
    113198        return TokError;
    114     }
     199
    115200    token.type = TokString;
    116201    token.end = ++m_ptr;
     
    152237        ++m_ptr;
    153238        // [0-9]+
    154         if (m_ptr >= m_end && !isASCIIDigit(*m_ptr))
     239        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
    155240            return TokError;
    156241
     
    169254
    170255        // [0-9]+
    171         if (m_ptr >= m_end && !isASCIIDigit(*m_ptr))
     256        if (m_ptr >= m_end || !isASCIIDigit(*m_ptr))
    172257            return TokError;
    173258       
     
    227312                JSObject* object = constructEmptyObject(m_exec);
    228313                objectStack.append(object);
    229                 // fallthrough
     314
     315                TokenType type = m_lexer.next();
     316                if (type == TokString) {
     317                    Lexer::LiteralParserToken identifierToken = m_lexer.currentToken();
     318
     319                    // Check for colon
     320                    if (m_lexer.next() != TokColon)
     321                        return JSValue();
     322                   
     323                    m_lexer.next();
     324                    identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
     325                    stateStack.append(DoParseObjectEndExpression);
     326                    goto startParseExpression;
     327                } else if (type != TokRBrace)
     328                    return JSValue();
     329                m_lexer.next();
     330                lastValue = objectStack.last();
     331                objectStack.removeLast();
     332                break;
    230333            }
    231334            doParseObjectStartExpression:
     
    240343
    241344                    m_lexer.next();
    242                     identifierStack.append(Identifier(m_exec, identifierToken.start + 1, identifierToken.end - identifierToken.start - 2));
     345                    identifierStack.append(Identifier(m_exec, identifierToken.stringToken));
    243346                    stateStack.append(DoParseObjectEndExpression);
    244347                    goto startParseExpression;
    245                 } else if (type != TokRBrace)
     348                } else
    246349                    return JSValue();
    247350                m_lexer.next();
     
    273376                        Lexer::LiteralParserToken stringToken = m_lexer.currentToken();
    274377                        m_lexer.next();
    275                         lastValue = jsString(m_exec, UString(stringToken.start + 1, stringToken.end - stringToken.start - 2));
     378                        lastValue = jsString(m_exec, stringToken.stringToken);
    276379                        break;
    277380                    }
     
    282385                        break;
    283386                    }
     387                    case TokNull:
     388                        m_lexer.next();
     389                        lastValue = jsNull();
     390                        break;
     391
     392                    case TokTrue:
     393                        m_lexer.next();
     394                        lastValue = jsBoolean(true);
     395                        break;
     396
     397                    case TokFalse:
     398                        m_lexer.next();
     399                        lastValue = jsBoolean(false);
     400                        break;
     401
    284402                    default:
    285403                        // Error
Note: See TracChangeset for help on using the changeset viewer.