File indexing completed on 2024-05-12 15:43:32

0001 /*
0002  *  This file is part of the KDE libraries
0003  *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
0004  *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
0005  *  Copyright (C) 2003, 2006, 2007 Apple Inc.
0006  *
0007  *  This library is free software; you can redistribute it and/or
0008  *  modify it under the terms of the GNU Library General Public
0009  *  License as published by the Free Software Foundation; either
0010  *  version 2 of the License, or (at your option) any later version.
0011  *
0012  *  This library is distributed in the hope that it will be useful,
0013  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015  *  Library General Public License for more details.
0016  *
0017  *  You should have received a copy of the GNU Library General Public License
0018  *  along with this library; see the file COPYING.LIB.  If not, write to
0019  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020  *  Boston, MA 02110-1301, USA.
0021  *
0022  */
0023 
0024 #include "Parser.h"
0025 
0026 #include "lexer.h"
0027 #include "nodes.h"
0028 #include <wtf/HashSet.h>
0029 
0030 #ifdef KJS_VERBOSE
0031 #include <stdio.h>
0032 #endif
0033 
0034 extern int kjsyyparse();
0035 
0036 namespace KJS
0037 {
0038 
0039 Parser::Parser()
0040     : m_sourceId(0)
0041 {
0042 }
0043 
0044 PassRefPtr<ProgramNode> Parser::parseProgram(const UString &sourceURL, int startingLineNumber,
0045         const UChar *code, unsigned length,
0046         int *sourceId, int *errLine, UString *errMsg)
0047 {
0048     parse(sourceURL, startingLineNumber, code, length, sourceId, errLine, errMsg);
0049     return m_progNode.release();
0050 }
0051 
0052 static HashSet<Node *> *nodeCycles;
0053 
0054 void Parser::noteNodeCycle(Node *node)
0055 {
0056     if (!nodeCycles) {
0057         nodeCycles = new HashSet<Node *>;
0058     }
0059     nodeCycles->add(node);
0060 }
0061 
0062 void Parser::removeNodeCycle(Node *node)
0063 {
0064     ASSERT(nodeCycles);
0065     nodeCycles->remove(node);
0066 }
0067 
0068 static void clearNewNodes()
0069 {
0070     if (nodeCycles) {
0071         for (HashSet<Node *>::iterator it = nodeCycles->begin(); it != nodeCycles->end(); ++it) {
0072             (*it)->breakCycle();
0073         }
0074         delete nodeCycles;
0075         nodeCycles = nullptr;
0076     }
0077     Node::clearNewNodes();
0078 }
0079 
0080 PassRefPtr<FunctionBodyNode> Parser::parseFunctionBody(const UString &sourceURL, int startingLineNumber,
0081         const UChar *code, unsigned length,
0082         int *sourceId, int *errLine, UString *errMsg)
0083 {
0084     parse(sourceURL, startingLineNumber, code, length, sourceId, errLine, errMsg);
0085     return m_progNode.release();
0086 }
0087 
0088 void Parser::parse(const UString &sourceURL, int startingLineNumber,
0089                    const UChar *code, unsigned length,
0090                    int *sourceId, int *errLine, UString *errMsg)
0091 {
0092     pushFunctionContext(0);
0093 
0094     ASSERT(!m_progNode);
0095 
0096     if (errLine) {
0097         *errLine = -1;
0098     }
0099     if (errMsg) {
0100         *errMsg = nullptr;
0101     }
0102 
0103     Lexer &lexer = KJS::lexer();
0104 
0105     lexer.setCode(sourceURL, startingLineNumber, code, length);
0106     m_sourceId++;
0107     if (sourceId) {
0108         *sourceId = m_sourceId;
0109     }
0110 
0111     // Enable this and the #define YYDEBUG in grammar.y to debug a parse error
0112     //extern int kjsyydebug;
0113     //kjsyydebug=1;
0114 
0115     int parseError = kjsyyparse();
0116 
0117     bool lexError = lexer.sawError();
0118     lexer.clear();
0119 
0120     clearNewNodes();
0121 
0122     if (parseError || lexError) {
0123         if (errLine) {
0124             *errLine = lexer.lineNo();
0125         }
0126         if (errMsg) {
0127             *errMsg = "Parse error";
0128         }
0129         m_progNode = nullptr;
0130         return;
0131     }
0132 
0133 #ifdef KJS_VERBOSE
0134     fprintf(stderr, "%s\n", m_progNode->toString().ascii());
0135 #endif
0136 }
0137 
0138 void Parser::didFinishParsing(PassRefPtr<ProgramNode> progNode)
0139 {
0140     m_progNode = progNode;
0141 }
0142 
0143 Parser &parser()
0144 {
0145     // ASSERT(JSLock::currentThreadIsHoldingLock());
0146 
0147     static Parser staticParser;
0148     return staticParser;
0149 }
0150 
0151 } // namespace KJS