/// <summary> /// Consumes a token and asserts that it is of a given kind. Calls <see cref="Move"/> and returns /// the previous value of <see cref="Current"/>. /// </summary> /// <exception cref="ArgumentException">Thrown if <paramref name="requiredKind"/> is /// <see cref="TokenKind.Default"/>.</exception> /// <param name="requiredKind">The required kind. This may not be /// <see cref="TokenKind.Default"/>.</param> /// <returns>The next token for consumption.</returns> public Token Require(TokenKind requiredKind) { if (requiredKind == TokenKind.Default) { throw new ArgumentException(Strings.RequiredInvalidToken, "requiredKind"); } Token result = this.Current; if (result.Kind != requiredKind) { throw G4ParseFailureException.UnexpectedToken(this.Current); } this.Move(); return(result); }
/// <summary>Parses a G4 non-terminal.</summary> /// <exception cref="G4ParseFailureException">Thrown when the input is not valid.</exception> /// <returns>A GrammarSymbol containing the non-terminal.</returns> public GrammarSymbol ParseNonTerminal() { ImmutableArray <Annotation> annotations = _iterator.ConsumeAnnotations(); Token current = _iterator.Consume(); if (current.Kind == TokenKind.Identifier) { return(new GrammarSymbol(current, SymbolKind.Identifier, annotations)); } if (current.Kind == TokenKind.Lparen) { GrammarSymbol result = this.ParseAlternation(); _iterator.Require(TokenKind.Rparen); return(result); } if (current.Kind != TokenKind.String) { throw G4ParseFailureException.UnexpectedToken(current); } if (_iterator.Current.Kind == TokenKind.Dots) { CheckForBadCharacterRangeCharacterLength(current); _iterator.Move(); // dots Token secondString = _iterator.Require(TokenKind.String); CheckForBadCharacterRangeCharacterLength(secondString); CheckForCorrectlyOrderedCharacterRange(current, secondString); return(new GrammarSymbol(current, secondString, SymbolKind.CharacterRange)); } else { return(new GrammarSymbol(current, SymbolKind.String)); } }