Skip to content
Snippets Groups Projects
state.go 4.84 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*
     * Copyright 2015 Manish R Jain <manishrjain@gmail.com>
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     * 		http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    
    import "github.com/dgraph-io/dgraph/lex"
    
    
    const (
    	itemText       lex.ItemType = 5 + iota // 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
    )
    
    func lexText(l *lex.Lexer) lex.StateFn {
    
    			l.Backup()
    			l.Emit(itemText) // emit whatever we have so far.
    			l.Next()         // advance one to get back to where we saw leftCurl.
    			l.Depth += 1     // one level down.
    			l.Emit(itemLeftCurl)
    
    			return lexInside // we're in.
    
    		case r == rightCurl:
    
    			return l.Errorf("Too many right characters")
    		case r == lex.EOF:
    
    	if l.Pos > l.Start {
    		l.Emit(itemText)
    
    func lexInside(l *lex.Lexer) lex.StateFn {
    
    			l.Depth -= 1
    			l.Emit(itemRightCurl)
    			if l.Depth == 0 {
    
    			l.Depth += 1
    			l.Emit(itemLeftCurl)
    		case r == lex.EOF:
    			return l.Errorf("unclosed action")
    
    		case isSpace(r) || isEndOfLine(r) || r == ',':
    
    		case isNameBegin(r):
    			return lexName
    		case r == '#':
    
    Manish R Jain's avatar
    Manish R Jain committed
    		case r == '(':
    
    Manish R Jain's avatar
    Manish R Jain committed
    			return lexArgInside
    
    			return l.Errorf("Unrecognized character in lexInside: %#U", r)
    
    func lexName(l *lex.Lexer) lex.StateFn {
    
    Manish R Jain's avatar
    Manish R Jain committed
    		// The caller already checked isNameBegin, and absorbed one rune.
    
    func lexComment(l *lex.Lexer) lex.StateFn {
    
    	if l.Pos > l.Start {
    		l.Emit(itemComment)
    
    func lexOperationType(l *lex.Lexer) lex.StateFn {
    
    		l.Backup()
    		word := l.Input[l.Start:l.Pos]
    
    		if word == "query" || word == "mutation" {
    
    func lexArgInside(l *lex.Lexer) lex.StateFn {
    
    Manish R Jain's avatar
    Manish R Jain committed
    	for {
    
    		switch r := l.Next(); {
    		case r == lex.EOF:
    			return l.Errorf("unclosed argument")
    
    Manish R Jain's avatar
    Manish R Jain committed
    		case isSpace(r) || isEndOfLine(r):
    
    Manish R Jain's avatar
    Manish R Jain committed
    		case isNameBegin(r):
    			return lexArgName
    		case r == ':':
    
    Manish R Jain's avatar
    Manish R Jain committed
    			return lexArgVal
    		case r == ')':
    
    Manish R Jain's avatar
    Manish R Jain committed
    			return lexInside
    		case r == ',':
    
    func lexArgName(l *lex.Lexer) lex.StateFn {
    
    Manish R Jain's avatar
    Manish R Jain committed
    	for {
    
    Manish R Jain's avatar
    Manish R Jain committed
    		if isNameSuffix(r) {
    			continue
    		}
    
    Manish R Jain's avatar
    Manish R Jain committed
    		break
    	}
    	return lexArgInside
    }
    
    
    func lexArgVal(l *lex.Lexer) lex.StateFn {
    	l.AcceptRun(isSpace)
    	l.Ignore() // Any spaces encountered.
    
    Manish R Jain's avatar
    Manish R Jain committed
    	for {
    
    Manish R Jain's avatar
    Manish R Jain committed
    		if isSpace(r) || isEndOfLine(r) || r == ')' || r == ',' {
    
    Manish R Jain's avatar
    Manish R Jain committed
    			return lexArgInside
    		}
    
    		if r == lex.EOF {
    			return l.Errorf("Reached lex.EOF while reading var value: %v",
    				l.Input[l.Start:l.Pos])
    
    Manish R Jain's avatar
    Manish R Jain committed
    		}
    	}
    	glog.Fatal("This shouldn't be reached.")
    	return nil
    }
    
    
    func lexArgumentVal(l *lex.Lexer) lex.StateFn {
    
    Manish R Jain's avatar
    Manish R Jain committed
    	for {
    
    Manish R Jain's avatar
    Manish R Jain committed
    		case isSpace(r):
    
    func isSpace(r rune) bool {
    
    	return r == '\u0009' || r == '\u0020'
    
    }
    
    func isEndOfLine(r rune) bool {
    
    	return r == '\u000A' || r == '\u000D'
    }
    
    func isNameBegin(r rune) bool {
    	switch {
    	case r >= 'a' && r <= 'z':
    		return true
    	case r >= 'A' && r <= 'Z':
    		return true
    	case r == '_':
    		return true
    	default:
    		return false
    	}
    
    func isNameSuffix(r rune) bool {
    	if isNameBegin(r) {
    		return true
    	}
    	if r >= '0' && r <= '9' {
    		return true
    	}
    	return false