docs: public final EObject ruleCharacterRange() throws RecognitionException {
          EObject current = null;
  
          Token otherlv_2=null;
          EObject this_Keyword_0 = null;
  
          EObject lv_right_3_0 = null;
  
  
  
          	enterRule();
  
          try {
              // InternalXtext.g:3480:2: ( (this_Keyword_0= ruleKeyword ( () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) ) )? ) )
              // InternalXtext.g:3481:2: (this_Keyword_0= ruleKeyword ( () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) ) )? )
              {
              // InternalXtext.g:3481:2: (this_Keyword_0= ruleKeyword ( () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) ) )? )
              // InternalXtext.g:3482:3: this_Keyword_0= ruleKeyword ( () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) ) )?
              {
  
              			newCompositeNode(grammarAccess.getCharacterRangeAccess().getKeywordParserRuleCall_0());
              		
              pushFollow(FollowSets000.FOLLOW_49);
              this_Keyword_0=ruleKeyword();
  
              state._fsp--;
  
  
              			current = this_Keyword_0;
              			afterParserOrEnumRuleCall();
              		
              // InternalXtext.g:3490:3: ( () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) ) )?
              int alt73=2;
              int LA73_0 = input.LA(1);
  
              if ( (LA73_0==49) ) {
                  alt73=1;
              }
              switch (alt73) {
                  case 1 :
                      // InternalXtext.g:3491:4: () otherlv_2= '..' ( (lv_right_3_0= ruleKeyword ) )
                      {
                      // InternalXtext.g:3491:4: ()
                      // InternalXtext.g:3492:5: 
                      {
  
                      					current = forceCreateModelElementAndSet(
                      						grammarAccess.getCharacterRangeAccess().getCharacterRangeLeftAction_1_0(),
                      						current);
                      				
  
                      }
  
                      otherlv_2=(Token)match(input,49,FollowSets000.FOLLOW_11); 
  
                      				newLeafNode(otherlv_2, grammarAccess.getCharacterRangeAccess().getFullStopFullStopKeyword_1_1());
                      			
                      // InternalXtext.g:3502:4: ( (lv_right_3_0= ruleKeyword ) )
                      // InternalXtext.g:3503:5: (lv_right_3_0= ruleKeyword )
                      {
                      // InternalXtext.g:3503:5: (lv_right_3_0= ruleKeyword )
                      // InternalXtext.g:3504:6: lv_right_3_0= ruleKeyword
                      {
  
                      						newCompositeNode(grammarAccess.getCharacterRangeAccess().getRightKeywordParserRuleCall_1_2_0());
                      					
                      pushFollow(FollowSets000.FOLLOW_2);
                      lv_right_3_0=ruleKeyword();
  
                      state._fsp--;
  
  
                      						if (current==null) {
                      							current = createModelElementForParent(grammarAccess.getCharacterRangeRule());
                      						}
                      						set(
                      							current,
                      							"right",
                      							lv_right_3_0,
                      							"org.eclipse.xtext.Xtext.Keyword");
                      						afterParserOrEnumRuleCall();
                      					
  
                      }
  
  
                      }
  
  
                      }
                      break;
  
              }
  
  
              }
  
  
              }
  
  
              	leaveRule();
  
          }
  
              catch (RecognitionException re) {
                  recover(input,re);
                  appendSkippedTokens();
              }
          finally {
          }
          return current;
      }