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
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.
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 ***** */
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;
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
)
118 , uses_finally(false)
120 , uses_arguments(false)
123 , optional_arguments(false)
128 Parser::Parser(Compiler
* compiler
, Lexer
* lexer
, uint32_t first_line
)
130 , allocator(compiler
->allocator
)
131 , line_offset(first_line
-1)
133 , configNamespaces(NULL
)
134 , configBindings(NULL
)
142 , included_input(NULL
)
146 Program
* Parser::parse()
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
)
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
));
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
);
175 while (hd() == T_Identifier
) {
176 name
.addAtEnd(identValue());
182 directives(SFLAG_Package
);
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
201 Expr
* e
; // Pending expression on entry to expr_statement
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;
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
;
225 if (hd() == T_RightBrace
|| hd() == T_EOS
) {
227 compiler
->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED
);
228 addExprStatements(&stmts
, metadatas
.get());
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
;
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.
262 compiler
->syntaxError(position(), SYNTAXERR_METADATA_NOT_ALLOWED
);
263 e
= commaExpression(0);
264 if (e
->tag() == TAG_literalXml
) {
266 metadatas
.addAtEnd(e
);
268 goto continue_directive
;
271 // Not metadata after all
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
282 // are valid statements (or will be).
284 compiler
->syntaxError(position(), SYNTAXERR_METADATA_NOT_ALLOWED
);
285 e
= commaExpression(0);
286 if (e
->tag() == TAG_literalArray
) {
288 metadatas
.addAtEnd(e
);
290 goto continue_directive
;
293 // Not metadata after all
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
)
316 goto configname_or_statement
;
317 if (isConfigReference(e
))
319 goto namespace_or_statement
;
321 configname_or_statement
:
322 if (!isConfigReference(e
))
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();
334 break; // Oops - really an error
335 stmts
.addAtEnd(ALLOC(ExprStmt
, (e
->pos
, e
)));
340 configname
= (QualifiedName
*)e
;
341 metadatas
.addAtEnd(e
);
345 goto continue_directive
;
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
);
356 compiler
->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED
);
358 metadatas
.addAtEnd(e
);
359 addExprStatements(&stmts
, metadatas
.get());
362 namespace_or_statement
:
363 AvmAssert(!newline());
364 if (!isNamespaceReference(e
))
366 if (qual
.tag
!= QUAL_none
)
367 compiler
->syntaxError(position(), SYNTAXERR_DUPLICATE_QUALIFIER
);
368 qual
.tag
= QUAL_name
;
369 qual
.name
= (QualifiedName
*)e
;
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.
390 QualifierTag t
= QUAL_none
;
391 if (hd2() != T_DoubleColon
) {
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()) {
406 compiler
->syntaxError(position(), SYNTAXERR_DIRECTIVE_REQUIRED
);
407 // Expression statement
409 metadatas
.addAtEnd(e
);
410 addExprStatements(&stmts
, metadatas
.get());
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");
425 goto continue_directive
;
430 goto consume_simple_qualifier
;
435 goto consume_simple_qualifier
;
440 goto consume_simple_qualifier
;
443 override_qualifier
: {
445 goto consume_simple_qualifier
;
450 goto consume_simple_qualifier
;
453 consume_simple_qualifier
: {
457 goto continue_directive
;
460 config_namespace_directive
: {
461 // No attributes or metadata will have been parsed
464 if (!(flags
& SFLAG_Toplevel
))
465 compiler
->syntaxError(position(), SYNTAXERR_CONFIG_NAMESPACE_NOT_ALLOWED
);
466 configNamespaceDefinition(flags
, evaluateConfigReference(configname
));
471 // No attributes or metadata will have been parsed
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
);
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
));
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);
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
);
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
);
534 AvmAssert(e
== NULL
);
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
)));
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
)
569 QualifiedName
* qn
= (QualifiedName
*)e
;
570 if (qn
->name
->tag() != TAG_simpleName
)
572 if (qn
->qualifier
!= NULL
&& qn
->qualifier
->tag() != TAG_simpleName
)
577 void Parser::addExprStatements(SeqBuilder
<Stmt
*>* stmts
, Seq
<Expr
*>* exprs
)
579 while (exprs
!= NULL
) {
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
)
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).
593 uint32_t pos
= position();
594 Str
* name
= identifier();
595 checkNoShadowingOfConfigNamespaces(pos
, name
);
597 SeqBuilder
<Str
*> implements(allocator
);
598 if (hd() == T_Identifier
&& identValue() == compiler
->SYM_extends
) {
600 extends
= identifier();
602 if (hd() == T_Identifier
&& identValue() == compiler
->SYM_implements
) {
605 implements
.addAtEnd(identifier());
606 } while (match(T_Comma
));
609 pushBindingRib(RIB_Class
);
610 pushBindingRib(RIB_Instance
);
611 Seq
<Stmt
*>* instance_init
= NULL
;
612 Seq
<Stmt
*>* class_init
= directives(SFLAG_Class
, &instance_init
);
616 addClass(ALLOC(ClassDefn
, (qual
, name
, extends
, implements
.get(), class_init
, instance_init
)));
619 void Parser::interfaceDefinition(bool config
, int /*flags*/, Qualifier
* qual
)
622 // FIXME: pick up the methods somehow, these are available from the binding ribs
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
) {
630 extends
.addAtEnd(identifier());
631 } while (match(T_Comma
));
634 pushBindingRib(RIB_Instance
);
635 directives(SFLAG_Interface
);
638 addInterface(ALLOC(InterfaceDefn
, (qual
, name
, extends
.get())));
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*/)
652 uint32_t pos
= position();
654 Str
* name
= identifier();
655 checkNoShadowingOfConfigNamespaces(pos
, name
);
657 if (match(T_Assign
)) {
658 if (hd() != T_Identifier
&& hd() != T_StringLiteral
)
659 compiler
->syntaxError(pos
, SYNTAXERR_ILLEGAL_NAMESPACE
);
660 value
= primaryExpression();
664 addNamespaceBinding(name
, value
);
667 void Parser::configNamespaceDefinition(int flags
, bool config
)
673 void Parser::includeDirective()
676 Str
* newFile
= stringValue();
677 uint32_t pos
= position();
678 eat(T_StringLiteral
);
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.
696 const wchar
* input
= compiler
->context
->readFileForEval(compiler
->filename
, newFile
->s
, &inputlen
);
698 compiler
->syntaxError(pos
, SYNTAXERR_INCLUDE_INACCESSIBLE
);
700 included_input
= input
; // freed in onEOS below
702 bool doTrace
= lexer
->getTrace();
704 lexer
= ALLOC(Lexer
, (compiler
, input
, inputlen
));
706 if (doTrace
) lexer
->trace();
711 Token
Parser::onEOS(uint32_t* linep
, TokenValue
* valuep
)
713 if (lexerStack
== NULL
)
716 compiler
->context
->freeInput(included_input
);
726 void Parser::pushLexerState()
728 LexerState
* s
= ALLOC(LexerState
, ());
730 s
->next
= lexerStack
;
737 s
->included_input
= included_input
;
741 void Parser::popLexerState()
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
)
770 if (n1
== NULL
|| n2
== NULL
)
772 if (n1
->tag() != n2
->tag())
776 return ((SimpleName
*)n1
)->name
== ((SimpleName
*)n2
)->name
; // Str is interned, so pointer comparison works
777 case TAG_wildcardName
:
779 case TAG_computedName
:
786 static bool sameName(QualifiedName
* n1
, QualifiedName
* n2
)
788 // ActionScript allows eg 'var n:Number; var n;".
789 if (n1
== NULL
|| n2
== NULL
)
791 return sameName(n1
->qualifier
, n2
->qualifier
) && sameName(n1
->name
, n2
->name
);
794 Binding
* Parser::findBinding(Str
* name
, BindingKind kind
, BindingRib
* rib
)
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
);
808 void Parser::addClass(ClassDefn
* cls
)
811 compiler
->internalError(0, "Unimplemented: Class definitions cannot be processed");
814 void Parser::addInterface(InterfaceDefn
* 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
);
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
)
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
)
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
)
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
);
900 addMethodBinding(fn
, topRib
);
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
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
)
918 compiler
->syntaxError(position(), SYNTAXERR_NATIVE_NOT_SUPPORTED
);
920 uint32_t numparams
= 0;
921 bool default_value_required
= false;
923 uint32_t pos
= position();
925 bool isSetter
= false;
926 bool isGetter
= false;
927 FunctionParam
* rest_param
= NULL
;
928 if (require_name
|| hd() == T_Identifier
)
930 if (name
!= NULL
&& hd() == T_Identifier
&& getters_and_setters
) {
931 isGetter
= (name
== compiler
->SYM_get
);
932 isSetter
= (name
== compiler
->SYM_set
);
935 pushBindingRib(RIB_Function
);
937 SeqBuilder
<FunctionParam
*> params(allocator
);
938 if (hd() != T_RightParen
) {
941 if (hd() == T_TripleDot
) {
942 Str
* rest_name
= NULL
;
943 QualifiedName
* rest_type_name
= NULL
;
945 rest_name
= identifier();
947 rest_type_name
= typeExpression();
948 addVarBinding(rest_name
, rest_type_name
);
949 rest_param
= ALLOC(FunctionParam
, (rest_name
, rest_type_name
, NULL
));
953 Str
* param_name
= identifier();
954 QualifiedName
* param_type_name
= NULL
;
955 Expr
* param_default_value
= NULL
;
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
)
972 topRib
->optional_arguments
= default_value_required
;
973 QualifiedName
* return_type_name
= NULL
;
974 if (match(T_Colon
)) {
976 topRib
->is_void
= true;
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
;
991 stmts
= directives(SFLAG_Function
);
993 // Rest takes precedence over 'arguments'
994 if (topRib
->uses_arguments
) {
995 if (rest_param
== NULL
)
996 addVarBinding(compiler
->SYM_arguments
, NULL
);
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
;
1011 // FIXME: transmit isGetter and isSetter
1014 return ALLOC(FunctionDefn
, (name
, bindings
, params
.get(), numparams
, rest_param
, return_type_name
, fndefs
, namespaces
, openNamespaces
, stmts
,
1017 optional_arguments
));
1020 // Token queue abstractions
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.
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
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
);
1062 Token
Parser::regexp()
1064 AvmAssert( T0
== T_BreakSlash
&& T1
== T_LAST
);
1065 T0
= lexer
->regexp(&L0
, &V0
);
1069 Token
Parser::rightAngle()
1071 AvmAssert( T0
== T_BreakRightAngle
&& T1
== T_LAST
);
1072 T0
= lexer
->rightAngle(&L0
);
1076 Token
Parser::leftShiftOrRelationalOperator()
1078 AvmAssert( T0
== T_BreakLeftAngle
&& T1
== T_LAST
);
1079 T0
= lexer
->leftShiftOrRelationalOperator(&L0
);
1083 Token
Parser::rightShiftOrRelationalOperator()
1085 AvmAssert( T0
== T_BreakRightAngle
&& T1
== T_LAST
);
1086 T0
= lexer
->rightShiftOrRelationalOperator(&L0
);
1093 T1
= lexer
->lex(&L1
, &V1
);
1105 T0
= lexer
->lex(&L0
, &V0
);
1108 // Token queue abstractions
1111 // If the current token is not tc then throw an error.
1112 // Otherwise consume the token.
1114 void Parser::eat(Token tc
)
1119 compiler
->syntaxError(position(), SYNTAXERR_WRONG_TOKEN
, tc
, tk
);
1121 compiler
->syntaxError(position(), SYNTAXERR_WRONG_TOKEN
); // FIXME: not adequate
1127 bool Parser::match (Token tc
)
1136 Str
* Parser::identifier()
1138 if (hd() != T_Identifier
)
1139 compiler
->syntaxError(position(), SYNTAXERR_EXPECTED_IDENT
);
1145 Str
* Parser::doubleToStr(double d
)
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
)
1156 StringBuilder
sb(compiler
);
1158 DEBUG_ONLY(bool flag
=) compiler
->context
->stringToDouble(sb
.chardata(), &n
);
1163 CodeBlock::~CodeBlock()
1169 #endif // VMCFG_EVAL