Esempio n. 1
0
  bool Parser::Impl::parseTest() {
    // test := identifier arguments
    // arguments := *argument [ test / test-list ]

    //
    // identifier
    //

    if ( !obtainToken() || atEnd() )
      return false;

    if ( token() != Lexer::Identifier )
      return false;

    if ( scriptBuilder() )
      scriptBuilder()->testStart( tokenValue() );
    consumeToken();

    //
    // *argument
    //

    if ( !obtainToken() )
      return false;

    if ( atEnd() ) // a test w/o args
      goto TestEnd;

    if ( isArgumentToken() && !parseArgumentList() ) {
      assert( error() );
      return false;
    }

    //
    // test / test-list
    //

    if ( !obtainToken() )
      return false;

    if ( atEnd() ) // a test w/o nested tests
      goto TestEnd;

    if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list
      if ( !parseTestList() ) {
        assert( error() );
        return false;
      }
    } else if ( token() == Lexer::Identifier ) { // should be test:
      if ( !parseTest() ) {
        assert( error() );
        return false;
      }
    }

  TestEnd:
    if ( scriptBuilder() )
      scriptBuilder()->testEnd();
    return true;
  }
Esempio n. 2
0
DeclarationsPtr Parser::parseArgumentList_r()
{
    if (match(TokenType::Semicolon)) {
        return parseArgumentList();
    }

    return DeclarationsPtr();
}
Esempio n. 3
0
void Parser::parseArguments(SubprogramDeclarationPtr sub)
{
    if (match(TokenType::LParen)) {
        DeclarationsPtr arguments = parseArgumentList();

        if (!match(TokenType::RParen)) {
            reportError(ErrorCodes::ExpectedRParen);
            return;
        }

        sub->arguments = arguments;
        return;
    }
}
Esempio n. 4
0
void PackageParser::parseProtocol(const EmojicodeString &documentation, const Token &theToken, bool exported) {
    EmojicodeChar name, enamespace;
    parseAndValidateNewTypeName(&name, &enamespace);
    
    auto protocol = new Protocol(name, package_, documentation, theToken);
    
    parseGenericArgumentList(protocol, Type(protocol, false));
    protocol->finalizeGenericArguments();
    
    auto token = stream_.consumeToken(IDENTIFIER);
    if (token.value[0] != E_GRAPES) {
        ecCharToCharStack(token.value[0], s);
        throw CompilerErrorException(token, "Expected 🍇 but found %s instead.", s);
    }
    
    auto protocolType = Type(protocol, false);
    package_->registerType(protocolType, name, enamespace, exported);
    
    while (stream_.nextTokenIsEverythingBut(E_WATERMELON)) {
        auto documentation = parseDocumentationToken();
        auto token = stream_.consumeToken(IDENTIFIER);
        auto deprecated = Attribute<E_WARNING_SIGN>().parse(&stream_);
        
        if (token.value[0] != E_PIG) {
            throw CompilerErrorException(token, "Only method declarations are allowed inside a protocol.");
        }
        
        auto methodName = stream_.consumeToken(IDENTIFIER);
        
        auto method = new Method(methodName.value[0], PUBLIC, false, nullptr, package_, methodName.position(),
                                 false, documentation, deprecated.set());
        auto a = parseArgumentList(method, protocolType);
        auto b = parseReturnType(method, protocolType);
        if (a || b) {
            protocol->setUsesSelf();
        }
        
        protocol->addMethod(method);
    }
    stream_.consumeToken(IDENTIFIER);
}
Esempio n. 5
0
  bool Parser::Impl::parseCommand() {
    // command   := identifier arguments ( ";" / block )
    // arguments := *argument [ test / test-list ]
    // block     := "{" *command "}"
    // our ABNF:
    // block     := "{" [ command-list ] "}"

    if ( atEnd() )
      return false;

    //
    // identifier
    //

    if ( !obtainToken() || token() != Lexer::Identifier )
      return false;

    if ( scriptBuilder() )
      scriptBuilder()->commandStart( tokenValue() );
    consumeToken();

    //
    // *argument
    //

    if ( !obtainToken() )
      return false;

    if ( atEnd() ) {
      makeError( Error::MissingSemicolonOrBlock );
      return false;
    }

    if ( isArgumentToken() && !parseArgumentList() ) {
      assert( error() );
      return false;
    }

    //
    // test / test-list
    //

    if ( !obtainToken() )
      return false;

    if ( atEnd() ) {
      makeError( Error::MissingSemicolonOrBlock );
      return false;
    }

    if ( token() == Lexer::Special && tokenValue() == "(" ) { // test-list
      if ( !parseTestList() ) {
        assert( error() );
        return false;
      }
    } else if ( token() == Lexer::Identifier ) { // should be test:
      if ( !parseTest() ) {
        assert( error() );
        return false;
      }
    }

    //
    // ";" / block
    //

    if ( !obtainToken() )
      return false;

    if ( atEnd() ) {
      makeError( Error::MissingSemicolonOrBlock );
      return false;
    }

    if ( token() != Lexer::Special ) {
      makeUnexpectedTokenError( Error::ExpectedBlockOrSemicolon );
      return false;
    }

    if ( tokenValue() == ";" )
      consumeToken();
    else if ( tokenValue() == "{" ) { // block
      if ( !parseBlock() )
        return false; // it's an error since we saw '{'
    } else {
      makeError( Error::MissingSemicolonOrBlock );
      return false;
    }

    if ( scriptBuilder() )
      scriptBuilder()->commandEnd();
    return true;
  }