aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/vektah/gqlparser/lexer/lexer.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/vektah/gqlparser/lexer/lexer.go')
-rw-r--r--vendor/github.com/vektah/gqlparser/lexer/lexer.go510
1 files changed, 0 insertions, 510 deletions
diff --git a/vendor/github.com/vektah/gqlparser/lexer/lexer.go b/vendor/github.com/vektah/gqlparser/lexer/lexer.go
deleted file mode 100644
index 89687857..00000000
--- a/vendor/github.com/vektah/gqlparser/lexer/lexer.go
+++ /dev/null
@@ -1,510 +0,0 @@
-package lexer
-
-import (
- "bytes"
- "unicode/utf8"
-
- "github.com/vektah/gqlparser/ast"
- "github.com/vektah/gqlparser/gqlerror"
-)
-
-// Lexer turns graphql request and schema strings into tokens
-type Lexer struct {
- *ast.Source
- // An offset into the string in bytes
- start int
- // An offset into the string in runes
- startRunes int
- // An offset into the string in bytes
- end int
- // An offset into the string in runes
- endRunes int
- // the current line number
- line int
- // An offset into the string in rune
- lineStartRunes int
-}
-
-func New(src *ast.Source) Lexer {
- return Lexer{
- Source: src,
- line: 1,
- }
-}
-
-// take one rune from input and advance end
-func (s *Lexer) peek() (rune, int) {
- return utf8.DecodeRuneInString(s.Input[s.end:])
-}
-
-func (s *Lexer) makeToken(kind Type) (Token, *gqlerror.Error) {
- return s.makeValueToken(kind, s.Input[s.start:s.end])
-}
-
-func (s *Lexer) makeValueToken(kind Type, value string) (Token, *gqlerror.Error) {
- return Token{
- Kind: kind,
- Value: value,
- Pos: ast.Position{
- Start: s.startRunes,
- End: s.endRunes,
- Line: s.line,
- Column: s.startRunes - s.lineStartRunes + 1,
- Src: s.Source,
- },
- }, nil
-}
-
-func (s *Lexer) makeError(format string, args ...interface{}) (Token, *gqlerror.Error) {
- column := s.endRunes - s.lineStartRunes + 1
- return Token{
- Kind: Invalid,
- Pos: ast.Position{
- Start: s.startRunes,
- End: s.endRunes,
- Line: s.line,
- Column: column,
- Src: s.Source,
- },
- }, gqlerror.ErrorLocf(s.Source.Name, s.line, column, format, args...)
-}
-
-// ReadToken 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
-// function for more complicated tokens.
-func (s *Lexer) ReadToken() (token Token, err *gqlerror.Error) {
-
- s.ws()
- s.start = s.end
- s.startRunes = s.endRunes
-
- if s.end >= len(s.Input) {
- return s.makeToken(EOF)
- }
- r := s.Input[s.start]
- s.end++
- s.endRunes++
- switch r {
- case '!':
- return s.makeValueToken(Bang, "")
-
- case '$':
- return s.makeValueToken(Dollar, "")
- case '&':
- return s.makeValueToken(Amp, "")
- case '(':
- return s.makeValueToken(ParenL, "")
- case ')':
- return s.makeValueToken(ParenR, "")
- case '.':
- if len(s.Input) > s.start+2 && s.Input[s.start:s.start+3] == "..." {
- s.end += 2
- s.endRunes += 2
- return s.makeValueToken(Spread, "")
- }
- case ':':
- return s.makeValueToken(Colon, "")
- case '=':
- return s.makeValueToken(Equals, "")
- case '@':
- return s.makeValueToken(At, "")
- case '[':
- return s.makeValueToken(BracketL, "")
- case ']':
- return s.makeValueToken(BracketR, "")
- case '{':
- return s.makeValueToken(BraceL, "")
- case '}':
- return s.makeValueToken(BraceR, "")
- case '|':
- return s.makeValueToken(Pipe, "")
- case '#':
- s.readComment()
- return s.ReadToken()
-
- case '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z':
- return s.readName()
-
- case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- return s.readNumber()
-
- case '"':
- if len(s.Input) > s.start+2 && s.Input[s.start:s.start+3] == `"""` {
- return s.readBlockString()
- }
-
- return s.readString()
- }
-
- s.end--
- s.endRunes--
-
- if r < 0x0020 && r != 0x0009 && r != 0x000a && r != 0x000d {
- return s.makeError(`Cannot contain the invalid character "\u%04d"`, r)
- }
-
- if r == '\'' {
- return s.makeError(`Unexpected single quote character ('), did you mean to use a double quote (")?`)
- }
-
- return s.makeError(`Cannot parse the unexpected character "%s".`, string(r))
-}
-
-// ws reads from body starting at startPosition until it finds a non-whitespace
-// or commented character, and updates the token end to include all whitespace
-func (s *Lexer) ws() {
- for s.end < len(s.Input) {
- switch s.Input[s.end] {
- case '\t', ' ', ',':
- s.end++
- s.endRunes++
- case '\n':
- s.end++
- s.endRunes++
- s.line++
- s.lineStartRunes = s.endRunes
- case '\r':
- s.end++
- s.endRunes++
- s.line++
- s.lineStartRunes = s.endRunes
- // skip the following newline if its there
- if s.end < len(s.Input) && s.Input[s.end] == '\n' {
- s.end++
- s.endRunes++
- }
- // byte order mark, given ws is hot path we aren't relying on the unicode package here.
- case 0xef:
- if s.end+2 < len(s.Input) && s.Input[s.end+1] == 0xBB && s.Input[s.end+2] == 0xBF {
- s.end += 3
- s.endRunes++
- } else {
- return
- }
- default:
- return
- }
- }
-}
-
-// readComment from the input
-//
-// #[\u0009\u0020-\uFFFF]*
-func (s *Lexer) readComment() (Token, *gqlerror.Error) {
- for s.end < len(s.Input) {
- r, w := s.peek()
-
- // SourceCharacter but not LineTerminator
- if r > 0x001f || r == '\t' {
- s.end += w
- s.endRunes++
- } else {
- break
- }
- }
-
- return s.makeToken(Comment)
-}
-
-// readNumber from the input, 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]+)?
-func (s *Lexer) readNumber() (Token, *gqlerror.Error) {
- float := false
-
- // backup to the first digit
- s.end--
- s.endRunes--
-
- s.acceptByte('-')
-
- if s.acceptByte('0') {
- if consumed := s.acceptDigits(); consumed != 0 {
- s.end -= consumed
- s.endRunes -= consumed
- return s.makeError("Invalid number, unexpected digit after 0: %s.", s.describeNext())
- }
- } else {
- if consumed := s.acceptDigits(); consumed == 0 {
- return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext())
- }
- }
-
- if s.acceptByte('.') {
- float = true
-
- if consumed := s.acceptDigits(); consumed == 0 {
- return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext())
- }
- }
-
- if s.acceptByte('e', 'E') {
- float = true
-
- s.acceptByte('-', '+')
-
- if consumed := s.acceptDigits(); consumed == 0 {
- return s.makeError("Invalid number, expected digit but got: %s.", s.describeNext())
- }
- }
-
- if float {
- return s.makeToken(Float)
- } else {
- return s.makeToken(Int)
- }
-}
-
-// acceptByte if it matches any of given bytes, returning true if it found anything
-func (s *Lexer) acceptByte(bytes ...uint8) bool {
- if s.end >= len(s.Input) {
- return false
- }
-
- for _, accepted := range bytes {
- if s.Input[s.end] == accepted {
- s.end++
- s.endRunes++
- return true
- }
- }
- return false
-}
-
-// acceptDigits from the input, returning the number of digits it found
-func (s *Lexer) acceptDigits() int {
- consumed := 0
- for s.end < len(s.Input) && s.Input[s.end] >= '0' && s.Input[s.end] <= '9' {
- s.end++
- s.endRunes++
- consumed++
- }
-
- return consumed
-}
-
-// describeNext peeks at the input and returns a human readable string. This should will alloc
-// and should only be used in errors
-func (s *Lexer) describeNext() string {
- if s.end < len(s.Input) {
- return `"` + string(s.Input[s.end]) + `"`
- }
- return "<EOF>"
-}
-
-// readString from the input
-//
-// "([^"\\\u000A\u000D]|(\\(u[0-9a-fA-F]{4}|["\\/bfnrt])))*"
-func (s *Lexer) readString() (Token, *gqlerror.Error) {
- inputLen := len(s.Input)
-
- // this buffer is lazily created only if there are escape characters.
- var buf *bytes.Buffer
-
- // skip the opening quote
- s.start++
- s.startRunes++
-
- for s.end < inputLen {
- r := s.Input[s.end]
- if r == '\n' || r == '\r' {
- break
- }
- if r < 0x0020 && r != '\t' {
- return s.makeError(`Invalid character within String: "\u%04d".`, r)
- }
- switch r {
- default:
- var char = rune(r)
- var w = 1
-
- // skip unicode overhead if we are in the ascii range
- if r >= 127 {
- char, w = utf8.DecodeRuneInString(s.Input[s.end:])
- }
- s.end += w
- s.endRunes++
-
- if buf != nil {
- buf.WriteRune(char)
- }
-
- case '"':
- t, err := s.makeToken(String)
- // the token should not include the quotes in its value, but should cover them in its position
- t.Pos.Start--
- t.Pos.End++
-
- if buf != nil {
- t.Value = buf.String()
- }
-
- // skip the close quote
- s.end++
- s.endRunes++
-
- return t, err
-
- case '\\':
- if s.end+1 >= inputLen {
- s.end++
- s.endRunes++
- return s.makeError(`Invalid character escape sequence.`)
- }
-
- if buf == nil {
- buf = bytes.NewBufferString(s.Input[s.start:s.end])
- }
-
- escape := s.Input[s.end+1]
-
- if escape == 'u' {
- if s.end+6 >= inputLen {
- s.end++
- s.endRunes++
- return s.makeError("Invalid character escape sequence: \\%s.", s.Input[s.end:])
- }
-
- r, ok := unhex(s.Input[s.end+2 : s.end+6])
- if !ok {
- s.end++
- s.endRunes++
- return s.makeError("Invalid character escape sequence: \\%s.", s.Input[s.end:s.end+5])
- }
- buf.WriteRune(r)
- s.end += 6
- s.endRunes += 6
- } else {
- switch escape {
- case '"', '/', '\\':
- buf.WriteByte(escape)
- case 'b':
- buf.WriteByte('\b')
- case 'f':
- buf.WriteByte('\f')
- case 'n':
- buf.WriteByte('\n')
- case 'r':
- buf.WriteByte('\r')
- case 't':
- buf.WriteByte('\t')
- default:
- s.end += 1
- s.endRunes += 1
- return s.makeError("Invalid character escape sequence: \\%s.", string(escape))
- }
- s.end += 2
- s.endRunes += 2
- }
- }
- }
-
- return s.makeError("Unterminated string.")
-}
-
-// readBlockString from the input
-//
-// """("?"?(\\"""|\\(?!=""")|[^"\\]))*"""
-func (s *Lexer) readBlockString() (Token, *gqlerror.Error) {
- inputLen := len(s.Input)
-
- var buf bytes.Buffer
-
- // skip the opening quote
- s.start += 3
- s.startRunes += 3
- s.end += 2
- s.endRunes += 2
-
- for s.end < inputLen {
- r := s.Input[s.end]
-
- // Closing triple quote (""")
- if r == '"' && s.end+3 <= inputLen && s.Input[s.end:s.end+3] == `"""` {
- t, err := s.makeValueToken(BlockString, blockStringValue(buf.String()))
-
- // the token should not include the quotes in its value, but should cover them in its position
- t.Pos.Start -= 3
- t.Pos.End += 3
-
- // skip the close quote
- s.end += 3
- s.endRunes += 3
-
- return t, err
- }
-
- // SourceCharacter
- if r < 0x0020 && r != '\t' && r != '\n' && r != '\r' {
- return s.makeError(`Invalid character within String: "\u%04d".`, r)
- }
-
- if r == '\\' && s.end+4 <= inputLen && s.Input[s.end:s.end+4] == `\"""` {
- buf.WriteString(`"""`)
- s.end += 4
- s.endRunes += 4
- } else if r == '\r' {
- if s.end+1 < inputLen && s.Input[s.end+1] == '\n' {
- s.end++
- s.endRunes++
- }
-
- buf.WriteByte('\n')
- s.end++
- s.endRunes++
- } else {
- var char = rune(r)
- var w = 1
-
- // skip unicode overhead if we are in the ascii range
- if r >= 127 {
- char, w = utf8.DecodeRuneInString(s.Input[s.end:])
- }
- s.end += w
- s.endRunes++
- buf.WriteRune(char)
- }
- }
-
- return s.makeError("Unterminated string.")
-}
-
-func unhex(b string) (v rune, ok bool) {
- for _, c := range b {
- v <<= 4
- switch {
- case '0' <= c && c <= '9':
- v |= c - '0'
- case 'a' <= c && c <= 'f':
- v |= c - 'a' + 10
- case 'A' <= c && c <= 'F':
- v |= c - 'A' + 10
- default:
- return 0, false
- }
- }
-
- return v, true
-}
-
-// readName from the input
-//
-// [_A-Za-z][_0-9A-Za-z]*
-func (s *Lexer) readName() (Token, *gqlerror.Error) {
- for s.end < len(s.Input) {
- r, w := s.peek()
-
- if (r >= '0' && r <= '9') || (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || r == '_' {
- s.end += w
- s.endRunes++
- } else {
- break
- }
- }
-
- return s.makeToken(Name)
-}