Merge remote-tracking branch 'redux/master' into sh4-pool
[tamarin-stm.git] / eval / eval-parse.cpp
blobbd3570e9b2f243c38361c943128f4f4414861f56
1 /* -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */
2 /* vi: set ts=4 sw=4 expandtab: (add to ~/.vimrc: set modeline modelines=5) */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is [Open Source Virtual Machine.].
18 * The Initial Developer of the Original Code is
19 * Adobe System Incorporated.
20 * Portions created by the Initial Developer are Copyright (C) 2008
21 * the Initial Developer. All Rights Reserved.
23 * Contributor(s):
24 * Adobe AS3 Team
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "avmplus.h"
42 #ifdef VMCFG_EVAL
44 #include "eval.h"
46 namespace avmplus
48 namespace RTC
52 static const struct TokenMapping {
53 unsigned isOpAssign:1;
54 unsigned isMultiplicative:1;
55 unsigned isAdditive:1;
56 unsigned isRelational:1;
57 unsigned isEquality:1;
58 unsigned isShift:1;
59 unsigned unaryOp:8;
60 unsigned binaryOp:8;
63 const Parser::TokenMapping Parser::tokenMapping[] = {
64 { 0, 0, 0, 1, 0, 0, 0, OPR_as }, // T_As
65 { 0, 0, 0, 0, 0, 0, 0, OPR_assign }, // T_Assign,
66 { 0, 0, 0, 0, 0, 0, 0, OPR_bitwiseAnd }, // T_BitwiseAnd,
67 { 1, 0, 0, 0, 0, 0, 0, OPR_bitwiseAnd }, // T_BitwiseAndAssign,
68 { 0, 0, 0, 0, 0, 0, OPR_bitwiseNot, 0 }, // T_BitwiseNot,
69 { 0, 0, 0, 0, 0, 0, 0, OPR_bitwiseOr }, // T_BitwiseOr,
70 { 1, 0, 0, 0, 0, 0, 0, OPR_bitwiseOr }, // T_BitwiseOrAssign,
71 { 0, 0, 0, 0, 0, 0, 0, OPR_bitwiseXor }, // T_BitwiseXor,
72 { 1, 0, 0, 0, 0, 0, 0, OPR_bitwiseXor }, // T_BitwiseXorAssign,
73 { 0, 0, 0, 0, 0, 0, OPR_delete, 0 }, // T_Delete,
74 { 0, 1, 0, 0, 0, 0, 0, OPR_divide }, // T_Divide,
75 { 1, 0, 0, 0, 0, 0, 0, OPR_divide }, // T_DivideAssign,
76 { 0, 0, 0, 0, 1, 0, 0, OPR_equal }, // T_Equal,
77 { 0, 0, 0, 1, 0, 0, 0, OPR_greater }, // T_GreaterThan,
78 { 0, 0, 0, 1, 0, 0, 0, OPR_greaterOrEqual }, // T_GreaterThanOrEqual,
79 { 0, 0, 0, 1, 0, 0, 0, OPR_in }, // T_In,
80 { 0, 0, 0, 1, 0, 0, 0, OPR_instanceof }, // T_InstanceOf,
81 { 0, 0, 0, 1, 0, 0, 0, OPR_is }, // T_Is,
82 { 0, 0, 0, 0, 0, 1, 0, OPR_leftShift }, // T_LeftShift,
83 { 1, 0, 0, 0, 0, 0, 0, OPR_leftShift }, // T_LeftShiftAssign,
84 { 0, 0, 0, 1, 0, 0, 0, OPR_less }, // T_LessThan,
85 { 0, 0, 0, 1, 0, 0, 0, OPR_lessOrEqual }, // T_LessThanOrEqual,
86 { 0, 0, 0, 0, 0, 0, 0, OPR_logicalAnd }, // T_LogicalAnd,
87 { 1, 0, 0, 0, 0, 0, 0, OPR_logicalAnd }, // T_LogicalAndAssign,
88 { 0, 0, 0, 0, 0, 0, 0, OPR_logicalOr }, // T_LogicalOr,
89 { 1, 0, 0, 0, 0, 0, 0, OPR_logicalOr }, // T_LogicalOrAssign,
90 { 0, 0, 1, 0, 0, 0, OPR_unminus, OPR_minus }, // T_Minus,
91 { 1, 0, 0, 0, 0, 0, 0, OPR_minus }, // T_MinusAssign,
92 { 0, 0, 0, 0, 0, 0, OPR_preDecr, OPR_postDecr }, // T_MinusMinus, note binop slot encodes postfix form
93 { 0, 1, 0, 0, 0, 0, 0, OPR_multiply }, // T_Multiply,
94 { 1, 0, 0, 0, 0, 0, 0, OPR_multiply }, // T_MultiplyAssign,
95 { 0, 0, 0, 0, 0, 0, OPR_not, 0 }, // T_Not,
96 { 0, 0, 0, 0, 1, 0, 0, OPR_notEqual }, // T_NotEqual,
97 { 0, 0, 1, 0, 0, 0, OPR_unplus, OPR_plus }, // T_Plus,
98 { 1, 0, 0, 0, 0, 0, 0, OPR_plus }, // T_PlusAssign,
99 { 0, 0, 0, 0, 0, 0, OPR_preIncr, OPR_postIncr }, // T_PlusPlus, note binop slot encodes postfix form
100 { 0, 1, 0, 0, 0, 0, 0, OPR_remainder }, // T_Remainder,
101 { 1, 0, 0, 0, 0, 0, 0, OPR_remainder }, // T_RemainderAssign,
102 { 0, 0, 0, 0, 0, 1, 0, OPR_rightShift }, // T_RightShift,
103 { 1, 0, 0, 0, 0, 0, 0, OPR_rightShift }, // T_RightShiftAssign,
104 { 0, 0, 0, 0, 1, 0, 0, OPR_strictEqual }, // T_StrictEqual,
105 { 0, 0, 0, 0, 1, 0, 0, OPR_strictNotEqual }, // T_StrictNotEqual,
106 { 0, 0, 0, 0, 0, 0, OPR_typeof, 0 }, // T_TypeOf,
107 { 0, 0, 0, 0, 1, 0, 0, OPR_rightShiftUnsigned }, // T_UnsignedRightShift,
108 { 1, 0, 0, 0, 0, 0, 0, OPR_rightShiftUnsigned }, // T_UnsignedRightShiftAssign,
109 { 0, 0, 0, 0, 0, 0, OPR_void, 0 } // T_Void,
112 Parser::BindingRib::BindingRib(Allocator* allocator, BindingRib* next, RibType tag)
113 : bindings(allocator)
114 , functionDefinitions(allocator)
115 , namespaces(allocator)
116 , openNamespaces(allocator)
117 , tag(tag)
118 , uses_finally(false)
119 , uses_catch(false)
120 , uses_arguments(false)
121 , uses_dxns(false)
122 , is_void(false)
123 , optional_arguments(false)
124 , next(next)
128 Parser::Parser(Compiler* compiler, Lexer* lexer, uint32_t first_line)
129 : compiler(compiler)
130 , allocator(compiler->allocator)
131 , line_offset(first_line-1)
132 , topRib(NULL)
133 , configNamespaces(NULL)
134 , configBindings(NULL)
135 , lexerStack(NULL)
136 , lexer(lexer)
137 , T0(T_LAST)
138 , T1(T_LAST)
139 , LP(0)
140 , L0(0)
141 , L1(0)
142 , included_input(NULL)
146 Program* Parser::parse()
148 start();
149 return program();
153 * <program> ::= <package>* <directive>*
155 Program* Parser::program()
157 addConfigNamespace(compiler->SYM_CONFIG);
158 pushBindingRib(RIB_Program);
159 addNamespaceBinding(compiler->SYM_AS3, ALLOC(LiteralString, (compiler->intern("http://adobe.com/AS3/2006/builtin"), 0)));
160 while (hd() == T_Package)
161 package();
162 Seq<Stmt*>* stmts = directives(SFLAG_Toplevel);
163 Program* prog = ALLOC(Program, (topRib->bindings.get(), topRib->functionDefinitions.get(), topRib->namespaces.get(), topRib->openNamespaces.get(), stmts));
164 popBindingRib();
165 return prog;
168 // FIXME: must open the package namespaces inside the package
169 // FIXME: must record the package name as a compound name prefix inside the package
170 // FIXME: must record that we're inside a package so that namespace qualifiers can be checked
171 void Parser::package()
173 SeqBuilder<Str*> name(allocator);
174 eat(T_Package);
175 while (hd() == T_Identifier) {
176 name.addAtEnd(identValue());
177 eat(T_Identifier);
178 if (!match(T_Dot))
179 break;
181 eat(T_LeftBrace);
182 directives(SFLAG_Package);
183 eat(T_RightBrace);
186 Seq<Stmt*>* Parser::directives(int flags, Seq<Stmt*>** out_instance_init)
188 (void)out_instance_init; // Accumulator of statement directives for instance initializer.
189 SeqBuilder<Stmt*> stmts(allocator); // Accumulator of statement directives. In a class body, this is also the class_init.
191 // Directive parser machine state.
193 SeqBuilder<Expr*> metadatas(allocator); // Metadata expressions, in order
194 QualifiedName* configname; // Non-NULL if we have a config name, will also appear in metadatas
195 Qualifier qual; // ns / native / static / prototype / dynamic / override / committed metadata
196 bool metadata; // We're still looking at metadata and have not moved to qualifiers
197 bool committed; // We're committed to parsing a directive
199 // Working storage
201 Expr* e; // Pending expression on entry to expr_statement
203 next_directive:
204 metadatas.clear();
205 configname = NULL;
206 qual = Qualifier();
207 metadata = true;
208 committed = false;
209 e = NULL;
211 switch (hd()) {
212 //case T_Import: goto import_directive;
213 case T_Include: goto include_directive;
214 //case T_Use: goto use_directive;
215 //case T_Package: goto package_directive;
216 case T_Identifier: {
217 if (identValue() == compiler->SYM_config && hd2() == T_Namespace && L0 == L1)
218 goto config_namespace_directive;
219 goto continue_directive;
221 default: goto continue_directive;
224 continue_directive:
225 if (hd() == T_RightBrace || hd() == T_EOS) {
226 if (committed)
227 compiler->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED);
228 addExprStatements(&stmts, metadatas.get());
229 goto finish;
232 switch (hd())
234 case T_LeftBracket: goto array_metadata;
235 case T_BreakLeftAngle: goto xml_metadata;
236 case T_Private: goto special_namespace_qualifier;
237 case T_Protected: goto special_namespace_qualifier;
238 case T_Public: goto special_namespace_qualifier;
239 case T_Internal: goto special_namespace_qualifier;
240 case T_Dynamic: goto dynamic_qualifier;
241 case T_Final: goto final_qualifier;
242 case T_Native: goto native_qualifier;
243 case T_Override: goto override_qualifier;
244 case T_Static: goto static_qualifier;
245 case T_Namespace: goto namespace_directive;
246 case T_Const: goto const_or_var_directive;
247 case T_Var: goto const_or_var_directive;
248 case T_Function: goto function_directive;
249 case T_Class: goto class_directive;
250 case T_Interface: goto interface_directive;
251 case T_Identifier: goto configname_or_namespacename_or_statement;
252 default: goto statement;
255 xml_metadata: {
256 // Could be xml-literal metadata or expression statement.
258 // Must parse full expression here in case it's not metadata, eg,
259 // <foo></foo> + "bar"
260 // is a valid statement.
261 if (!metadata)
262 compiler->syntaxError(position(), SYNTAXERR_METADATA_NOT_ALLOWED);
263 e = commaExpression(0);
264 if (e->tag() == TAG_literalXml) {
265 committed = true;
266 metadatas.addAtEnd(e);
267 e = NULL;
268 goto continue_directive;
271 // Not metadata after all
272 goto expr_statement;
275 array_metadata: {
276 // Could be array-literal metadata or expression statement.
278 // Must parse full expression here in case it's not metadata, eg,
279 // [native(a,b,c)] + " = " + x
280 // or
281 // [a,b,c] = 10
282 // are valid statements (or will be).
283 if (!metadata)
284 compiler->syntaxError(position(), SYNTAXERR_METADATA_NOT_ALLOWED);
285 e = commaExpression(0);
286 if (e->tag() == TAG_literalArray) {
287 committed = true;
288 metadatas.addAtEnd(e);
289 e = NULL;
290 goto continue_directive;
293 // Not metadata after all
294 goto expr_statement;
297 configname_or_namespacename_or_statement: {
298 // Here we're looking at some identifier. It can be the start of: a config name
299 // reference (always of the form NS::v), a namespace reference (anything from a
300 // simple unqualified name through a string of namespace qualifiers and finally a
301 // name), a labeled statement, or an expression statement. The special names
302 // private, public, protected, and internal do not appear.
304 // If it's followed by a colon then it's a label. Otherwise we must parse it as
305 // a full comma expression and then start disambiguating.
307 // In the AST, a simple unqualified name is a QualifiedName with a NULL qualifier
308 // and a SimpleName for a name.
310 if (hd2() == T_Colon)
311 goto statement; // labeled statement
312 e = commaExpression(0);
313 if (e->tag() != TAG_qualifiedName)
314 goto expr_statement;
315 if (newline())
316 goto configname_or_statement;
317 if (isConfigReference(e))
318 goto configname;
319 goto namespace_or_statement;
321 configname_or_statement:
322 if (!isConfigReference(e))
323 goto expr_statement;
324 goto configname;
326 configname:
327 if (!metadata)
328 compiler->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED);
329 if (configname != NULL) {
330 // Flush up to and including previous configname
331 while (!metadatas.isEmpty()) {
332 Expr* p = metadatas.dequeue();
333 if (p == NULL)
334 break; // Oops - really an error
335 stmts.addAtEnd(ALLOC(ExprStmt, (e->pos, e)));
336 if (e == configname)
337 break;
340 configname = (QualifiedName*)e;
341 metadatas.addAtEnd(e);
342 e = NULL;
343 if (!newline())
344 committed = true;
345 goto continue_directive;
347 expr_statement:
348 // When we get here there must be an expr in e that is
349 // an expression statement. We must not be committed,
350 // but there can be metadatas - those are also expression
351 // statements that were newline-terminated. We have not
352 // consumed any semicolon at the end of the current
353 // expression statement.
354 AvmAssert(e != NULL);
355 if (committed)
356 compiler->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED);
357 semicolon();
358 metadatas.addAtEnd(e);
359 addExprStatements(&stmts, metadatas.get());
360 goto next_directive;
362 namespace_or_statement:
363 AvmAssert(!newline());
364 if (!isNamespaceReference(e))
365 goto expr_statement;
366 if (qual.tag != QUAL_none)
367 compiler->syntaxError(position(), SYNTAXERR_DUPLICATE_QUALIFIER);
368 qual.tag = QUAL_name;
369 qual.name = (QualifiedName*)e;
370 committed = true;
371 metadata = false;
372 e = NULL;
373 goto continue_directive;
376 special_namespace_qualifier: {
377 // The namespace qualifiers public, private, protected, and internal can be used
378 // either by themselves as qualifiers or as part of a qualified name, eg,
379 // 'internal::foo'. In the latter case, we also risk looking at an expression
380 // statement, eg, 'internal::foo() + fnord'. However, the namespace qualifiers
381 // are not themselves valid expressions, so we can't blithely parse an expression
382 // here. We must instead look ahead: if we're seeing '::' next then we can parse
383 // an expression and then disambiguate between a qualified namespace name or
384 // an expression statement, otherwise we take the keyword to be a qualifier.
386 // Configuration names do not appear here because private, public, protected, and
387 // internal never denote a configuration namespace.
389 Token tok = hd();
390 QualifierTag t = QUAL_none;
391 if (hd2() != T_DoubleColon) {
392 next();
393 switch (tok) {
394 case T_Private: t = QUAL_private; break;
395 case T_Public: t = QUAL_public; break;
396 case T_Protected: t = QUAL_protected; break;
397 case T_Internal: t = QUAL_internal; break;
399 goto consumed_special_namespace_qualifier;
403 Expr* e = commaExpression(0);
404 if (e->tag() != TAG_qualifiedName || newline()) {
405 if (committed)
406 compiler->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED);
407 // Expression statement
408 semicolon();
409 metadatas.addAtEnd(e);
410 addExprStatements(&stmts, metadatas.get());
411 goto next_directive;
414 t = QUAL_name;
415 qual.name = (QualifiedName*)e;
416 goto consumed_special_namespace_qualifier;
419 consumed_special_namespace_qualifier:
420 if (qual.tag != QUAL_none)
421 compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "private");
422 qual.tag = t;
423 committed = true;
424 metadata = false;
425 goto continue_directive;
428 dynamic_qualifier: {
429 qual.is_dynamic++;
430 goto consume_simple_qualifier;
433 final_qualifier: {
434 qual.is_final++;
435 goto consume_simple_qualifier;
438 native_qualifier: {
439 qual.is_native++;
440 goto consume_simple_qualifier;
443 override_qualifier: {
444 qual.is_override++;
445 goto consume_simple_qualifier;
448 static_qualifier: {
449 qual.is_static++;
450 goto consume_simple_qualifier;
453 consume_simple_qualifier: {
454 next();
455 committed = true;
456 metadata = false;
457 goto continue_directive;
460 config_namespace_directive: {
461 // No attributes or metadata will have been parsed
462 eat(T_Identifier);
463 eat(T_Namespace);
464 if (!(flags & SFLAG_Toplevel))
465 compiler->syntaxError(position(), SYNTAXERR_CONFIG_NAMESPACE_NOT_ALLOWED);
466 configNamespaceDefinition(flags, evaluateConfigReference(configname));
467 goto next_directive;
470 include_directive: {
471 // No attributes or metadata will have been parsed
472 includeDirective();
473 goto next_directive;
476 namespace_directive: {
477 checkSimpleAttributes(&qual);
478 if (!(flags & (SFLAG_Function|SFLAG_Toplevel|SFLAG_Package|SFLAG_Class)))
479 compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_NAMESPACE);
480 if (qual.is_dynamic || qual.is_final || qual.is_native || qual.is_override || qual.is_static)
481 compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_NAMESPACE);
482 namespaceDefinition(evaluateConfigReference(configname), flags, &qual);
483 goto next_directive;
486 const_or_var_directive: {
487 checkSimpleAttributes(&qual);
488 if (flags & SFLAG_Interface)
489 compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_IN_INTERFACE);
490 if (qual.is_dynamic || qual.is_final || qual.is_native || qual.is_override ||
491 (qual.is_static && !(flags & SFLAG_Class)) ||
492 (qual.tag != QUAL_none && !(flags & (SFLAG_Toplevel|SFLAG_Package|SFLAG_Class))))
493 compiler->syntaxError(position(), SYNTAXERR_QUALIFIER_NOT_ALLOWED);
494 // FIXME: if inside a class, the statement goes into the instance initializer ... except if static...
495 // FIXME: if const, and at the top level, and the namespace is a config namespace, evaluate and define a config const
496 stmts.addAtEnd(variableDefinition(evaluateConfigReference(configname), &qual));
497 goto next_directive;
500 function_directive: {
501 checkSimpleAttributes(&qual);
502 if (qual.is_dynamic ||
503 ((qual.is_final || qual.is_override || qual.is_static) && !(flags & SFLAG_Class)) ||
504 (qual.tag != QUAL_none && !(flags & (SFLAG_Toplevel|SFLAG_Package|SFLAG_Class))))
505 compiler->syntaxError(position(), SYNTAXERR_QUALIFIER_NOT_ALLOWED);
506 // FIXME: if inside a class or interface, we want to pick up the methods.
507 // FIXME: if inside a class, it goes into the instance... except if static...
508 functionDefinition(evaluateConfigReference(configname), &qual, (flags & SFLAG_Class) != 0, (flags & SFLAG_Interface) == 0);
509 goto next_directive;
512 class_directive: {
513 checkSimpleAttributes(&qual);
514 if (!(flags & (SFLAG_Toplevel|SFLAG_Package)))
515 compiler->syntaxError(position(), SYNTAXERR_CLASS_NOT_ALLOWED);
516 if (qual.is_native || qual.is_override || qual.is_static)
517 compiler->syntaxError(position(), SYNTAXERR_QUALIFIER_NOT_ALLOWED);
518 classDefinition(evaluateConfigReference(configname), flags, &qual);
519 goto next_directive;
522 interface_directive: {
523 checkSimpleAttributes(&qual);
524 if (!(flags & (SFLAG_Toplevel|SFLAG_Package)))
525 compiler->syntaxError(position(), SYNTAXERR_INTERFACE_NOT_ALLOWED);
526 if (qual.is_dynamic || qual.is_final || qual.is_native || qual.is_override || qual.is_static ||
527 (qual.tag != QUAL_none && qual.tag != QUAL_public))
528 compiler->syntaxError(position(), SYNTAXERR_QUALIFIER_NOT_ALLOWED);
529 interfaceDefinition(evaluateConfigReference(configname), flags, &qual);
530 goto next_directive;
533 statement: {
534 AvmAssert(e == NULL);
535 if (committed)
536 compiler->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED);
537 addExprStatements(&stmts, metadatas.get());
538 if (flags & SFLAG_Interface)
539 compiler->syntaxError(position(), SYNTAXERR_STMT_IN_INTERFACE);
540 // FIXME: is this test right?
541 if (qual.tag != QUAL_none)
542 compiler->syntaxError(position(), SYNTAXERR_ILLEGAL_STMT);
543 if (configname != NULL && hd() != T_LeftBrace)
544 compiler->syntaxError(position(), SYNTAXERR_CONFIG_PROHIBITED);
545 stmts.addAtEnd(statement(evaluateConfigReference(configname)));
546 goto next_directive;
549 finish:
550 return stmts.get();
553 void Parser::checkSimpleAttributes(Qualifier* qual)
555 // FIXME: if the defining keyword is not const, and a namespace is present,
556 // then that namespace must not be a config namespace.
557 if ((qual->is_dynamic > 1 || qual->is_final > 1 || qual->is_native > 1 || qual->is_override > 1 || qual->is_static > 1) ||
558 (qual->is_static + qual->is_final > 1) ||
559 (qual->is_static + qual->is_override > 1) ||
560 (qual->is_static + qual->is_dynamic > 1))
561 compiler->syntaxError(position(), SYNTAXERR_QUALIFIER_NOT_ALLOWED);
564 // FIXME: This is incorrect because QualifiedName currently does not admit a::b::c
565 bool Parser::isNamespaceReference(Expr* e)
567 if (e->tag() != TAG_qualifiedName)
568 return false;
569 QualifiedName* qn = (QualifiedName*)e;
570 if (qn->name->tag() != TAG_simpleName)
571 return false;
572 if (qn->qualifier != NULL && qn->qualifier->tag() != TAG_simpleName)
573 return false;
574 return true;
577 void Parser::addExprStatements(SeqBuilder<Stmt*>* stmts, Seq<Expr*>* exprs)
579 while (exprs != NULL) {
580 Expr* e = exprs->hd;
581 exprs = exprs->tl;
582 stmts->addAtEnd(ALLOC(ExprStmt, (e->pos, e)));
586 // Qualifiers are known to be appropriate for 'class'
587 void Parser::classDefinition(bool config, int /*flags*/, Qualifier* qual)
589 (void)config;
590 // FIXME: pick up the methods plus all other flags somehow, these are available from the binding ribs
591 // Maybe time to package them up conveniently (FunctionDefinition needs it too).
592 eat(T_Class);
593 uint32_t pos = position();
594 Str* name = identifier();
595 checkNoShadowingOfConfigNamespaces(pos, name);
596 Str* extends = NULL;
597 SeqBuilder<Str*> implements(allocator);
598 if (hd() == T_Identifier && identValue() == compiler->SYM_extends) {
599 next();
600 extends = identifier();
602 if (hd() == T_Identifier && identValue() == compiler->SYM_implements) {
603 next();
604 do {
605 implements.addAtEnd(identifier());
606 } while (match(T_Comma));
608 eat(T_LeftBrace);
609 pushBindingRib(RIB_Class);
610 pushBindingRib(RIB_Instance);
611 Seq<Stmt*>* instance_init = NULL;
612 Seq<Stmt*>* class_init = directives(SFLAG_Class, &instance_init);
613 popBindingRib();
614 popBindingRib();
615 eat(T_RightBrace);
616 addClass(ALLOC(ClassDefn, (qual, name, extends, implements.get(), class_init, instance_init)));
619 void Parser::interfaceDefinition(bool config, int /*flags*/, Qualifier* qual)
621 (void)config;
622 // FIXME: pick up the methods somehow, these are available from the binding ribs
623 eat(T_Interface);
624 uint32_t pos = position();
625 Str* name = identifier();
626 checkNoShadowingOfConfigNamespaces(pos, name);
627 SeqBuilder<Str*> extends(allocator);
628 if (hd() == T_Identifier && identValue() == compiler->SYM_extends) {
629 do {
630 extends.addAtEnd(identifier());
631 } while (match(T_Comma));
633 eat(T_LeftBrace);
634 pushBindingRib(RIB_Instance);
635 directives(SFLAG_Interface);
636 popBindingRib();
637 eat(T_RightBrace);
638 addInterface(ALLOC(InterfaceDefn, (qual, name, extends.get())));
641 // Namespaces are:
642 // - allowed at the top level of classes
643 // - allowed in functions and blocks
644 // - hoisted to the function level and scoped to the entire function
645 // - initialized on entry to the function (so defining them in blocks is pretty silly)
647 // FIXME: don't discard the qualifier in namespace definitions
649 void Parser::namespaceDefinition(bool config, int flags, Qualifier* /*qual*/)
651 (void)flags;
652 uint32_t pos = position();
653 eat(T_Namespace);
654 Str* name = identifier();
655 checkNoShadowingOfConfigNamespaces(pos, name);
656 Expr* value = NULL;
657 if (match(T_Assign)) {
658 if (hd() != T_Identifier && hd() != T_StringLiteral)
659 compiler->syntaxError(pos, SYNTAXERR_ILLEGAL_NAMESPACE);
660 value = primaryExpression();
662 semicolon();
663 if (config)
664 addNamespaceBinding(name, value);
667 void Parser::configNamespaceDefinition(int flags, bool config)
669 (void)flags;
670 (void)config;
673 void Parser::includeDirective()
675 eat(T_Include);
676 Str* newFile = stringValue();
677 uint32_t pos = position();
678 eat(T_StringLiteral);
679 semicolon();
680 if (!compiler->origin_is_file)
681 compiler->syntaxError(pos, SYNTAXERR_INCLUDE_ORIGIN);
683 // The current lexer state - including the state variables that are a part of the
684 // parser object - gets pushed onto a stack, a new lexer is created for the new
685 // input, and is installed. Then we return, the caller must continue parsing as
686 // if nothing had happened. When the current lexer sees EOS it calls onEOS()
687 // on the parser, which pops the lexer stack and generates a token from the popped
688 // lexer. The normal token processing path does not slow down at all and the
689 // machinery is almost entirely transparent to the parser.
691 pushLexerState();
692 T0 = T1 = T_LAST;
693 LP = L0 = L1 = 0;
695 uint32_t inputlen;
696 const wchar* input = compiler->context->readFileForEval(compiler->filename, newFile->s, &inputlen);
697 if (input == NULL)
698 compiler->syntaxError(pos, SYNTAXERR_INCLUDE_INACCESSIBLE);
700 included_input = input; // freed in onEOS below
701 #ifdef DEBUG
702 bool doTrace = lexer->getTrace();
703 #endif
704 lexer = ALLOC(Lexer, (compiler, input, inputlen));
705 #ifdef DEBUG
706 if (doTrace) lexer->trace();
707 #endif
708 start();
711 Token Parser::onEOS(uint32_t* linep, TokenValue* valuep)
713 if (lexerStack == NULL)
714 return T_EOS;
716 compiler->context->freeInput(included_input);
717 popLexerState();
719 if (T0 == T_LAST)
720 next();
721 *linep = L0;
722 *valuep = V0;
723 return T0;
726 void Parser::pushLexerState()
728 LexerState* s = ALLOC(LexerState, ());
729 s->lexer = lexer;
730 s->next = lexerStack;
731 s->T0 = T0;
732 s->T1 = T1;
733 s->V0 = V0;
734 s->LP = LP;
735 s->L0 = L0;
736 s->L1 = L1;
737 s->included_input = included_input;
738 lexerStack = s;
741 void Parser::popLexerState()
743 T0 = lexerStack->T0;
744 T1 = lexerStack->T1;
745 V0 = lexerStack->V0;
746 V1 = lexerStack->V1;
747 LP = lexerStack->LP;
748 L0 = lexerStack->L0;
749 L1 = lexerStack->L1;
750 included_input = lexerStack->included_input;
751 lexer = lexerStack->lexer;
752 lexerStack = lexerStack->next;
755 void Parser::pushBindingRib(RibType tag)
757 topRib = ALLOC(BindingRib, (allocator, topRib, tag));
760 void Parser::popBindingRib()
762 topRib = topRib->next;
765 // Only makes sense in the context of a scope; compares name components only
766 static bool sameName(NameComponent* n1, NameComponent* n2)
768 if (n1 == NULL && n2 == NULL)
769 return true;
770 if (n1 == NULL || n2 == NULL)
771 return false;
772 if (n1->tag() != n2->tag())
773 return false;
774 switch (n1->tag()) {
775 case TAG_simpleName:
776 return ((SimpleName*)n1)->name == ((SimpleName*)n2)->name; // Str is interned, so pointer comparison works
777 case TAG_wildcardName:
778 return true;
779 case TAG_computedName:
780 return false;
781 default:
782 return false;
786 static bool sameName(QualifiedName* n1, QualifiedName* n2)
788 // ActionScript allows eg 'var n:Number; var n;".
789 if (n1 == NULL || n2 == NULL)
790 return true;
791 return sameName(n1->qualifier, n2->qualifier) && sameName(n1->name, n2->name);
794 Binding* Parser::findBinding(Str* name, BindingKind kind, BindingRib* rib)
796 if (rib == NULL)
797 rib = topRib;
798 for ( Seq<Binding*>* bindings = rib->bindings.get() ; bindings != NULL ; bindings = bindings->tl ) {
799 if (bindings->hd->name == name) {
800 if (bindings->hd->kind != kind)
801 compiler->syntaxError(0, SYNTAXERR_REDEFINITION);
802 return bindings->hd;
805 return NULL;
808 void Parser::addClass(ClassDefn* cls)
810 (void)cls;
811 compiler->internalError(0, "Unimplemented: Class definitions cannot be processed");
814 void Parser::addInterface(InterfaceDefn* iface)
816 (void)iface;
817 compiler->internalError(0, "Unimplemented: Interface definitions cannot be processed");
820 void Parser::addFunctionBinding(FunctionDefn* fn)
822 addVarBinding(fn->name, NULL);
823 topRib->functionDefinitions.addAtEnd(fn);
826 // FIXME: this ignores namespaces
827 void Parser::addVarBinding(Str* name, QualifiedName* type_name)
829 Binding* b = findBinding(name, TAG_varBinding);
830 if (!b)
831 topRib->bindings.addAtEnd(ALLOC(Binding, (name, type_name, TAG_varBinding)));
832 else if (!sameName(b->type_name, type_name))
833 compiler->syntaxError(0, SYNTAXERR_REDEFINITION_TYPE);
836 void Parser::addConstBinding(Str* name, QualifiedName* type_name)
838 if (findBinding(name, TAG_constBinding))
839 compiler->syntaxError(0, SYNTAXERR_REDUNDANT_CONST);
840 topRib->bindings.addAtEnd(ALLOC(Binding, (name, type_name, TAG_constBinding)));
843 void Parser::addMethodBinding(FunctionDefn* fn, BindingRib* rib)
845 if (findBinding(fn->name, TAG_methodBinding, rib))
846 compiler->syntaxError(0, SYNTAXERR_REDUNDANT_METHOD);
847 rib->bindings.addAtEnd(ALLOC(Binding, (fn->name, NULL, TAG_methodBinding)));
848 rib->functionDefinitions.addAtEnd(fn);
851 void Parser::addNamespaceBinding(Str* name, Expr* expr)
853 if (findBinding(name, TAG_namespaceBinding))
854 compiler->syntaxError(0, SYNTAXERR_REDUNDANT_NAMESPACE);
855 topRib->bindings.addAtEnd(ALLOC(Binding, (name, NULL, TAG_namespaceBinding))); // FIXME: type for 'Namespace'
856 topRib->namespaces.addAtEnd(ALLOC(NamespaceDefn, (name, expr)));
859 void Parser::addQualifiedImport(Seq<Str*>* name)
861 (void)name;
862 // A map from the last element of the name to the name
863 compiler->internalError(0, "Unimplemented: Qualified import not supported, use an unqualified import instead");
866 void Parser::addUnqualifiedImport(Seq<Str*>* name)
868 (void)name;
869 // Nothing we care about at this time
872 void Parser::addOpenNamespace(Namespace* ns)
874 topRib->openNamespaces.addAtEnd(ns);
877 void Parser::setUsesFinally()
879 topRib->uses_finally = true;
882 void Parser::setUsesCatch()
884 topRib->uses_catch = true;
887 void Parser::functionDefinition(bool config, Qualifier* qual, bool getters_and_setters, bool require_body)
889 (void)config;
890 uint32_t pos = position();
891 FunctionDefn* fn = functionGuts(qual, true, getters_and_setters, require_body);
892 checkNoShadowingOfConfigNamespaces(pos, fn->name);
893 if (topRib->tag == RIB_Instance) {
894 // class or interface
895 if (qual->is_static) {
896 AvmAssert(topRib->next->tag == RIB_Class);
897 addMethodBinding(fn, topRib->next);
899 else
900 addMethodBinding(fn, topRib);
902 else
903 addFunctionBinding(fn);
906 Stmt* Parser::variableDefinition(bool config, Qualifier* qual)
908 // FIXME: do not ignore the config value
909 // FIXME: check that the name we're defining is not shadowing a config NS
910 (void)qual;
911 // FIXME: discards qualifiers on variable definitions!
912 return statement(config);
915 FunctionDefn* Parser::functionGuts(Qualifier* qual, bool require_name, bool getters_and_setters, bool require_body)
917 if (qual->is_native)
918 compiler->syntaxError(position(), SYNTAXERR_NATIVE_NOT_SUPPORTED);
920 uint32_t numparams = 0;
921 bool default_value_required = false;
922 eat(T_Function);
923 uint32_t pos = position();
924 Str* name = NULL;
925 bool isSetter = false;
926 bool isGetter = false;
927 FunctionParam * rest_param = NULL;
928 if (require_name || hd() == T_Identifier)
929 name = identifier();
930 if (name != NULL && hd() == T_Identifier && getters_and_setters) {
931 isGetter = (name == compiler->SYM_get);
932 isSetter = (name == compiler->SYM_set);
933 name = identifier();
935 pushBindingRib(RIB_Function);
936 eat(T_LeftParen);
937 SeqBuilder<FunctionParam*> params(allocator);
938 if (hd() != T_RightParen) {
939 for (;;)
941 if (hd() == T_TripleDot) {
942 Str* rest_name = NULL;
943 QualifiedName* rest_type_name = NULL;
944 eat(T_TripleDot);
945 rest_name = identifier();
946 if (match(T_Colon))
947 rest_type_name = typeExpression();
948 addVarBinding(rest_name, rest_type_name);
949 rest_param = ALLOC(FunctionParam, (rest_name, rest_type_name, NULL));
950 break;
952 ++numparams;
953 Str* param_name = identifier();
954 QualifiedName* param_type_name = NULL;
955 Expr* param_default_value = NULL;
956 if (match(T_Colon))
957 param_type_name = typeExpression();
958 if (match(T_Assign)) {
959 default_value_required = true;
960 param_default_value = assignmentExpression(0);
962 else if (default_value_required)
963 compiler->syntaxError(pos, SYNTAXERR_DEFAULT_VALUE_REQD);
964 addVarBinding(param_name, param_type_name);
965 params.addAtEnd(ALLOC(FunctionParam, (param_name, param_type_name, param_default_value)));
966 if (hd() == T_RightParen)
967 break;
968 eat(T_Comma);
971 eat(T_RightParen);
972 topRib->optional_arguments = default_value_required;
973 QualifiedName* return_type_name = NULL;
974 if (match(T_Colon)) {
975 if (match(T_Void))
976 topRib->is_void = true;
977 else
978 return_type_name = typeExpression();
980 Seq<Stmt*>* stmts = NULL;
981 Seq<FunctionDefn*>* fndefs = NULL;
982 Seq<Binding*>* bindings = NULL;
983 Seq<NamespaceDefn*>* namespaces = NULL;
984 Seq<Namespace*>* openNamespaces = NULL;
985 bool uses_arguments = false;
986 bool uses_dxns = false;
987 bool optional_arguments = topRib->optional_arguments;
988 if (require_body)
990 eat(T_LeftBrace);
991 stmts = directives(SFLAG_Function);
992 eat(T_RightBrace);
993 // Rest takes precedence over 'arguments'
994 if (topRib->uses_arguments) {
995 if (rest_param == NULL)
996 addVarBinding(compiler->SYM_arguments, NULL);
997 else
998 topRib->uses_arguments = false;
1000 fndefs = topRib->functionDefinitions.get();
1001 bindings = topRib->bindings.get();
1002 namespaces = topRib->namespaces.get();
1003 openNamespaces = topRib->openNamespaces.get();
1004 uses_arguments = topRib->uses_arguments;
1005 uses_dxns = topRib->uses_dxns;
1007 else
1008 semicolon();
1010 popBindingRib();
1011 // FIXME: transmit isGetter and isSetter
1012 (void)isGetter;
1013 (void)isSetter;
1014 return ALLOC(FunctionDefn, (name, bindings, params.get(), numparams, rest_param, return_type_name, fndefs, namespaces, openNamespaces, stmts,
1015 uses_arguments,
1016 uses_dxns,
1017 optional_arguments));
1020 // Token queue abstractions
1021 // BEGIN
1023 // Token queue
1025 // T0 is the current token, L0 its line number
1026 // T1 is the next token, L1 its line number
1027 // LP is the line number of the previous token
1029 // The line number of a token is the 1-based line number of
1030 // the last character of the token.
1032 // Invariants:
1033 // T0 is LAST only before start() and when the stream is exhausted.
1034 // T1 is LAST whenever it's invalid
1035 // L1 is invalid iff T1 is invalid
1036 // LP, L0, and L1 are 0 if there is "no information"
1037 // The scanner never returns Eol
1039 // Every token passes through this interface so we try to save time
1040 // when possible.
1042 // Current optimizations:
1043 // * avoid function calls
1044 // - Lexer::lex() is shallow
1045 // - Token::tokenKind and Token::tokenText have been in-lined
1046 // * avoid allocations
1047 // - Communicate with lexer via multiple variables rather than
1048 // using multiple return values
1050 void Parser::start()
1052 T0 = lexer->lex(&L0, &V0);
1055 Token Parser::divideOperator()
1057 AvmAssert( T0 == T_BreakSlash && T1 == T_LAST );
1058 T0 = lexer->divideOperator(&L0);
1059 return hd();
1062 Token Parser::regexp()
1064 AvmAssert( T0 == T_BreakSlash && T1 == T_LAST );
1065 T0 = lexer->regexp(&L0, &V0);
1066 return hd();
1069 Token Parser::rightAngle()
1071 AvmAssert( T0 == T_BreakRightAngle && T1 == T_LAST );
1072 T0 = lexer->rightAngle(&L0);
1073 return hd();
1076 Token Parser::leftShiftOrRelationalOperator()
1078 AvmAssert( T0 == T_BreakLeftAngle && T1 == T_LAST );
1079 T0 = lexer->leftShiftOrRelationalOperator(&L0);
1080 return hd();
1083 Token Parser::rightShiftOrRelationalOperator()
1085 AvmAssert( T0 == T_BreakRightAngle && T1 == T_LAST );
1086 T0 = lexer->rightShiftOrRelationalOperator(&L0);
1087 return hd();
1090 Token Parser::hd2()
1092 if (T1 == T_LAST)
1093 T1 = lexer->lex(&L1, &V1);
1094 return T1;
1097 void Parser::next()
1099 LP = L0;
1100 T0 = T1;
1101 L0 = L1;
1102 V0 = V1;
1103 T1 = T_LAST;
1104 if (T0 == T_LAST)
1105 T0 = lexer->lex(&L0, &V0);
1108 // Token queue abstractions
1109 // END
1111 // If the current token is not tc then throw an error.
1112 // Otherwise consume the token.
1114 void Parser::eat(Token tc)
1116 Token tk = hd();
1117 if (tk != tc) {
1118 #ifdef DEBUG
1119 compiler->syntaxError(position(), SYNTAXERR_WRONG_TOKEN, tc, tk);
1120 #else
1121 compiler->syntaxError(position(), SYNTAXERR_WRONG_TOKEN); // FIXME: not adequate
1122 #endif
1124 next();
1127 bool Parser::match (Token tc)
1129 Token tk = hd();
1130 if (tk != tc)
1131 return false;
1132 next();
1133 return true;
1136 Str* Parser::identifier()
1138 if (hd() != T_Identifier)
1139 compiler->syntaxError(position(), SYNTAXERR_EXPECTED_IDENT);
1140 Str* name = V0.s;
1141 next();
1142 return name;
1145 Str* Parser::doubleToStr(double d)
1147 char buf[380];
1148 compiler->context->doubleToString(d, buf, sizeof(buf));
1149 return compiler->intern(buf);
1152 // FIXME: this duplicates Lexer::parseDouble()
1153 double Parser::strToDouble(Str* s)
1155 double n;
1156 StringBuilder sb(compiler);
1157 sb.append(s);
1158 DEBUG_ONLY(bool flag =) compiler->context->stringToDouble(sb.chardata(), &n);
1159 AvmAssert(flag);
1160 return n;
1163 CodeBlock::~CodeBlock()
1169 #endif // VMCFG_EVAL