/// <summary> /// Reads <see cref="SyntaxToken" />s from a GraphQL /// <paramref name="source" /> and returns the first token. /// </summary> /// <param name="source"> /// The GraphQL source that shall be tokenized. /// </param> /// <returns> /// Returns the first token of the given /// GraphQL <paramref name="source" />. /// </returns> /// <exception cref="SyntaxException"> /// There are unexpected tokens in the given <paramref name="source" />. /// </exception> /// <exception cref="ArgumentNullException"> /// <paramref name="source" /> is null. /// </exception> public SyntaxToken Read(ISource source) { if (source == null) { throw new ArgumentNullException(nameof(source)); } var state = new LexerState(source.Text); try { var start = new SyntaxToken(TokenKind.StartOfFile, 0, 0, state.Line, state.Column, null); SyntaxToken current = start; do { SyntaxToken previous = current; current = ReadNextToken(state, previous); previous.Next = current; }while (current.Kind != TokenKind.EndOfFile); return(start); } catch (Exception ex) { throw new SyntaxException(state, "Unexpected token sequence.", ex); } }
internal SyntaxException(LexerState context, string message) : base(message) { Position = context.Position; Line = context.Line; Column = context.Column; SourceText = context.SourceText; }
internal SyntaxException(LexerState context, string message) : base(message) { if (context == null) { throw new ArgumentNullException(nameof(context)); } Position = context.Position; Line = context.Line; Column = context.Column; SourceText = context.SourceText; }
/// <summary> /// Reads the token that comes after the /// <paramref name="previous"/>-token. /// </summary> /// <returns> /// Returns token that comes after the /// <paramref name="previous"/>-token. /// </returns> /// <param name="state">The lexer state.</param> /// <param name="previous">The previous-token.</param> private static SyntaxToken ReadNextToken( LexerState state, SyntaxToken previous) { SkipWhitespaces(state); state.UpdateColumn(); if (state.IsEndOfStream()) { return(new SyntaxToken(TokenKind.EndOfFile, state.Column, previous.End, state.Line, state.Column, previous)); } var code = state.SourceText[state.Position]; if (code.IsLetterOrUnderscore()) { return(ReadNameToken(state, previous)); } if (code.IsPunctuator()) { return(ReadPunctuatorToken(state, previous, in code)); } if (code.IsDigitOrMinus()) { return(ReadNumberToken(state, previous, in code)); } if (code.IsHash()) { return(ReadCommentToken(state, previous)); } if (code.IsQuote()) { if (state.SourceText[state.Position + 1].IsQuote() && state.SourceText[state.Position + 2].IsQuote()) { state.Position += 2; return(ReadBlockStringToken(state, previous)); } return(ReadStringValueToken(state, previous)); } throw new SyntaxException(state, "Unexpected character."); }
/// <summary> /// Reads punctuator tokens as specified in /// http://facebook.github.io/graphql/October2016/#sec-Punctuators /// one of ! $ ( ) ... : = @ [ ] { | } /// additionaly the reader will tokenize ampersands. /// </summary> /// <param name="state"> /// The lexer state. /// </param> /// <param name="previous"> /// The previous-token. /// </param> /// <param name="firstCode"> /// The first character of the punctuator. /// </param> /// <returns> /// Returns the punctuator token read from the current lexer state. /// </returns> private static SyntaxToken ReadPunctuatorToken( LexerState state, SyntaxToken previous, in char firstCode)