1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=4 sw=4 et tw=78:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 : *
7 : * The contents of this file are subject to the Mozilla Public License Version
8 : * 1.1 (the "License"); you may not use this file except in compliance with
9 : * the License. You may obtain a copy of the License at
10 : * http://www.mozilla.org/MPL/
11 : *
12 : * Software distributed under the License is distributed on an "AS IS" basis,
13 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14 : * for the specific language governing rights and limitations under the
15 : * License.
16 : *
17 : * The Original Code is Mozilla Communicator client code, released
18 : * March 31, 1998.
19 : *
20 : * The Initial Developer of the Original Code is
21 : * Netscape Communications Corporation.
22 : * Portions created by the Initial Developer are Copyright (C) 1998
23 : * the Initial Developer. All Rights Reserved.
24 : *
25 : * Contributor(s):
26 : *
27 : * Alternatively, the contents of this file may be used under the terms of
28 : * either of the GNU General Public License Version 2 or later (the "GPL"),
29 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 : * in which case the provisions of the GPL or the LGPL are applicable instead
31 : * of those above. If you wish to allow use of your version of this file only
32 : * under the terms of either the GPL or the LGPL, and not to allow others to
33 : * use your version of this file under the terms of the MPL, indicate your
34 : * decision by deleting the provisions above and replace them with the notice
35 : * and other provisions required by the GPL or the LGPL. If you do not delete
36 : * the provisions above, a recipient may use your version of this file under
37 : * the terms of any one of the MPL, the GPL or the LGPL.
38 : *
39 : * ***** END LICENSE BLOCK ***** */
40 :
41 : #ifndef Parser_h__
42 : #define Parser_h__
43 :
44 : /*
45 : * JS parser definitions.
46 : */
47 : #include "jsversion.h"
48 : #include "jsprvtd.h"
49 : #include "jspubtd.h"
50 : #include "jsatom.h"
51 : #include "jsscript.h"
52 : #include "jswin.h"
53 :
54 : #include "frontend/ParseMaps.h"
55 : #include "frontend/ParseNode.h"
56 :
57 : #define NUM_TEMP_FREELISTS 6U /* 32 to 2048 byte size classes (32 bit) */
58 :
59 : typedef struct BindData BindData;
60 :
61 : namespace js {
62 :
63 : class StaticBlockObject;
64 :
65 : enum FunctionSyntaxKind { Expression, Statement };
66 : enum LetContext { LetExpresion, LetStatement };
67 : enum VarContext { HoistVars, DontHoistVars };
68 :
69 : struct Parser : private AutoGCRooter
70 : {
71 : JSContext *const context; /* FIXME Bug 551291: use AutoGCRooter::context? */
72 : void *tempFreeList[NUM_TEMP_FREELISTS];
73 : TokenStream tokenStream;
74 : void *tempPoolMark; /* initial JSContext.tempLifoAlloc mark */
75 : JSPrincipals *principals; /* principals associated with source */
76 : JSPrincipals *originPrincipals; /* see jsapi.h 'originPrincipals' comment */
77 : StackFrame *const callerFrame; /* scripted caller frame for eval and dbgapi */
78 : JSObject *const callerVarObj; /* callerFrame's varObj */
79 : ParseNodeAllocator allocator;
80 : uint32_t functionCount; /* number of functions in current unit */
81 : ObjectBox *traceListHead; /* list of parsed object for GC tracing */
82 : TreeContext *tc; /* innermost tree context (stack-allocated) */
83 :
84 : /* Root atoms and objects allocated for the parsed tree. */
85 : AutoKeepAtoms keepAtoms;
86 :
87 : /* Perform constant-folding; must be true when interfacing with the emitter. */
88 : bool foldConstants;
89 :
90 : Parser(JSContext *cx, JSPrincipals *prin = NULL, JSPrincipals *originPrin = NULL,
91 : StackFrame *cfp = NULL, bool fold = true);
92 : ~Parser();
93 :
94 : friend void AutoGCRooter::trace(JSTracer *trc);
95 : friend struct TreeContext;
96 :
97 : /*
98 : * Initialize a parser. Parameters are passed on to init tokenStream. The
99 : * compiler owns the arena pool "tops-of-stack" space above the current
100 : * JSContext.tempLifoAlloc mark. This means you cannot allocate from
101 : * tempLifoAlloc and save the pointer beyond the next Parser destructor
102 : * invocation.
103 : */
104 : bool init(const jschar *base, size_t length, const char *filename, unsigned lineno,
105 : JSVersion version);
106 :
107 : void setPrincipals(JSPrincipals *prin, JSPrincipals *originPrin);
108 :
109 : const char *getFilename() const { return tokenStream.getFilename(); }
110 1229793 : JSVersion versionWithFlags() const { return tokenStream.versionWithFlags(); }
111 43103 : JSVersion versionNumber() const { return tokenStream.versionNumber(); }
112 : bool hasXML() const { return tokenStream.hasXML(); }
113 :
114 : /*
115 : * Parse a top-level JS script.
116 : */
117 : ParseNode *parse(JSObject *chain);
118 :
119 : #if JS_HAS_XML_SUPPORT
120 : ParseNode *parseXMLText(JSObject *chain, bool allowList);
121 : #endif
122 :
123 : /*
124 : * Allocate a new parsed object or function container from
125 : * cx->tempLifoAlloc.
126 : */
127 : ObjectBox *newObjectBox(JSObject *obj);
128 :
129 : FunctionBox *newFunctionBox(JSObject *obj, ParseNode *fn, TreeContext *tc);
130 :
131 : /*
132 : * Create a new function object given tree context (tc) and a name (which
133 : * is optional if this is a function expression).
134 : */
135 : JSFunction *newFunction(TreeContext *tc, JSAtom *atom, FunctionSyntaxKind kind);
136 :
137 : void trace(JSTracer *trc);
138 :
139 : /*
140 : * Report a parse (compile) error.
141 : */
142 : inline bool reportErrorNumber(ParseNode *pn, unsigned flags, unsigned errorNumber, ...);
143 :
144 : private:
145 80627913 : ParseNode *allocParseNode(size_t size) {
146 80627913 : JS_ASSERT(size == sizeof(ParseNode));
147 80627913 : return static_cast<ParseNode *>(allocator.allocNode());
148 : }
149 :
150 : /*
151 : * Create a parse node with the given kind and op using the current token's
152 : * atom.
153 : */
154 : ParseNode *atomNode(ParseNodeKind kind, JSOp op);
155 :
156 : public:
157 1141819 : ParseNode *freeTree(ParseNode *pn) { return allocator.freeTree(pn); }
158 23 : void prepareNodeForMutation(ParseNode *pn) { return allocator.prepareNodeForMutation(pn); }
159 :
160 : /* new_ methods for creating parse nodes. These report OOM on context. */
161 80620402 : JS_DECLARE_NEW_METHODS(allocParseNode, inline)
162 :
163 7511 : ParseNode *cloneNode(const ParseNode &other) {
164 7511 : ParseNode *node = allocParseNode(sizeof(ParseNode));
165 7511 : if (!node)
166 0 : return NULL;
167 7511 : PodAssign(node, &other);
168 7511 : return node;
169 : }
170 :
171 : /* Public entry points for parsing. */
172 : ParseNode *statement();
173 : bool recognizeDirectivePrologue(ParseNode *pn, bool *isDirectivePrologueMember);
174 :
175 : /*
176 : * Parse a function body. Pass StatementListBody if the body is a list of
177 : * statements; pass ExpressionBody if the body is a single expression.
178 : */
179 : enum FunctionBodyType { StatementListBody, ExpressionBody };
180 : ParseNode *functionBody(FunctionBodyType type);
181 :
182 : private:
183 : /*
184 : * JS parsers, from lowest to highest precedence.
185 : *
186 : * Each parser must be called during the dynamic scope of a TreeContext
187 : * object, pointed to by this->tc.
188 : *
189 : * Each returns a parse node tree or null on error.
190 : *
191 : * Parsers whose name has a '1' suffix leave the TokenStream state
192 : * pointing to the token one past the end of the parsed fragment. For a
193 : * number of the parsers this is convenient and avoids a lot of
194 : * unnecessary ungetting and regetting of tokens.
195 : *
196 : * Some parsers have two versions: an always-inlined version (with an 'i'
197 : * suffix) and a never-inlined version (with an 'n' suffix).
198 : */
199 : ParseNode *functionStmt();
200 : ParseNode *functionExpr();
201 : ParseNode *statements();
202 :
203 : ParseNode *switchStatement();
204 : ParseNode *forStatement();
205 : ParseNode *tryStatement();
206 : ParseNode *withStatement();
207 : #if JS_HAS_BLOCK_SCOPE
208 : ParseNode *letStatement();
209 : #endif
210 : ParseNode *expressionStatement();
211 : ParseNode *variables(ParseNodeKind kind, StaticBlockObject *blockObj = NULL,
212 : VarContext varContext = HoistVars);
213 : ParseNode *expr();
214 : ParseNode *assignExpr();
215 : ParseNode *condExpr1();
216 : ParseNode *orExpr1();
217 : ParseNode *andExpr1i();
218 : ParseNode *andExpr1n();
219 : ParseNode *bitOrExpr1i();
220 : ParseNode *bitOrExpr1n();
221 : ParseNode *bitXorExpr1i();
222 : ParseNode *bitXorExpr1n();
223 : ParseNode *bitAndExpr1i();
224 : ParseNode *bitAndExpr1n();
225 : ParseNode *eqExpr1i();
226 : ParseNode *eqExpr1n();
227 : ParseNode *relExpr1i();
228 : ParseNode *relExpr1n();
229 : ParseNode *shiftExpr1i();
230 : ParseNode *shiftExpr1n();
231 : ParseNode *addExpr1i();
232 : ParseNode *addExpr1n();
233 : ParseNode *mulExpr1i();
234 : ParseNode *mulExpr1n();
235 : ParseNode *unaryExpr();
236 : ParseNode *memberExpr(JSBool allowCallSyntax);
237 : ParseNode *primaryExpr(TokenKind tt, bool afterDoubleDot);
238 : ParseNode *parenExpr(JSBool *genexp = NULL);
239 :
240 : /*
241 : * Additional JS parsers.
242 : */
243 : enum FunctionType { Getter, Setter, Normal };
244 : bool functionArguments(TreeContext &funtc, FunctionBox *funbox, ParseNode **list);
245 :
246 : ParseNode *functionDef(PropertyName *name, FunctionType type, FunctionSyntaxKind kind);
247 :
248 : ParseNode *unaryOpExpr(ParseNodeKind kind, JSOp op);
249 :
250 : ParseNode *condition();
251 : ParseNode *comprehensionTail(ParseNode *kid, unsigned blockid, bool isGenexp,
252 : ParseNodeKind kind = PNK_SEMI, JSOp op = JSOP_NOP);
253 : ParseNode *generatorExpr(ParseNode *kid);
254 : JSBool argumentList(ParseNode *listNode);
255 : ParseNode *bracketedExpr();
256 : ParseNode *letBlock(LetContext letContext);
257 : ParseNode *returnOrYield(bool useAssignExpr);
258 : ParseNode *destructuringExpr(BindData *data, TokenKind tt);
259 :
260 : bool checkForFunctionNode(PropertyName *name, ParseNode *node);
261 :
262 : ParseNode *identifierName(bool afterDoubleDot);
263 :
264 : #if JS_HAS_XML_SUPPORT
265 : ParseNode *endBracketedExpr();
266 :
267 : ParseNode *propertySelector();
268 : ParseNode *qualifiedSuffix(ParseNode *pn);
269 : ParseNode *qualifiedIdentifier();
270 : ParseNode *attributeIdentifier();
271 : ParseNode *xmlExpr(JSBool inTag);
272 : ParseNode *xmlNameExpr();
273 : ParseNode *xmlTagContent(ParseNodeKind tagkind, JSAtom **namep);
274 : JSBool xmlElementContent(ParseNode *pn);
275 : ParseNode *xmlElementOrList(JSBool allowList);
276 : ParseNode *xmlElementOrListRoot(JSBool allowList);
277 :
278 : ParseNode *starOrAtPropertyIdentifier(TokenKind tt);
279 : ParseNode *propertyQualifiedIdentifier();
280 : #endif /* JS_HAS_XML_SUPPORT */
281 :
282 : bool setAssignmentLhsOps(ParseNode *pn, JSOp op);
283 : bool matchInOrOf(bool *isForOfp);
284 : };
285 :
286 : inline bool
287 9043 : Parser::reportErrorNumber(ParseNode *pn, unsigned flags, unsigned errorNumber, ...)
288 : {
289 : va_list args;
290 9043 : va_start(args, errorNumber);
291 9043 : bool result = tokenStream.reportCompileErrorNumberVA(pn, flags, errorNumber, args);
292 9043 : va_end(args);
293 9043 : return result;
294 : }
295 :
296 : bool
297 : CheckStrictParameters(JSContext *cx, TreeContext *tc);
298 :
299 : bool
300 : DefineArg(ParseNode *pn, JSAtom *atom, unsigned i, TreeContext *tc);
301 :
302 : } /* namespace js */
303 :
304 : /*
305 : * Convenience macro to access Parser.tokenStream as a pointer.
306 : */
307 : #define TS(p) (&(p)->tokenStream)
308 :
309 : #endif /* Parser_h__ */
|