docs: public final EObject ruleGrammar() throws RecognitionException {
          EObject current = null;
  
          Token otherlv_0=null;
          Token otherlv_2=null;
          Token otherlv_4=null;
          Token lv_definesHiddenTokens_6_0=null;
          Token otherlv_7=null;
          Token otherlv_9=null;
          Token otherlv_11=null;
          AntlrDatatypeRuleToken lv_name_1_0 = null;
  
          EObject lv_metamodelDeclarations_12_0 = null;
  
          EObject lv_rules_13_0 = null;
  
  
  
          	enterRule();
  
          try {
              // InternalXtext.g:77:2: ( (otherlv_0= 'grammar' ( (lv_name_1_0= ruleGrammarID ) ) (otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )* )? ( ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')' )? ( (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration ) )* ( (lv_rules_13_0= ruleAbstractRule ) )+ ) )
              // InternalXtext.g:78:2: (otherlv_0= 'grammar' ( (lv_name_1_0= ruleGrammarID ) ) (otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )* )? ( ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')' )? ( (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration ) )* ( (lv_rules_13_0= ruleAbstractRule ) )+ )
              {
              // InternalXtext.g:78:2: (otherlv_0= 'grammar' ( (lv_name_1_0= ruleGrammarID ) ) (otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )* )? ( ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')' )? ( (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration ) )* ( (lv_rules_13_0= ruleAbstractRule ) )+ )
              // InternalXtext.g:79:3: otherlv_0= 'grammar' ( (lv_name_1_0= ruleGrammarID ) ) (otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )* )? ( ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')' )? ( (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration ) )* ( (lv_rules_13_0= ruleAbstractRule ) )+
              {
              otherlv_0=(Token)match(input,11,FollowSets000.FOLLOW_3); 
  
              			newLeafNode(otherlv_0, grammarAccess.getGrammarAccess().getGrammarKeyword_0());
              		
              // InternalXtext.g:83:3: ( (lv_name_1_0= ruleGrammarID ) )
              // InternalXtext.g:84:4: (lv_name_1_0= ruleGrammarID )
              {
              // InternalXtext.g:84:4: (lv_name_1_0= ruleGrammarID )
              // InternalXtext.g:85:5: lv_name_1_0= ruleGrammarID
              {
  
              					newCompositeNode(grammarAccess.getGrammarAccess().getNameGrammarIDParserRuleCall_1_0());
              				
              pushFollow(FollowSets000.FOLLOW_4);
              lv_name_1_0=ruleGrammarID();
  
              state._fsp--;
  
  
              					if (current==null) {
              						current = createModelElementForParent(grammarAccess.getGrammarRule());
              					}
              					set(
              						current,
              						"name",
              						lv_name_1_0,
              						"org.eclipse.xtext.Xtext.GrammarID");
              					afterParserOrEnumRuleCall();
              				
  
              }
  
  
              }
  
              // InternalXtext.g:102:3: (otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )* )?
              int alt2=2;
              int LA2_0 = input.LA(1);
  
              if ( (LA2_0==12) ) {
                  alt2=1;
              }
              switch (alt2) {
                  case 1 :
                      // InternalXtext.g:103:4: otherlv_2= 'with' ( ( ruleGrammarID ) ) (otherlv_4= ',' ( ( ruleGrammarID ) ) )*
                      {
                      otherlv_2=(Token)match(input,12,FollowSets000.FOLLOW_3); 
  
                      				newLeafNode(otherlv_2, grammarAccess.getGrammarAccess().getWithKeyword_2_0());
                      			
                      // InternalXtext.g:107:4: ( ( ruleGrammarID ) )
                      // InternalXtext.g:108:5: ( ruleGrammarID )
                      {
                      // InternalXtext.g:108:5: ( ruleGrammarID )
                      // InternalXtext.g:109:6: ruleGrammarID
                      {
  
                      						if (current==null) {
                      							current = createModelElement(grammarAccess.getGrammarRule());
                      						}
                      					
  
                      						newCompositeNode(grammarAccess.getGrammarAccess().getUsedGrammarsGrammarCrossReference_2_1_0());
                      					
                      pushFollow(FollowSets000.FOLLOW_5);
                      ruleGrammarID();
  
                      state._fsp--;
  
  
                      						afterParserOrEnumRuleCall();
                      					
  
                      }
  
  
                      }
  
                      // InternalXtext.g:123:4: (otherlv_4= ',' ( ( ruleGrammarID ) ) )*
                      loop1:
                      do {
                          int alt1=2;
                          int LA1_0 = input.LA(1);
  
                          if ( (LA1_0==13) ) {
                              alt1=1;
                          }
  
  
                          switch (alt1) {
                      	case 1 :
                      	    // InternalXtext.g:124:5: otherlv_4= ',' ( ( ruleGrammarID ) )
                      	    {
                      	    otherlv_4=(Token)match(input,13,FollowSets000.FOLLOW_3); 
  
                      	    					newLeafNode(otherlv_4, grammarAccess.getGrammarAccess().getCommaKeyword_2_2_0());
                      	    				
                      	    // InternalXtext.g:128:5: ( ( ruleGrammarID ) )
                      	    // InternalXtext.g:129:6: ( ruleGrammarID )
                      	    {
                      	    // InternalXtext.g:129:6: ( ruleGrammarID )
                      	    // InternalXtext.g:130:7: ruleGrammarID
                      	    {
  
                      	    							if (current==null) {
                      	    								current = createModelElement(grammarAccess.getGrammarRule());
                      	    							}
                      	    						
  
                      	    							newCompositeNode(grammarAccess.getGrammarAccess().getUsedGrammarsGrammarCrossReference_2_2_1_0());
                      	    						
                      	    pushFollow(FollowSets000.FOLLOW_5);
                      	    ruleGrammarID();
  
                      	    state._fsp--;
  
  
                      	    							afterParserOrEnumRuleCall();
                      	    						
  
                      	    }
  
  
                      	    }
  
  
                      	    }
                      	    break;
  
                      	default :
                      	    break loop1;
                          }
                      } while (true);
  
  
                      }
                      break;
  
              }
  
              // InternalXtext.g:146:3: ( ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')' )?
              int alt5=2;
              int LA5_0 = input.LA(1);
  
              if ( (LA5_0==14) ) {
                  alt5=1;
              }
              switch (alt5) {
                  case 1 :
                      // InternalXtext.g:147:4: ( (lv_definesHiddenTokens_6_0= 'hidden' ) ) otherlv_7= '(' ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )? otherlv_11= ')'
                      {
                      // InternalXtext.g:147:4: ( (lv_definesHiddenTokens_6_0= 'hidden' ) )
                      // InternalXtext.g:148:5: (lv_definesHiddenTokens_6_0= 'hidden' )
                      {
                      // InternalXtext.g:148:5: (lv_definesHiddenTokens_6_0= 'hidden' )
                      // InternalXtext.g:149:6: lv_definesHiddenTokens_6_0= 'hidden'
                      {
                      lv_definesHiddenTokens_6_0=(Token)match(input,14,FollowSets000.FOLLOW_6); 
  
                      						newLeafNode(lv_definesHiddenTokens_6_0, grammarAccess.getGrammarAccess().getDefinesHiddenTokensHiddenKeyword_3_0_0());
                      					
  
                      						if (current==null) {
                      							current = createModelElement(grammarAccess.getGrammarRule());
                      						}
                      						setWithLastConsumed(current, "definesHiddenTokens", true, "hidden");
                      					
  
                      }
  
  
                      }
  
                      otherlv_7=(Token)match(input,15,FollowSets000.FOLLOW_7); 
  
                      				newLeafNode(otherlv_7, grammarAccess.getGrammarAccess().getLeftParenthesisKeyword_3_1());
                      			
                      // InternalXtext.g:165:4: ( ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )* )?
                      int alt4=2;
                      int LA4_0 = input.LA(1);
  
                      if ( (LA4_0==RULE_ID||(LA4_0>=39 && LA4_0<=40)) ) {
                          alt4=1;
                      }
                      switch (alt4) {
                          case 1 :
                              // InternalXtext.g:166:5: ( ( ruleRuleID ) ) (otherlv_9= ',' ( ( ruleRuleID ) ) )*
                              {
                              // InternalXtext.g:166:5: ( ( ruleRuleID ) )
                              // InternalXtext.g:167:6: ( ruleRuleID )
                              {
                              // InternalXtext.g:167:6: ( ruleRuleID )
                              // InternalXtext.g:168:7: ruleRuleID
                              {
  
                              							if (current==null) {
                              								current = createModelElement(grammarAccess.getGrammarRule());
                              							}
                              						
  
                              							newCompositeNode(grammarAccess.getGrammarAccess().getHiddenTokensAbstractRuleCrossReference_3_2_0_0());
                              						
                              pushFollow(FollowSets000.FOLLOW_8);
                              ruleRuleID();
  
                              state._fsp--;
  
  
                              							afterParserOrEnumRuleCall();
                              						
  
                              }
  
  
                              }
  
                              // InternalXtext.g:182:5: (otherlv_9= ',' ( ( ruleRuleID ) ) )*
                              loop3:
                              do {
                                  int alt3=2;
                                  int LA3_0 = input.LA(1);
  
                                  if ( (LA3_0==13) ) {
                                      alt3=1;
                                  }
  
  
                                  switch (alt3) {
                              	case 1 :
                              	    // InternalXtext.g:183:6: otherlv_9= ',' ( ( ruleRuleID ) )
                              	    {
                              	    otherlv_9=(Token)match(input,13,FollowSets000.FOLLOW_3); 
  
                              	    						newLeafNode(otherlv_9, grammarAccess.getGrammarAccess().getCommaKeyword_3_2_1_0());
                              	    					
                              	    // InternalXtext.g:187:6: ( ( ruleRuleID ) )
                              	    // InternalXtext.g:188:7: ( ruleRuleID )
                              	    {
                              	    // InternalXtext.g:188:7: ( ruleRuleID )
                              	    // InternalXtext.g:189:8: ruleRuleID
                              	    {
  
                              	    								if (current==null) {
                              	    									current = createModelElement(grammarAccess.getGrammarRule());
                              	    								}
                              	    							
  
                              	    								newCompositeNode(grammarAccess.getGrammarAccess().getHiddenTokensAbstractRuleCrossReference_3_2_1_1_0());
                              	    							
                              	    pushFollow(FollowSets000.FOLLOW_8);
                              	    ruleRuleID();
  
                              	    state._fsp--;
  
  
                              	    								afterParserOrEnumRuleCall();
                              	    							
  
                              	    }
  
  
                              	    }
  
  
                              	    }
                              	    break;
  
                              	default :
                              	    break loop3;
                                  }
                              } while (true);
  
  
                              }
                              break;
  
                      }
  
                      otherlv_11=(Token)match(input,16,FollowSets000.FOLLOW_4); 
  
                      				newLeafNode(otherlv_11, grammarAccess.getGrammarAccess().getRightParenthesisKeyword_3_3());
                      			
  
                      }
                      break;
  
              }
  
              // InternalXtext.g:210:3: ( (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration ) )*
              loop6:
              do {
                  int alt6=2;
                  int LA6_0 = input.LA(1);
  
                  if ( (LA6_0==18||LA6_0==20) ) {
                      alt6=1;
                  }
  
  
                  switch (alt6) {
              	case 1 :
              	    // InternalXtext.g:211:4: (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration )
              	    {
              	    // InternalXtext.g:211:4: (lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration )
              	    // InternalXtext.g:212:5: lv_metamodelDeclarations_12_0= ruleAbstractMetamodelDeclaration
              	    {
  
              	    					newCompositeNode(grammarAccess.getGrammarAccess().getMetamodelDeclarationsAbstractMetamodelDeclarationParserRuleCall_4_0());
              	    				
              	    pushFollow(FollowSets000.FOLLOW_4);
              	    lv_metamodelDeclarations_12_0=ruleAbstractMetamodelDeclaration();
  
              	    state._fsp--;
  
  
              	    					if (current==null) {
              	    						current = createModelElementForParent(grammarAccess.getGrammarRule());
              	    					}
              	    					add(
              	    						current,
              	    						"metamodelDeclarations",
              	    						lv_metamodelDeclarations_12_0,
              	    						"org.eclipse.xtext.Xtext.AbstractMetamodelDeclaration");
              	    					afterParserOrEnumRuleCall();
              	    				
  
              	    }
  
  
              	    }
              	    break;
  
              	default :
              	    break loop6;
                  }
              } while (true);
  
              // InternalXtext.g:229:3: ( (lv_rules_13_0= ruleAbstractRule ) )+
              int cnt7=0;
              loop7:
              do {
                  int alt7=2;
                  int LA7_0 = input.LA(1);
  
                  if ( (LA7_0==RULE_ID||(LA7_0>=21 && LA7_0<=22)||(LA7_0>=39 && LA7_0<=40)||LA7_0==47||LA7_0==50) ) {
                      alt7=1;
                  }
  
  
                  switch (alt7) {
              	case 1 :
              	    // InternalXtext.g:230:4: (lv_rules_13_0= ruleAbstractRule )
              	    {
              	    // InternalXtext.g:230:4: (lv_rules_13_0= ruleAbstractRule )
              	    // InternalXtext.g:231:5: lv_rules_13_0= ruleAbstractRule
              	    {
  
              	    					newCompositeNode(grammarAccess.getGrammarAccess().getRulesAbstractRuleParserRuleCall_5_0());
              	    				
              	    pushFollow(FollowSets000.FOLLOW_9);
              	    lv_rules_13_0=ruleAbstractRule();
  
              	    state._fsp--;
  
  
              	    					if (current==null) {
              	    						current = createModelElementForParent(grammarAccess.getGrammarRule());
              	    					}
              	    					add(
              	    						current,
              	    						"rules",
              	    						lv_rules_13_0,
              	    						"org.eclipse.xtext.Xtext.AbstractRule");
              	    					afterParserOrEnumRuleCall();
              	    				
  
              	    }
  
  
              	    }
              	    break;
  
              	default :
              	    if ( cnt7 >= 1 ) break loop7;
                          EarlyExitException eee =
                              new EarlyExitException(7, input);
                          throw eee;
                  }
                  cnt7++;
              } while (true);
  
  
              }
  
  
              }
  
  
              	leaveRule();
  
          }
  
              catch (RecognitionException re) {
                  recover(input,re);
                  appendSkippedTokens();
              }
          finally {
          }
          return current;
      }