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