/* getter-setter-block → {getter-clause setter-clauseopt} getter-setter-block → {setter-clause getter-clause} getter-clause → attributes opt get code-block setter-clause → attributes opt set setter-name opt code-block setter-name → (identifier) */ std::pair<CodeBlockPtr, std::pair<std::wstring, CodeBlockPtr> > Parser::parseGetterSetterBlock() { Token token; Attributes attrs; parseAttributes(attrs); peek(token); CodeBlockPtr getter = NULL; std::pair<std::wstring, CodeBlockPtr> setter = std::make_pair(std::wstring(), CodeBlockPtr()); if(token.getKeyword() == Keyword::Get) { expect_next(token); getter = parseCodeBlock(); getter->setAttributes(attrs); peek(token); if(token == L"@" || token.getKeyword() == Keyword::Set) { setter = parseSetterClause(); } } else if(token.getKeyword() == Keyword::Set) { setter = parseSetterClause(); setter.second->setAttributes(attrs); parseAttributes(attrs); expect(Keyword::Get); getter = parseCodeBlock(); getter->setAttributes(attrs); } return std::make_pair(getter, setter); }
void SemanticAnalyzer::append_block(CodeBlockPtr new_block) { if (new_block != nullptr) { // child of top block stack parent this->block_stack->top()->append(new_block); // parent is the top of the block stack new_block->set_parent(this->block_stack->top()); // push this block to the stack top this->block_stack->push(new_block); // set this block's analyzer parent if null new_block->set_analyzer(SemanticAnalyzerPtr(this)); } }
CodeBlockPtr Parser::parseCodeBlock() { Token token; Flags flags(this); flags -= SUPPRESS_TRAILING_CLOSURE; expect(L"{", token); CodeBlockPtr ret = nodeFactory->createCodeBlock(token.state); while(!match(L"}")) { StatementPtr st = parseStatement(); if(st != NULL) ret->addStatement(st); } return ret; }
TEST(TestFunc, testFunc) { PARSE_STATEMENT(L"func stepForward(input: Int) -> Int {" L"return input + 1" L"}"); FunctionDefPtr func; ParametersNodePtr params; ParameterNodePtr param; TypeIdentifierPtr type; CodeBlockPtr cb; ReturnStatementPtr ret; BinaryOperatorPtr add; IdentifierPtr id; IntegerLiteralPtr i; ASSERT_NOT_NULL(func = std::dynamic_pointer_cast<FunctionDef>(root)); ASSERT_EQ(L"stepForward", func->getName()); ASSERT_EQ(1, func->numParameters()); ASSERT_NOT_NULL(params = func->getParameters(0)); ASSERT_EQ(1, params->numParameters()); ASSERT_NOT_NULL(param = params->getParameter(0)); ASSERT_EQ(ParameterNode::None, param->getAccessibility()); ASSERT_FALSE(param->isShorthandExternalName()); ASSERT_FALSE(param->isInout()); ASSERT_NULL(param->getDefaultValue()); ASSERT_EQ(L"", param->getExternalName()); ASSERT_EQ(L"input", param->getLocalName()); ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(param->getDeclaredType())); ASSERT_EQ(L"Int", type->getName()); ASSERT_NOT_NULL(type = std::dynamic_pointer_cast<TypeIdentifier>(func->getReturnType())); ASSERT_EQ(L"Int", type->getName()); ASSERT_NOT_NULL(cb = func->getBody()); ASSERT_EQ(1, cb->numStatements()); ASSERT_NOT_NULL(ret = std::dynamic_pointer_cast<ReturnStatement>(cb->getStatement(0))); ASSERT_NOT_NULL(add = std::dynamic_pointer_cast<BinaryOperator>(ret->getExpression())); ASSERT_EQ(L"+", add->getOperator()); ASSERT_NOT_NULL(id = std::dynamic_pointer_cast<Identifier>(add->getLHS())); ASSERT_NOT_NULL(i = std::dynamic_pointer_cast<IntegerLiteral>(add->getRHS())); ASSERT_EQ(L"input", id->getIdentifier()); ASSERT_EQ(L"1", i->valueAsString); }
void FunctionAnalyzer::visitAccessor(const CodeBlockPtr& accessor, const ParametersNodePtr& params, const SymbolPtr& setter, int modifiers) { if(!accessor) return; ScopedCodeBlockPtr codeBlock = std::static_pointer_cast<ScopedCodeBlock>(accessor); SymbolScope *scope = codeBlock->getScope(); ScopeGuard scopeGuard(codeBlock.get(), this); (void) scopeGuard; if(setter) scope->addSymbol(setter); params->accept(this); declarationAnalyzer->prepareParameters(scope, params); SCOPED_SET(ctx->currentFunction, accessor->getType()); accessor->accept(semanticAnalyzer); }
void Parser::parseSwitchStatements(const CaseStatementPtr& case_) { Token token; Flags flags(this); flags -= SUPPRESS_TRAILING_CLOSURE; CodeBlockPtr codeBlock = case_->getCodeBlock(); while(true) { expect_next(token); if(token.type == TokenType::Semicolon) continue; restore(token); Keyword::T k = token.getKeyword(); if(token.type == TokenType::CloseBrace || (k == Keyword::Case || k == Keyword::Default)) { break; } StatementPtr st = parseStatement(); codeBlock->addStatement(st); } }
void SemanticAnalyzer::generate_one(CodeBlockPtr current) { // iterate through the blocks and // generate all code // generate pre inner code current->preprocess(); if (current->validate()) { current->generate_pre(); // get children and visit for (auto i = current->inner_begin(); i != current->inner_end(); i++) { generate_one(*i); } // generate post code current->generate_post(); } else { // terminate the program this->close_file(); report_msg_type("Compilation Failed", "Validation failure."); exit(0); } }
/* getter-setter-keyword-block → {getter-keyword-clause setter-keyword-clause opt} getter-setter-keyword-block → {setter-keyword-clause getter-keyword-clause} getter-keyword-clause → attributes opt get setter-keyword-clause → attributes opt set */ std::pair<CodeBlockPtr, CodeBlockPtr> Parser::parseGetterSetterKeywordBlock() { Token token; Attributes attributes; parseAttributes(attributes); CodeBlockPtr getter = NULL; CodeBlockPtr setter = NULL; if(match(Keyword::Get, token)) { getter = nodeFactory->createCodeBlock(token.state); getter->setAttributes(attributes); parseAttributes(attributes); if(match(Keyword::Set, token)) { setter = nodeFactory->createCodeBlock(token.state); setter->setAttributes(attributes); } else if(!attributes.empty())//attributes defined for setter but setter is not found { Token token; expect_next(token); unexpected(token); } } else if(match(Keyword::Set, token)) { setter = nodeFactory->createCodeBlock(token.state); setter->setAttributes(attributes); parseAttributes(attributes); expect(Keyword::Get, token); getter = nodeFactory->createCodeBlock(token.state); getter->setAttributes(attributes); } return std::make_pair(getter, setter); }
/* 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; }