Beispiel #1
0
 public SyntaxError(Source source, int position, String description)
 {
     Source = source;
     Position = position;
     Description = description;
     Location = new SourceLocation(source, position);
 }
        public void SimpleNonNullType()
        {
            var body = new Source(
                @"
type Hello {
  world: String!
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new TypeDefinition
                    {
                        Name = new Name("Hello", new Location(6, 11, body)),
                        Fields = ImmutableArray.Create(
                            new FieldDefinition
                            {
                                Name = new Name("world", new Location(16, 21, body)),
                                Type = new NonNullType
                                {
                                    Type = new NamedType("String", 23, 29, body),
                                    Location = new Location(23, 30, body),
                                },
                                Location = new Location(16, 30, body),
                            }),
                        Location = new Location(1, 32, body),
                    }),
                Location = new Location(1, 32, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
Beispiel #3
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Parser"/> class.
 /// Returns the parser object that is used to store state throughout the
 /// process of parsing.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="options">The options.</param>
 protected Parser(Source source, ParseOptions options)
 {
     Source = source;
     Options = options ?? new ParseOptions();
     _lexToken = new Lexer(source);
     PrevEnd = 0;
     Token = _lexToken.NextToken();
 }
Beispiel #4
0
 public SourceLocation(Source source, int position)
 {
     Line = 1;
     Column = position + 1;
     Match match = LineRegexp.Match(source.Body);
     while (match != Match.Empty
         && match.Index < position)
     {
         Line += 1;
         Column = position + 1 - (match.Index + match.Groups[0].Length);
         match = match.NextMatch();
     }
 }
 public void SimpleTypeInheritingInterface()
 {
     var body = new Source("type Hello implements World { }");
     var doc = SchemaParser.ParseSchema(body);
     var expected = new SchemaDocument
     {
         Definitions = ImmutableArray.Create<SchemaDefinition>(
             new TypeDefinition
             {
                 Name = new Name("Hello", new Location(5, 10, body)),
                 Interfaces = ImmutableArray.Create(new NamedType("World", 22, 27, body)),
                 Location = new Location(0, 31, body),
             }),
         Location = new Location(0, 31, body),
     };
     doc.ShouldBeEquivalentToDeepDynamic(expected);
 }
Beispiel #6
0
 /// <summary>
 /// Highlights the source at location.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="location">The location.</param>
 /// <returns></returns>
 public static String HighlightSourceAtLocation(Source source, SourceLocation location)
 {
     var line = location.Line;
     var prevLineNum = (line - 1).ToString();
     var lineNum = line.ToString();
     var nextLineNum = (line + 1).ToString();
     var padLen = nextLineNum.Length;
     var lines = SourceLocation.LineRegexp.Split(source.Body);
     var res = (line >= 2
         ? prevLineNum.PadLeft(padLen) + ": " + lines[line - 2] + "\n"
         : "") +
               lineNum.PadLeft(padLen) + ": " + lines[line - 1] + "\n" +
               "".PadLeft(2 + padLen + location.Column - 1) + "^\n" +
               (line < lines.Length
                   ? nextLineNum.PadLeft(padLen) + ": " + lines[line] + "\n"
                   : "");
     return res;
 }
        public void SimpleFieldWithListArg()
        {
            var body = new Source(
                @"
type Hello {
  world(things: [String]): String
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new TypeDefinition
                    {
                        Name = new Name("Hello", new Location(6, 11, body)),
                        Fields = ImmutableArray.Create(
                            new FieldDefinition
                            {
                                Name = new Name("world", new Location(16, 21, body)),
                                Type = new NamedType("String", 41, 47, body),
                                Arguments = ImmutableArray.Create(
                                    new InputValueDefinition
                                    {
                                        Name = new Name("things", new Location(22, 28, body)),
                                        Type = new ListType
                                        {
                                            Type = new NamedType("String", 31, 37, body),
                                            Location = new Location(30, 38, body),
                                        },
                                        DefaultValue = null,
                                        Location = new Location(22, 38, body),
                                    }),
                                Location = new Location(16, 47, body),
                            }),
                        Location = new Location(1, 49, body),
                    }),
                Location = new Location(1, 49, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
        public void SimpleFieldWithArgWithDefaultValue()
        {
            var body = new Source(
                @"
type Hello {
  world(flag: Boolean = true): String
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new TypeDefinition
                    {
                        Name = new Name("Hello", new Location(6, 11, body)),
                        Fields = ImmutableArray.Create(
                            new FieldDefinition
                            {
                                Name = new Name("world", new Location(16, 21, body)),
                                Type = new NamedType("String", 45, 51, body),
                                Arguments = ImmutableArray.Create(
                                    new InputValueDefinition
                                    {
                                        Name = new Name("flag", new Location(22, 26, body)),
                                        Type = new NamedType("Boolean", 28, 35, body),
                                        DefaultValue = new BooleanValue
                                        {
                                            Value = true,
                                            Location = new Location(38, 42, body),
                                        },
                                        Location = new Location(22, 42, body),
                                    }),
                                Location = new Location(16, 51, body),
                            }),
                        Location = new Location(1, 53, body),
                    }),
                Location = new Location(1, 53, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
        public void SimpleInterface()
        {
            var body = new Source(
                @"
interface Hello {
  world: String
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new InterfaceDefinition
                    {
                        Name = new Name("Hello", new Location(11, 16, body)),
                        Fields = ImmutableArray.Create(
                            new FieldDefinition
                            {
                                Name = new Name("world", new Location(21, 26, body)),
                                Type = new NamedType("String", 28, 34, body),
                                Location = new Location(21, 34, body),
                            }),
                        Location = new Location(1, 36, body),
                    }),
                Location = new Location(1, 36, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
 public void DoubleValueEnum()
 {
     var body = new Source("enum Hello { WO, RLD }");
     var doc = SchemaParser.ParseSchema(body);
     var expected = new SchemaDocument
     {
         Definitions = ImmutableArray.Create<SchemaDefinition>(
             new EnumDefinition
             {
                 Name = new Name("Hello", new Location(5, 10, body)),
                 Values = ImmutableArray.Create(
                     new EnumValueDefinition("WO", new Location(13, 15, body)),
                     new EnumValueDefinition("RLD", new Location(17, 20, body))),
                 Location = new Location(0, 22, body),
             }),
         Location = new Location(0, 22, body),
     };
     doc.ShouldBeEquivalentToDeepDynamic(expected);
 }
Beispiel #11
0
 public static void ParseErr(Source source, string message)
 {
     Action action = () => Parser.Parse(source);
     action.ShouldThrow<SyntaxError>().Where(err => err.Message.StartsWith(message));
 }
Beispiel #12
0
 /// <summary>
 /// Reads an alphanumeric + underscore name from the source.
 /// [_A-Za-z][_0-9A-Za-z]*
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="position">The position.</param>
 /// <returns></returns>
 private static Token ReadName(Source source, int position)
 {
     var body = source.Body;
       var bodyLength = body.Length;
       var end = position + 1;
       char code;
       while (
     end != bodyLength &&
     (
       (code = body[end]) == 95 || // _
       code >= 48 && code <= 57 || // 0-9
       code >= 65 && code <= 90 || // A-Z
       code >= 97 && code <= 122 // a-z
     )
       )
       {
     ++end;
       }
       return new Token(
     TokenKind.NAME,
     position,
     end,
     body.Substring(position, end - position)
       );
 }
 public void Scalar()
 {
     var body = new Source("scalar Hello");
     var doc = SchemaParser.ParseSchema(body);
     var expected = new SchemaDocument
     {
         Definitions = ImmutableArray.Create<SchemaDefinition>(
             new ScalarDefinition
             {
                 Name = new Name("Hello", new Location(7, 12, body)),
                 Location = new Location(0, 12, body),
             }),
         Location = new Location(0, 12, body),
     };
     doc.ShouldBeEquivalentToDeepDynamic(expected);
 }
Beispiel #14
0
 /// <summary>
 /// Given a string containing a GraphQL value, parse the AST for that value.
 /// Throws GraphQLError if a syntax error is encountered.
 ///
 /// This is useful within tools that operate upon GraphQL Values directly and
 /// in isolation of complete GraphQL documents.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="options">The options.</param>
 /// <returns></returns>
 public static IValue ParseValue(Source source, ParseOptions options = null)
 {
     var parser = new Parser(source, options);
     return parser.ParseValueLiteral(false);
 }
        public void SimpleInputObject()
        {
            var body = new Source(
@"
input Hello {
  world: String
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new InputObjectDefinition
                    {
                        Name = new Name("Hello", new Location(7, 12, body)),
                        Fields = ImmutableArray.Create(
                            new InputValueDefinition
                            {
                                Name = new Name("world", new Location(17, 22, body)),
                                Type = new NamedType("String", 24, 30, body),
                                Location = new Location(17, 30, body),
                            }),
                        Location = new Location(1, 32, body),
                    }),
                Location = new Location(1, 32, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
Beispiel #16
0
 public void TestToStringStackWalker()
 {
     var source = new Source("{\n  node(id: 4) {\n    id,\n    name\n  }\n}\n");
     var result = Parser.Parse(source);
     var visitor = new ToStringStackWalker(_output);
     var visited = visitor.Visit(result);
     result.Should().Be(visited);
 }
Beispiel #17
0
 /// <summary>
 /// Initializes a new instance of the <see cref="Lexer"/> class.
 /// Given a Source object, this returns a Lexer for that source.
 /// A Lexer is a function that acts like a generator in that every time
 /// it is called, it returns the next token in the Source. Assuming the
 /// source lexes, the final Token emitted by the lexer will be of kind
 /// EOF, after which the lexer will repeatedly return EOF tokens whenever
 /// called.
 /// 
 /// The argument to the lexer function is optional, and can be used to
 /// rewind or fast forward the lexer to a new position in the source.
 /// </summary>
 public Lexer(Source source)
 {
     Source = source;
     PrevPosition = 0;
 }
Beispiel #18
0
        /// <summary>
        /// Gets the next token from the source starting at the given position.
        /// 
        /// This skips over whitespace and comments until it finds the next lexable
        /// token, then lexes punctuators immediately or calls the appropriate helper
        /// fucntion for more complicated tokens.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="fromPosition">The from position.</param>
        /// <returns></returns>
        private Token ReadToken(Source source, int fromPosition)
        {
            var body = source.Body;
            var bodyLength = body.Length;

            var position = PositionAfterWhitespace(body, fromPosition);

            if (position >= bodyLength)
            {
                return new Token(TokenKind.EOF, position, position);
            }

            var code = body[position];
            switch ((int)code) {
            // !
            case 33: return new Token(TokenKind.BANG, position, position + 1);
            // $
            case 36: return new Token(TokenKind.DOLLAR, position, position + 1);
            // (
            case 40: return new Token(TokenKind.PAREN_L, position, position + 1);
            // )
            case 41: return new Token(TokenKind.PAREN_R, position, position + 1);
            // .
            case 46:
                if (position + 2 < bodyLength &&
                    body[position + 1] == 46 &&
                    body[position + 2] == 46) {
                return new Token(TokenKind.SPREAD, position, position + 3);
                }
                break;
            // :
            case 58: return new Token(TokenKind.COLON, position, position + 1);
            // =
            case 61: return new Token(TokenKind.EQUALS, position, position + 1);
            // @
            case 64: return new Token(TokenKind.AT, position, position + 1);
            // [
            case 91: return new Token(TokenKind.BRACKET_L, position, position + 1);
            // ]
            case 93: return new Token(TokenKind.BRACKET_R, position, position + 1);
            // {
            case 123: return new Token(TokenKind.BRACE_L, position, position + 1);
            // |
            case 124: return new Token(TokenKind.PIPE, position, position + 1);
            // }
            case 125: return new Token(TokenKind.BRACE_R, position, position + 1);
            // A-Z
            case 65: case 66: case 67: case 68: case 69: case 70: case 71: case 72:
            case 73: case 74: case 75: case 76: case 77: case 78: case 79: case 80:
            case 81: case 82: case 83: case 84: case 85: case 86: case 87: case 88:
            case 89: case 90:
            // _
            case 95:
            // a-z
            case 97: case 98: case 99: case 100: case 101: case 102: case 103: case 104:
            case 105: case 106: case 107: case 108: case 109: case 110: case 111:
            case 112: case 113: case 114: case 115: case 116: case 117: case 118:
            case 119: case 120: case 121: case 122:
                return ReadName(source, position);
            // -
            case 45:
            // 0-9
            case 48: case 49: case 50: case 51: case 52:
            case 53: case 54: case 55: case 56: case 57:
                return ReadNumber(source, position, code);
            // "
            case 34: return ReadString(source, position);
            }

            throw new SyntaxError(source, position,
                $"Unexpected character \"{char.ConvertFromUtf32(code)}\".");
        }
Beispiel #19
0
        /// <summary>
        /// Reads a string token from the source file.
        /// "([^"\\\u000A\u000D\u2028\u2029]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="start">The start.</param>
        /// <returns></returns>
        private static Token ReadString(Source source, int start)
        {
            var body = source.Body;
            var position = start + 1;
            var chunkStart = position;
            var code = 0;
            var value = "";

            while (
                position < body.Length &&
                (code = body[position]) != 34 &&
                code != 10 && code != 13 && code != 0x2028 && code != 0x2029
            ) {
                ++position;
                if (code == 92) { // \
                    value += body.Substring(chunkStart, position -1 - chunkStart);
                    code = body[position];
                    switch (code) {
                        case 34: value += '"'; break;
                        case 47: value += '/'; break;
                        case 92: value += '\\'; break;
                        case 98: value += '\b'; break;
                        case 102: value += '\f'; break;
                        case 110: value += '\n'; break;
                        case 114: value += '\r'; break;
                        case 116: value += '\t'; break;
                        case 117:
                            var charCode = UniCharCode(
                                body[position + 1],
                                body[position + 2],
                                body[position + 3],
                                body[position + 4]
                            );
                            if (charCode < 0) {
                                throw new SyntaxError(source, position, "Bad character escape sequence");
                            }
                            value += char.ConvertFromUtf32(charCode);
                            position += 4;
                        break;
                    default:
                        throw new SyntaxError(source, position, "Bad character escape sequence");
                    }
                    ++position;
                    chunkStart = position;
                }
            }

            if (code != 34) {
                throw new SyntaxError(source, position, "Unterminated string");
            }

            value += body.Substring(chunkStart, position - chunkStart);
            return new Token(TokenKind.STRING, start, position + 1, value);
        }
Beispiel #20
0
        /// <summary>
        /// Reads a number token from the source file, either a float
        /// or an int depending on whether a decimal point appears.
        /// 
        /// Int:   -?(0|[1-9][0-9]*)
        /// Float: -?(0|[1-9][0-9]*)(\.[0-9]+)?((E|e)(+|-)?[0-9]+)?
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="start">The start.</param>
        /// <param name="firstCode">The first code.</param>
        /// <returns></returns>
        private static Token ReadNumber(Source source, int start, int firstCode)
        {
            var code = firstCode;
            var body = source.Body;
            var position = start;
            var isFloat = false;

            if (code == 45) { // -
                code = SafeCode(body, ++position);
            }

            if (code == 48) { // 0
                code = SafeCode(body, ++position);
            }
            else if (code >= 49 && code <= 57)
            { // 1 - 9
                do {
                    code = SafeCode(body, ++position);
                } while (code >= 48 && code <= 57); // 0 - 9
            }
            else
            {
                throw new SyntaxError(source, position, "Invalid number");
            }

            if (code == 46) // .
            {
                isFloat = true;

                code = SafeCode(body, ++position);
                if (code >= 48 && code <= 57)
                {
                    // 0 - 9
                    do
                    {
                        code = SafeCode(body, ++position);
                    } while (code >= 48 && code <= 57); // 0 - 9
                }
                else
                {
                    throw new SyntaxError(source, position, "Invalid number");
                }
            }

            if (code == 69 || code == 101) // E e
            {
                isFloat = true;

                code = SafeCode(body, ++position);
                if (code == 43 || code == 45) { // + -
                    code = SafeCode(body, ++position);
                }
                if (code >= 48 && code <= 57) { // 0 - 9
                    do {
                        code = SafeCode(body, ++position);
                    } while (code >= 48 && code <= 57); // 0 - 9
                } else {
                    throw new SyntaxError(source, position, "Invalid number");
                }
            }

            return new Token(
                isFloat ? TokenKind.FLOAT : TokenKind.INT,
                start,
                position,
                body.Substring(start, position - start)
            );
        }
        public void SimpleFieldWithTwoArgs()
        {
            var body = new Source(
                @"
type Hello {
  world(argOne: Boolean, argTwo: Int): String
}".ToLF());
            var doc = SchemaParser.ParseSchema(body);
            var expected = new SchemaDocument
            {
                Definitions = ImmutableArray.Create<SchemaDefinition>(
                    new TypeDefinition
                    {
                        Name = new Name("Hello", new Location(6, 11, body)),
                        Fields = ImmutableArray.Create(
                            new FieldDefinition
                            {
                                Name = new Name("world", new Location(16, 21, body)),
                                Type = new NamedType("String", 53, 59, body),
                                Arguments = ImmutableArray.Create(
                                    new InputValueDefinition
                                    {
                                        Name = new Name("argOne", new Location(22, 28, body)),
                                        Type = new NamedType("Boolean", 30, 37, body),
                                        DefaultValue = null,
                                        Location = new Location(22, 37, body),
                                    },
                                    new InputValueDefinition
                                    {
                                        Name = new Name("argTwo", new Location(39, 45, body)),
                                        Type = new NamedType("Int", 47, 50, body),
                                        DefaultValue = null,
                                        Location = new Location(39, 50, body),
                                    }),
                                Location = new Location(16, 59, body),
                            }),
                        Location = new Location(1, 61, body),
                    }),
                Location = new Location(1, 61, body),
            };
            doc.ShouldBeEquivalentToDeepDynamic(expected);
        }
 public void UnionWithTwoTypes()
 {
     var body = new Source("union Hello = Wo | Rld");
     var doc = SchemaParser.ParseSchema(body);
     var expected = new SchemaDocument
     {
         Definitions = ImmutableArray.Create<SchemaDefinition>(
             new UnionDefinition
             {
                 Name = new Name("Hello", new Location(6, 11, body)),
                 Types = ImmutableArray.Create(
                     new NamedType("Wo", 14, 16, body),
                     new NamedType("Rld", 19, 22, body)),
                 Location = new Location(0, 22, body),
             }),
         Location = new Location(0, 22, body),
     };
     doc.ShouldBeEquivalentToDeepDynamic(expected);
 }
Beispiel #23
0
 public NamedType(String value, int start, int end, Source source = null)
 {
     Location = new Location(start, end, source);
     Name     = new Name(value, Location);
 }
Beispiel #24
0
 public void TestToStringVisitor()
 {
     var source = new Source("{\n  node(id: 4) {\n    id,\n    name\n  }\n}\n");
     var result = Parser.Parse(source);
     var visitor = new ToStringVisitor(_output);
     visitor.Visit(result);
 }
Beispiel #25
0
 /// <summary>
 /// Given a GraphQL source, parses it into a Document.
 /// Throws GraphQLError if a syntax error is encountered.
 /// </summary>
 /// <param name="source">The source.</param>
 /// <param name="options">The options.</param>
 /// <returns></returns>
 public static Document Parse(Source source, ParseOptions options = null)
 {
     var parser = new Parser(source, options);
     return parser.ParseDocument();
 }
Beispiel #26
0
 public Location(int start, int end, Source source = null)
 {
     Start  = start;
     End    = end;
     Source = source;
 }
Beispiel #27
0
 public void ParseCreatesAst()
 {
     var source = new Source("{\n  node(id: 4) {\n    id,\n    name\n  }\n}\n");
     var result = Parser.Parse(source);
     result.ShouldBeEquivalentToDeepDynamic(new Document
     {
         Location = new Location(0, 41, source),
         Definitions = ImmutableArray.Create<IDefinition>(
             new OperationDefinition
             {
                 Location = new Location(0, 40, source),
                 Operation = OperationType.Query,
                 Name = null,
                 VariableDefinitions = ImmutableArray<VariableDefinition>.Empty,
                 Directives = ImmutableArray<Directive>.Empty,
                 SelectionSet = new SelectionSet
                 {
                     Location = new Location(0, 40, source),
                     Selections = ImmutableArray.Create<ISelection>(
                         new Field
                         {
                             Location = new Location(4, 38, source),
                             Alias = null,
                             Name = new Name
                             {
                                 Location = new Location(4, 8, source),
                                 Value = "node",
                             },
                             Arguments = ImmutableArray.Create(
                                 new Argument
                                 {
                                     Name = new Name
                                     {
                                         Location = new Location(9, 11, source),
                                         Value = "id",
                                     },
                                     Value = new IntValue
                                     {
                                         Location = new Location(13, 14, source),
                                         Value = "4",
                                     },
                                     Location = new Location(9, 14, source),
                                 }
                             ),
                             Directives = ImmutableArray<Directive>.Empty,
                             SelectionSet = new SelectionSet
                             {
                                 Location = new Location(16, 38, source),
                                 Selections = ImmutableArray.Create<ISelection>(
                                     new Field
                                     {
                                         Location = new Location(22, 24, source),
                                         Alias = null,
                                         Name = new Name
                                         {
                                             Location = new Location(22, 24, source),
                                             Value = "id",
                                         },
                                         Arguments = ImmutableArray<Argument>.Empty,
                                         Directives = ImmutableArray<Directive>.Empty,
                                         SelectionSet = null,
                                     },
                                     new Field
                                     {
                                         Location = new Location(30, 34, source),
                                         Alias = null,
                                         Name = new Name
                                         {
                                             Location = new Location(30, 34, source),
                                             Value = "name",
                                         },
                                         Arguments = ImmutableArray<Argument>.Empty,
                                         Directives = ImmutableArray<Directive>.Empty,
                                         SelectionSet = null,
                                     }
                                 )
                             }
                         }
                     )
                 }
             }
         )
     });
 }