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