/*
 ‌ 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));
	}
}
Exemple #3
0
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;
}
Exemple #4
0
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);


}
Exemple #5
0
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);
}
Exemple #6
0
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;
}