github.com/unigraph-dev/dgraph@v1.1.1-0.20200923154953-8b52b426f765/schema/state.go (about) 1 /* 2 * Copyright 2016-2018 Dgraph Labs, Inc. and Contributors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package schema 18 19 import ( 20 "github.com/dgraph-io/dgraph/lex" 21 ) 22 23 // Constants representing type of different graphql lexed items. 24 const ( 25 itemText lex.ItemType = 5 + iota // plain text 26 itemLeftCurl // left curly bracket 27 itemRightCurl // right curly bracket 28 itemColon // colon 29 itemLeftRound // left round bracket 30 itemRightRound // right round bracket 31 itemAt 32 itemComma 33 itemNewLine 34 itemDot 35 itemLeftSquare 36 itemRightSquare 37 itemExclamationMark 38 ) 39 40 func lexText(l *lex.Lexer) lex.StateFn { 41 Loop: 42 for { 43 switch r := l.Next(); { 44 case r == lex.EOF: 45 break Loop 46 case isNameBegin(r): 47 l.Backup() 48 return lexWord 49 case isSpace(r): 50 l.Ignore() 51 case lex.IsEndOfLine(r): 52 l.Emit(itemNewLine) 53 case r == '.': 54 l.Emit(itemDot) 55 case r == '#': 56 return lexTextComment 57 case r == ',': 58 l.Emit(itemComma) 59 case r == '<': 60 if err := lex.IRIRef(l, itemText); err != nil { 61 return l.Errorf("Invalid schema: %v", err) 62 } 63 case r == '{': 64 l.Emit(itemLeftCurl) 65 case r == '}': 66 l.Emit(itemRightCurl) 67 case r == '(': 68 l.Emit(itemLeftRound) 69 case r == ')': 70 l.Emit(itemRightRound) 71 case r == ':': 72 l.Emit(itemColon) 73 case r == '@': 74 l.Emit(itemAt) 75 case r == '[': 76 l.Emit(itemLeftSquare) 77 case r == ']': 78 l.Emit(itemRightSquare) 79 case r == '!': 80 l.Emit(itemExclamationMark) 81 case r == '_': 82 // Predicates can start with _. 83 return lexWord 84 default: 85 return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) 86 } 87 } 88 if l.Pos > l.Start { 89 l.Emit(itemText) 90 } 91 l.Emit(lex.ItemEOF) 92 return nil 93 } 94 95 func lexWord(l *lex.Lexer) lex.StateFn { 96 for { 97 // The caller already checked isNameBegin, and absorbed one rune. 98 r := l.Next() 99 if isNameSuffix(r) { 100 continue 101 } 102 l.Backup() 103 l.Emit(itemText) 104 break 105 } 106 return lexText 107 } 108 109 // lexTextComment lexes a comment text inside a schema. 110 func lexTextComment(l *lex.Lexer) lex.StateFn { 111 for { 112 r := l.Next() 113 if r == lex.EOF { 114 l.Ignore() 115 l.Emit(lex.ItemEOF) 116 break 117 } 118 if !lex.IsEndOfLine(r) { 119 continue 120 } 121 l.Ignore() 122 l.Emit(itemNewLine) 123 break 124 } 125 return lexText 126 } 127 128 // isNameBegin returns true if the rune is an alphabet. 129 func isNameBegin(r rune) bool { 130 switch { 131 case r >= 'a' && r <= 'z': 132 return true 133 case r >= 'A' && r <= 'Z': 134 return true 135 default: 136 return false 137 } 138 } 139 140 func isNameSuffix(r rune) bool { 141 if isNameBegin(r) { 142 return true 143 } 144 if r >= '0' && r <= '9' { 145 return true 146 } 147 if r == '_' || r == '.' || r == '-' { // Use by freebase. 148 return true 149 } 150 return false 151 } 152 153 // isSpace returns true if the rune is a tab or space. 154 func isSpace(r rune) bool { 155 return r == '\u0009' || r == '\u0020' 156 }