Skip to content
Snippets Groups Projects
Commit 85adf86a authored by Manish R Jain's avatar Manish R Jain
Browse files

Add argument parsing

parent 1fd88720
Branches
Tags
No related merge requests found
...@@ -2,7 +2,6 @@ package gqlex ...@@ -2,7 +2,6 @@ package gqlex
import ( import (
"fmt" "fmt"
"strings"
"unicode/utf8" "unicode/utf8"
"github.com/Sirupsen/logrus" "github.com/Sirupsen/logrus"
...@@ -14,15 +13,19 @@ var glog = x.Log("lexer") ...@@ -14,15 +13,19 @@ var glog = x.Log("lexer")
type itemType int type itemType int
const ( const (
itemEOF itemType = iota itemEOF itemType = iota
itemError // error itemError // error
itemText // plain text itemText // plain text
itemLeftCurl // left curly bracket itemLeftCurl // left curly bracket
itemRightCurl // right curly bracket itemRightCurl // right curly bracket
itemComment // comment itemComment // comment
itemName // names itemName // names
itemOpType // operation type itemOpType // operation type
itemString // quoted string itemString // quoted string
itemLeftRound // left round bracket
itemRightRound // right round bracket
itemArgName // argument name
itemArgVal // argument val
) )
const EOF = -1 const EOF = -1
...@@ -123,16 +126,15 @@ func (l *lexer) ignore() { ...@@ -123,16 +126,15 @@ func (l *lexer) ignore() {
l.start = l.pos l.start = l.pos
} }
func (l *lexer) accept(valid string) bool { type checkRune func(r rune) bool
if strings.IndexRune(valid, l.next()) >= 0 {
return true
}
l.backup()
return false
}
func (l *lexer) acceptRun(valid string) { func (l *lexer) acceptRun(c checkRune) {
for strings.IndexRune(valid, l.next()) >= 0 { for {
r := l.next()
if !c(r) {
break
}
} }
l.backup() l.backup()
} }
...@@ -8,9 +8,10 @@ import ( ...@@ -8,9 +8,10 @@ import (
func TestNewLexer(t *testing.T) { func TestNewLexer(t *testing.T) {
input := ` input := `
mutation { mutation {
me { me( id: 10, xid: rick ) {
name0 # my name name0 # my name
_city, # 0what would fail lex. _city, # 0what would fail lex.
profilePic(width: 100, height: 100)
friends { friends {
name name
} }
......
...@@ -55,11 +55,13 @@ func lexInside(l *lexer) stateFn { ...@@ -55,11 +55,13 @@ func lexInside(l *lexer) stateFn {
case isSpace(r) || isEndOfLine(r) || r == ',': case isSpace(r) || isEndOfLine(r) || r == ',':
l.ignore() l.ignore()
case isNameBegin(r): case isNameBegin(r):
l.backup()
return lexName return lexName
case r == '#': case r == '#':
l.backup() l.backup()
return lexComment return lexComment
case r == '(':
l.emit(itemLeftRound)
return lexArgInside
default: default:
return l.errorf("Unrecognized character in lexInside: %#U", r) return l.errorf("Unrecognized character in lexInside: %#U", r)
} }
...@@ -68,7 +70,7 @@ func lexInside(l *lexer) stateFn { ...@@ -68,7 +70,7 @@ func lexInside(l *lexer) stateFn {
func lexName(l *lexer) stateFn { func lexName(l *lexer) stateFn {
for { for {
// The caller must have already checked isNameBegin. // The caller already checked isNameBegin, and absorbed one rune.
r := l.next() r := l.next()
if isNameSuffix(r) { if isNameSuffix(r) {
continue continue
...@@ -114,6 +116,68 @@ func lexOperationType(l *lexer) stateFn { ...@@ -114,6 +116,68 @@ func lexOperationType(l *lexer) stateFn {
return lexText return lexText
} }
func lexArgInside(l *lexer) stateFn {
for {
switch r := l.next(); {
case r == EOF:
return l.errorf("unclosed argument")
case isSpace(r) || isEndOfLine(r):
l.ignore()
case isNameBegin(r):
return lexArgName
case r == ':':
l.ignore()
return lexArgVal
case r == ')':
l.emit(itemRightRound)
return lexInside
case r == ',':
l.ignore()
}
}
}
func lexArgName(l *lexer) stateFn {
for {
r := l.next()
if isNameSuffix(r) {
continue
}
l.backup()
l.emit(itemArgName)
break
}
return lexArgInside
}
func lexArgVal(l *lexer) stateFn {
l.acceptRun(isSpace)
l.ignore() // Any spaces encountered.
for {
r := l.next()
if isSpace(r) || isEndOfLine(r) || r == ')' || r == ',' {
l.backup()
l.emit(itemArgVal)
return lexArgInside
}
if r == EOF {
return l.errorf("Reached EOF while reading var value: %v",
l.input[l.start:l.pos])
}
}
glog.Fatal("This shouldn't be reached.")
return nil
}
func lexArgumentVal(l *lexer) stateFn {
for {
switch r := l.next(); {
case isSpace(r):
l.ignore()
}
}
}
func isSpace(r rune) bool { func isSpace(r rune) bool {
return r == '\u0009' || r == '\u0020' return r == '\u0009' || r == '\u0020'
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment