docs: public final AntlrDatatypeRuleToken ruleRuleID() throws RecognitionException {
          AntlrDatatypeRuleToken current = new AntlrDatatypeRuleToken();
  
          Token kw=null;
          AntlrDatatypeRuleToken this_ValidID_0 = null;
  
          AntlrDatatypeRuleToken this_ValidID_2 = null;
  
  
  
          	enterRule();
  
          try {
              // InternalXtext.g:2092:2: ( (this_ValidID_0= ruleValidID (kw= '::' this_ValidID_2= ruleValidID )* ) )
              // InternalXtext.g:2093:2: (this_ValidID_0= ruleValidID (kw= '::' this_ValidID_2= ruleValidID )* )
              {
              // InternalXtext.g:2093:2: (this_ValidID_0= ruleValidID (kw= '::' this_ValidID_2= ruleValidID )* )
              // InternalXtext.g:2094:3: this_ValidID_0= ruleValidID (kw= '::' this_ValidID_2= ruleValidID )*
              {
  
              			newCompositeNode(grammarAccess.getRuleIDAccess().getValidIDParserRuleCall_0());
              		
              pushFollow(FollowSets000.FOLLOW_38);
              this_ValidID_0=ruleValidID();
  
              state._fsp--;
  
  
              			current.merge(this_ValidID_0);
              		
  
              			afterParserOrEnumRuleCall();
              		
              // InternalXtext.g:2104:3: (kw= '::' this_ValidID_2= ruleValidID )*
              loop48:
              do {
                  int alt48=2;
                  int LA48_0 = input.LA(1);
  
                  if ( (LA48_0==29) ) {
                      alt48=1;
                  }
  
  
                  switch (alt48) {
              	case 1 :
              	    // InternalXtext.g:2105:4: kw= '::' this_ValidID_2= ruleValidID
              	    {
              	    kw=(Token)match(input,29,FollowSets000.FOLLOW_3); 
  
              	    				current.merge(kw);
              	    				newLeafNode(kw, grammarAccess.getRuleIDAccess().getColonColonKeyword_1_0());
              	    			
  
              	    				newCompositeNode(grammarAccess.getRuleIDAccess().getValidIDParserRuleCall_1_1());
              	    			
              	    pushFollow(FollowSets000.FOLLOW_38);
              	    this_ValidID_2=ruleValidID();
  
              	    state._fsp--;
  
  
              	    				current.merge(this_ValidID_2);
              	    			
  
              	    				afterParserOrEnumRuleCall();
              	    			
  
              	    }
              	    break;
  
              	default :
              	    break loop48;
                  }
              } while (true);
  
  
              }
  
  
              }
  
  
              	leaveRule();
  
          }
  
              catch (RecognitionException re) {
                  recover(input,re);
                  appendSkippedTokens();
              }
          finally {
          }
          return current;
      }