TEST(TestDeclaration, testLet) { PARSE_STATEMENT(L"let a : Int[] = [1, 2, 3]"); ValueBindingsPtr c; IdentifierPtr id; ValueBindingPtr a; ArrayLiteralPtr value; ArrayTypePtr type; TypeIdentifierPtr Int; ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(c->isReadOnly()); ASSERT_EQ(1, c->numBindings()); ASSERT_NOT_NULL(a = c->get(0)); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(a->getName())); ASSERT_EQ(L"a", id->getIdentifier()); ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<ArrayType>(a->getDeclaredType())); ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(type->getInnerType())); ASSERT_EQ(L"Int", Int->getName()); ASSERT_NOT_NULL(value = std::dynamic_pointer_cast<ArrayLiteral>(c->get(0)->getInitializer())); ASSERT_EQ(3, value->numElements()); ASSERT_EQ(L"1", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(0))->valueAsString); ASSERT_EQ(L"2", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(1))->valueAsString); ASSERT_EQ(L"3", std::dynamic_pointer_cast<IntegerLiteral>(value->getElement(2))->valueAsString); }
/* GRAMMAR OF A CONSTANT DECLARATION constant-declaration → attributes opt declaration-specifiers opt let pattern-initializer-list pattern-initializer-list → pattern-initializer | pattern-initializer,pattern-initializer-list pattern-initializer → pattern initializer opt initializer → =expression */ DeclarationPtr Parser::parseLet(const std::vector<AttributePtr>& attrs, int specifiers) { Token token; Flags flag(this, UNDER_LET); expect(Keyword::Let, token); ValueBindingsPtr ret = nodeFactory->createValueBindings(token.state); ret->setReadOnly(true); ret->setAttributes(attrs); ret->setSpecifiers(specifiers); do { PatternPtr pattern = parsePattern(); ExpressionPtr initializer = NULL; if(match(L"=")) { initializer = parseExpression(); } ValueBindingPtr constant = nodeFactory->createValueBinding(*pattern->getSourceInfo()); constant->setAttributes(attrs); constant->setSpecifiers(specifiers); constant->setName(pattern); TypedPatternPtr typedPattern = std::dynamic_pointer_cast<TypedPattern>(pattern); if(typedPattern) { //promote typed pattern constant->setDeclaredType(typedPattern->getDeclaredType()); constant->setName(typedPattern->getPattern()); } constant->setInitializer(initializer); ret->add(constant); }while(match(L",")); return ret; }
TEST(TestDeclaration, testLet_Tuple) { PARSE_STATEMENT(L"let (a, b) : Int = (1, 2)"); ValueBindingsPtr c; TuplePtr tuple; TypeIdentifierPtr type; ParenthesizedExpressionPtr p; ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(c->isReadOnly()); ASSERT_NOT_NULL(tuple = std::dynamic_pointer_cast<Tuple>(c->get(0)->getName())); ASSERT_EQ(2, tuple->numElements()); ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(c->get(0)->getDeclaredType())); ASSERT_NOT_NULL(p = std::dynamic_pointer_cast<ParenthesizedExpression>(c->get(0)->getInitializer())); ASSERT_EQ(2, p->numExpressions()); }
TEST(TestDeclaration, testVar_Typed) { PARSE_STATEMENT(L"var welcomeMessage: String"); ValueBindingsPtr vars; ValueBindingPtr var; IdentifierPtr id; TypeIdentifierPtr t; ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(!vars->isReadOnly()); ASSERT_EQ(1, vars->numBindings()); ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0))); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName())); ASSERT_EQ(L"welcomeMessage", id->getIdentifier()); ASSERT_NOT_NULL(t = std::dynamic_pointer_cast<TypeIdentifier>(var->getDeclaredType())); ASSERT_EQ(L"String", t->getName()); }
TEST(TestDeclaration, testVar) { PARSE_STATEMENT(L"var currentLoginAttempt = 0"); ValueBindingsPtr vars; ValueBindingPtr var; IdentifierPtr id; IntegerLiteralPtr i; ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(!vars->isReadOnly()); ASSERT_EQ(1, vars->numBindings()); ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0))); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName())); ASSERT_EQ(L"currentLoginAttempt", id->getIdentifier()); ASSERT_NOT_NULL(i = std::dynamic_pointer_cast<IntegerLiteral>(var->getInitializer())); ASSERT_EQ(L"0", i->valueAsString); }
TEST(TestDeclaration, testVar_Multiple) { PARSE_STATEMENT(L"var x = 0.0, y = 0.0, z = 0.0"); ValueBindingsPtr vars; ValueBindingPtr var; IdentifierPtr id; FloatLiteralPtr f; ASSERT_NOT_NULL(vars = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(!vars->isReadOnly()); ASSERT_EQ(3, vars->numBindings()); ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(0))); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName())); ASSERT_EQ(L"x", id->getIdentifier()); ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer())); ASSERT_EQ(L"0.0", f->valueAsString); ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(1))); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName())); ASSERT_EQ(L"y", id->getIdentifier()); ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer())); ASSERT_EQ(L"0.0", f->valueAsString); ASSERT_NOT_NULL(var = std::dynamic_pointer_cast<ValueBinding>(vars->get(2))); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(var->getName())); ASSERT_EQ(L"z", id->getIdentifier()); ASSERT_NOT_NULL(f = std::dynamic_pointer_cast<FloatLiteral>(var->getInitializer())); ASSERT_EQ(L"0.0", f->valueAsString); }
TEST(TestDeclaration, testLet_Multiple) { PARSE_STATEMENT(L"let a=[k1 : 1, k2 : 2], b : Int = 2"); ValueBindingsPtr c; ValueBindingPtr b; IdentifierPtr id; TypeIdentifierPtr Int; DictionaryLiteralPtr dict; ASSERT_NOT_NULL(c = std::dynamic_pointer_cast<ValueBindings>(root)); ASSERT_TRUE(c->isReadOnly()); ASSERT_EQ(2, c->numBindings()); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(c->get(0)->getName())); ASSERT_EQ(L"a", id->getIdentifier()); ASSERT_NOT_NULL(dict = std::dynamic_pointer_cast<DictionaryLiteral>(c->get(0)->getInitializer())); ASSERT_EQ(2, dict->numElements()); ASSERT_NOT_NULL(b = c->get(1)); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(b->getName())); ASSERT_EQ(L"b", id->getIdentifier()); ASSERT_NOT_NULL(Int = std::dynamic_pointer_cast<TypeIdentifier>(b->getDeclaredType())); ASSERT_EQ(L"Int", Int->getName()); }
/* GRAMMAR OF A VARIABLE DECLARATION variable-declaration → variable-declaration-head pattern-initializer-list variable-declaration → variable-declaration-head variable-name type-annotation code-block variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-block variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block variable-declaration → variable-declaration-head variable-name type-annotation initializer opt willSet-didSet-block variable-declaration-head → attributes opt declaration-specifiers opt var variable-name → identifier */ DeclarationPtr Parser::parseVar(const std::vector<AttributePtr>& attrs, int specifiers) { Token token; expect(Keyword::Var, token); Flags flags(this, UNDER_VAR); //try read it as pattern-initializer-list ValueBindingsPtr ret = nodeFactory->createValueBindings(token.state); ret->setReadOnly(false); ret->setAttributes(attrs); ret->setSpecifiers(specifiers); ValueBindingPtr var = parseVariableDeclaration(); var->setSpecifiers(specifiers); ret->add(var); if(predicate(L",")) { while(match(L",")) { var = parseVariableDeclaration(); var->setSpecifiers(specifiers); ret->add(var); } return ret; } if(!match(L"{")) return ret; peek(token); IdentifierPtr name = std::dynamic_pointer_cast<Identifier>(var->getName()); tassert(token, name != nullptr, Errors::E_GETTER_SETTER_CAN_ONLY_BE_DEFINED_FOR_A_SINGLE_VARIABLE, L""); ComputedPropertyPtr prop = nodeFactory->createComputedProperty(*var->getSourceInfo()); prop->setAttributes(attrs); prop->setSpecifiers(specifiers); prop->setTypeAttributes(var->getTypeAttributes()); prop->setName(name->getIdentifier()); prop->setDeclaredType(var->getDeclaredType()); prop->setInitializer(var->getInitializer()); var = nullptr; ret = nullptr; if(token.type != TokenType::CloseBrace) { Flags flags(this, SUPPRESS_TRAILING_CLOSURE); switch(token.getKeyword()) { case Keyword::Get: case Keyword::Set: if(this->flags & UNDER_PROTOCOL) { // variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-keyword-block //no code block for getter/setter for protocol std::pair<CodeBlockPtr, CodeBlockPtr> r = parseGetterSetterKeywordBlock(); prop->setGetter(r.first); prop->setSetter(r.second); } else { // variable-declaration → variable-declaration-head variable-name type-annotation getter-setter-block std::pair<CodeBlockPtr, std::pair<std::wstring, CodeBlockPtr> > r = parseGetterSetterBlock(); prop->setGetter(r.first); prop->setSetterName(r.second.first); prop->setSetter(r.second.second); } break; case Keyword::WillSet: case Keyword::DidSet: // variable-declaration → variable-declaration-head variable-name type-annotation initializer opt willSet-didSet-block parseWillSetDidSetBlock(prop); break; default: // variable-declaration → variable-declaration-head variable-name type-annotation code-block CodeBlockPtr getter = nodeFactory->createCodeBlock(token.state); prop->setGetter(getter); do { StatementPtr st = parseStatement(); getter->addStatement(st); }while(!predicate(L"}")); break; } } expect(L"}"); return prop; }
void NodeSerializer::visitValueBindings(const ValueBindingsPtr &node) { append(node->isReadOnly() ? L"let " : L"var "); NodeVisitor::visitValueBindings(node); }