func lexObject(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == rightCurl: return lexText case isSpace(r) || isEndOfLine(r): l.Ignore() case isNameBegin(r): { for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() l.Emit(itemObject) break } return lexObjectBlock } default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } }
// Assumes '"' has already been encountered. func lexLiteral(l *lex.Lexer) lex.StateFn { for { r := l.Next() if r == '\u005c' { // backslash r = l.Next() continue // This would skip over the escaped rune. } if r == lex.EOF || isEndLiteral(r) { break } } l.Backup() l.Emit(itemLiteral) l.Next() // Move to end literal. l.Ignore() // Ignore end literal. l.Depth++ r := l.Peek() if r == '@' { return lexLanguage(l) } if r == '^' { return lexObjectType(l) } return lexText }
func lexObject(l *lex.Lexer) lex.StateFn { r := l.Next() // The object can be an IRI, blank node or a literal. if r == '<' { l.Depth++ return lexUntilClosing(l, itemObject, lexText) } if r == '_' { l.Depth++ r = l.Next() // TODO - Remove this, doesn't conform to the spec. if r == 'u' { return lexUidNode(l, itemObject, lexText) } if r == ':' { return lexBlankNode(l, itemObject, lexText) } } if r == '"' { l.Ignore() return lexLiteral(l) } return l.Errorf("Invalid char: %v at lexObject", r) }
// lexInsideMutation lexes the text inside a mutation block. func lexInsideMutation(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == rightCurl: l.Depth-- l.Emit(itemRightCurl) if l.Depth == 0 { return lexText } case r == leftCurl: l.Depth++ l.Emit(itemLeftCurl) if l.Depth >= 2 { return lexTextMutation } case r == lex.EOF: return l.Errorf("Unclosed mutation action") case isSpace(r) || isEndOfLine(r): l.Ignore() case isNameBegin(r): return lexNameMutation default: return l.Errorf("Unrecognized character in lexInsideMutation: %#U", r) } } }
func lexInside(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == rightCurl: l.Depth -= 1 l.Emit(itemRightCurl) if l.Depth == 0 { return lexText } case r == leftCurl: l.Depth += 1 l.Emit(itemLeftCurl) case r == lex.EOF: return l.Errorf("unclosed action") case isSpace(r) || isEndOfLine(r) || r == ',': l.Ignore() case isNameBegin(r): 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) } } }
func lexArgumentVal(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case isSpace(r): l.Ignore() } } }
// lexInside lexes the content inside a query block. func lexInside(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == period: if l.Next() == period && l.Next() == period { return lexFragmentSpread } // We do not expect a period at all. If you do, you may want to // backup the two extra periods we try to read. return l.Errorf("Unrecognized character in lexInside: %#U", r) case r == rightCurl: l.Depth-- l.Emit(itemRightCurl) if l.Depth == 0 { return lexText } case r == leftCurl: l.Depth++ l.Emit(itemLeftCurl) case r == lex.EOF: return l.Errorf("Unclosed action") case isSpace(r) || isEndOfLine(r) || r == comma: l.Ignore() case isNameBegin(r): return lexName case r == '#': l.Backup() return lexComment case r == leftRound: l.Emit(itemLeftRound) l.AcceptRun(isSpace) l.Ignore() k := l.Next() if k == '_' || l.Depth != 1 || l.Mode == fragmentMode { l.Backup() l.Emit(itemArgument) return lexArgInside } // This is a generator function. l.Backup() l.Emit(itemGenerator) l.FilterDepth++ return lexFilterInside case r == ':': return lexAlias case r == '@': return lexDirective default: return l.Errorf("Unrecognized character in lexInside: %#U", r) } } }
func lexLanguage(l *lex.Lexer) lex.StateFn { r := l.Next() if r != '@' { return l.Errorf("Expected @ prefix for lexLanguage") } l.Ignore() r = l.Next() if !isLangTagPrefix(r) { return l.Errorf("Invalid language tag prefix: %v", r) } l.AcceptRun(isLangTag) l.Emit(itemLanguage) return lexText }
func lexAlias(l *lex.Lexer) lex.StateFn { l.AcceptRun(isSpace) l.Ignore() // Any spaces encountered. for { r := l.Next() if isNameSuffix(r) { continue } l.Backup() l.Emit(itemAlias) break } return lexInside }
func lexVarInside(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == lex.EOF: return l.Errorf("unclosed argument") case isSpace(r) || isEndOfLine(r): l.Ignore() case isDollar(r): return lexVarName case r == ':': l.Ignore() return lexVarType case r == equal: l.Emit(itemEqual) l.Ignore() return lexVarDefault case r == rightRound: l.Emit(itemRightRound) return lexText case r == comma: l.Emit(itemComma) l.Ignore() default: return l.Errorf("variable list invalid") } } }
func lexObjectType(l *lex.Lexer) lex.StateFn { r := l.Next() if r != '^' { return l.Errorf("Expected ^ for lexObjectType") } r = l.Next() if r != '^' { return l.Errorf("Expected ^^ for lexObjectType") } l.Ignore() r = l.Next() if r != '<' { return l.Errorf("Expected < for lexObjectType") } return lexUntilClosing(l, itemObjectType, lexText) }
// lexArgVal lexes and emits the value part of an argument. func lexArgVal(l *lex.Lexer) lex.StateFn { l.AcceptRun(isSpace) l.Ignore() // Any spaces encountered. for { r := l.Next() if isSpace(r) || isEndOfLine(r) || r == rightRound || r == comma { l.Backup() l.Emit(itemArgVal) return lexArgInside } if r == lex.EOF { return l.Errorf("Reached lex.EOF while reading var value: %v", l.Input[l.Start:l.Pos]) } } }
func lexScalarBlock(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == ')': l.Emit(itemRightRound) return lexText case isNameBegin(r): l.Backup() return lexScalarPair1 case isSpace(r) || isEndOfLine(r): l.Ignore() default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } }
func lexObject(l *lex.Lexer) lex.StateFn { r := l.Next() if r == '<' { l.Depth += 1 return lexUntilClosing(l, itemObject, lexText) } if r == '_' { l.Depth += 1 return lexBlankNode(l, itemObject, lexText) } if r == '"' { l.Ignore() return lexLiteral(l) } return l.Errorf("Invalid char: %v at lexObject", r) }
func lexObjectBlock(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == leftCurl: l.Emit(itemLeftCurl) case isSpace(r) || isEndOfLine(r): l.Ignore() case r == rightCurl: l.Emit(itemRightCurl) return lexText case isNameBegin(r): return lexObjectPair default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } }
func lexArgVal(l *lex.Lexer) lex.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 == lex.EOF { return l.Errorf("Reached lex.EOF while reading var value: %v", l.Input[l.Start:l.Pos]) } } glog.Fatal("This shouldn't be reached.") return nil }
// lexArgInside is used to lex the arguments inside (). func lexArgInside(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case r == lex.EOF: return l.Errorf("unclosed argument") case isSpace(r) || isEndOfLine(r) || r == comma: l.Ignore() case isNameBegin(r): return lexArgName case r == ':': l.Ignore() return lexArgVal case r == rightRound: l.Emit(itemRightRound) return lexInside default: return l.Errorf("argument list invalid") } } }
// lexFilterInside expects input like ( (equal(...) && f(...)) || g(...) ). func lexFilterInside(l *lex.Lexer) lex.StateFn { for { r := l.Next() switch { case r == leftRound: l.Emit(itemLeftRound) l.FilterDepth++ case r == rightRound: if l.FilterDepth == 0 { return l.Errorf("Unexpected right round bracket") } l.FilterDepth-- l.Emit(itemRightRound) if l.FilterDepth == 0 { return lexInside // Filter directive is done. } case r == lex.EOF: return l.Errorf("Unclosed directive") case isSpace(r) || isEndOfLine(r): l.Ignore() case isNameBegin(r): return lexFilterFuncName case r == '&': r2 := l.Next() if r2 == '&' { l.Emit(itemFilterAnd) return lexFilterInside } return l.Errorf("Expected & but got %v", r2) case r == '|': r2 := l.Next() if r2 == '|' { l.Emit(itemFilterOr) return lexFilterInside } return l.Errorf("Expected | but got %v", r2) default: return l.Errorf("Unrecognized character in lexInside: %#U", r) } } }
// lexText lexes the input string and calls other lex functions. func lexText(l *lex.Lexer) lex.StateFn { Loop: for { switch r := l.Next(); { case r == lex.EOF: break Loop case isNameBegin(r): l.Backup() return lexStart case isSpace(r) || isEndOfLine(r): l.Ignore() default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } if l.Pos > l.Start { l.Emit(itemText) } l.Emit(lex.ItemEOF) return nil }
func lexObjectPair(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() l.Emit(itemObjectName) break } L: for { switch r := l.Next(); { case isSpace(r) || isEndOfLine(r): l.Ignore() case r == ':': l.Emit(itemCollon) break case isNameBegin(r): l.Backup() break L default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() l.Emit(itemObjectType) break } return lexObjectBlock }
// lexFilterFuncInside expects input to look like ("...", "..."). func lexFilterFuncInside(l *lex.Lexer) lex.StateFn { l.AcceptRun(isSpace) l.Ignore() // Any spaces encountered. for { r := l.Next() if isSpace(r) || r == ',' { l.Ignore() } else if r == leftRound { l.Emit(itemLeftRound) } else if r == rightRound { l.Emit(itemRightRound) return lexFilterInside } else if isEndLiteral(r) { l.Ignore() l.AcceptUntil(isEndLiteral) // This call will backup the ending ". l.Emit(itemFilterFuncArg) l.Next() // Consume " and ignore it. l.Ignore() } else { return l.Errorf("Expected quotation mark in lexFilterFuncArgs") } } }
func lexScalarPair1(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() // l.Pos would be index of the end of operation type + 1. l.Emit(itemScalarName) break } L: for { switch r := l.Next(); { case isSpace(r) || isEndOfLine(r): l.Ignore() case r == ':': l.Emit(itemCollon) break case isNameBegin(r): l.Backup() break L default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() l.Emit(itemScalarType) break } // Check for the mention of @index. var isIndexed bool L1: for { switch r := l.Next(); { case isSpace(r): l.Ignore() case isEndOfLine(r): break L1 case r == '@': l.Emit(itemAt) isIndexed = true for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() // l.Pos would be index of the end of operation type + 1. word := l.Input[l.Start:l.Pos] if word == "index" { l.Emit(itemIndex) break L1 } else { return l.Errorf("Invalid mention of index") } } break L1 default: return l.Errorf("Invalid schema. Unexpected %s", l.Input[l.Start:l.Pos]) } } if !isIndexed { l.Emit(itemDummy) } return lexScalarBlock }