// 'default' has been consumed, hd() is the identifier 'xml' Stmt* Parser::defaultXmlNamespaceStatement() { uint32_t pos = position(); if(hd() != T_Identifier || identValue() != compiler->SYM_xml) goto failure; eat(T_Identifier); if(hd() != T_Identifier || identValue() != compiler->SYM_namespace) goto failure; eat(T_Identifier); eat(T_Assign); setUsesDefaultXmlNamespace(); return ALLOC(DefaultXmlNamespaceStmt, (pos, commaExpression(0))); failure: compiler->syntaxError(pos, SYNTAXERR_EXPECT_DXNS); /*NOTREACHED*/ return NULL; }
// <import> ::= "import" <ident> { "." <ident> }* { "." "*" } Stmt* Parser::importStatement() { uint32_t pos = position(); SeqBuilder<Str*> name(allocator); eat(T_Import); if (hd() == T_Identifier) name.addAtEnd(identValue()); eat(T_Identifier); while (match(T_Dot)) { if (hd() == T_Multiply) { name.addAtEnd(NULL); break; } if (hd() == T_Identifier) name.addAtEnd(identValue()); eat(T_Identifier); } return ALLOC(ImportStmt, (pos, name.get())); }
Stmt* Parser::useStatement() { uint32_t pos = position(); eat(T_Use); if (!(hd() == T_Identifier && identValue() == compiler->SYM_namespace)) compiler->syntaxError(pos, SYNTAXERR_ILLEGAL_USE); eat(T_Identifier); Str* ns = identifier(); return ALLOC(UseNamespaceStmt, (pos, ns)); }
Stmt* Parser::forStatement() { Expr* init=NULL; Expr* lhs=NULL; uint32_t numbindings = 0; bool is_each = false; eat (T_For); if (hd() == T_Identifier && identValue() == compiler->SYM_each) { is_each = true; eat(T_Identifier); } uint32_t pos = position(); eat (T_LeftParen); if (hd() == T_Var) { uint32_t dummy = 0; init = varBindings(&dummy, defaultNamespace(), false, false, EFLAG_NoIn, &numbindings, &lhs); } else if (hd() == T_Semicolon) ; else lhs = init = commaExpression(EFLAG_NoIn); if (match(T_In)) { if (numbindings > 1) compiler->syntaxError(pos, SYNTAXERR_FOR_IN_ONEBINDING); Expr* objexpr = commaExpression(0); eat (T_RightParen); Stmt* body = statement(); AvmAssert( lhs != NULL ); return ALLOC(ForInStmt, (pos, lhs, init, objexpr, body, is_each)); } else { if (is_each) compiler->syntaxError(pos, SYNTAXERR_FOR_EACH_REQS_IN); eat(T_Semicolon); Expr* test = hd() == T_Semicolon ? NULL : commaExpression(0); eat(T_Semicolon); Expr* update = hd() == T_RightParen ? NULL : commaExpression(0); eat(T_RightParen); Stmt* body = statement (); return ALLOC(ForStmt, (pos, init, test, update, body)); } }
// <import> ::= "import" <ident> { "." <ident> }* { "." "*" } Stmt* Parser::importStatement() { SeqBuilder<Str*> name(allocator); StringBuilder id(compiler); const bool hackaround = true; // treat import x.y.z as import x.y.* eat(T_Import); if (hd() == T_Identifier) { name.addAtEnd(identValue()); id.append(identValue()); } eat(T_Identifier); bool qualified = true; while (match(T_Dot)) { if (hd() == T_Multiply) { match(T_Multiply); qualified = false; break; } if (hackaround) { if (hd() == T_Identifier && hd2() == T_Dot) { id.append("."); name.addAtEnd(identValue()); id.append(identValue()); } eat(T_Identifier); } else { id.append("."); if (hd() == T_Identifier) { name.addAtEnd(identValue()); id.append(identValue()); } eat(T_Identifier); } } Seq<Str*>* n = name.get(); if (qualified) { compiler->internalWarning(position(), "Unimplemented: Qualified import not supported yet, using an unqualified import instead"); addOpenNamespace(ALLOC(CommonNamespace, (id.str()))); addQualifiedImport(n); } else { addOpenNamespace(ALLOC(CommonNamespace, (id.str()))); addUnqualifiedImport(n); } return ALLOC(EmptyStmt, ()); }
bool Parser::namespaceQualifier(int flags, Qualifier* qual) { switch (hd()) { case T_Native: if (!(flags & (SFLAG_Class|SFLAG_Package|SFLAG_Toplevel)) || qual->is_native || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "native"); eat(T_Native); qual->is_native = true; return true; case T_Private: if (!(flags & SFLAG_Class) || qual->tag != QUAL_none || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "private"); eat(T_Private); qual->tag = QUAL_private; return true; case T_Protected: if (!(flags & SFLAG_Class) || qual->tag != QUAL_none || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "protected"); eat(T_Protected); qual->tag = QUAL_protected; return true; case T_Public: if (!(flags & (SFLAG_Class|SFLAG_Package)) || qual->tag != QUAL_none || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "public"); eat(T_Protected); qual->tag = QUAL_public; return true; case T_Internal: if (!(flags & (SFLAG_Class|SFLAG_Package)) || qual->tag != QUAL_none || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "internal"); eat(T_Internal); qual->tag = QUAL_internal; return true; case T_Identifier: if (identValue() == compiler->SYM_namespace) return false; if ((flags & SFLAG_Class) && identValue() == compiler->SYM_static) { if (qual->is_static || qual->is_prototype) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "static"); next(); qual->is_static = true; return true; } if ((flags & SFLAG_Class) && identValue() == compiler->SYM_prototype) { if (qual->is_static || qual->is_prototype || qual->is_native || qual->tag != QUAL_none) compiler->syntaxError(position(), SYNTAXERR_KWD_NOT_ALLOWED, "prototype"); next(); qual->is_prototype = true; return true; } if (qual->tag != QUAL_none) return false; if (qual->is_native) goto consume; switch (hd2()) { case T_Function: case T_Var: case T_Const: case T_Class: case T_Interface: goto consume; default: return false; } consume: qual->tag = QUAL_name; qual->name = identValue(); eat(T_Identifier); return true; default: compiler->internalError(position(), "Unexpected namespace qualifier"); /*NOTREACHED*/ return false; } }