// This function inspects the next rune and calls the appropriate stateFn. func lexText(l *lex.Lexer) lex.StateFn { Loop: for { switch r := l.Next(); { case r == '<' || r == '_': if l.Depth == atSubject { l.Backup() l.Emit(itemText) // emit whatever we have so far. return lexSubject } if l.Depth == atPredicate { l.Backup() l.Emit(itemText) return lexPredicate } if l.Depth == atObject { l.Backup() l.Emit(itemText) return lexObject } if l.Depth == atLabel { l.Backup() l.Emit(itemText) return lexLabel } return l.Errorf("Invalid input: %c at lexText", r) case r == '"': if l.Depth != atObject { return l.Errorf("Invalid quote for non-object.") } l.Backup() l.Emit(itemText) return lexObject case r == lex.EOF: break Loop case r == '.': if l.Depth > atObject { l.Emit(itemValidEnd) } break Loop case isSpace(r): continue default: l.Errorf("Invalid input: %c at lexText", r) } } if l.Pos > l.Start { l.Emit(itemText) } l.Emit(lex.ItemEOF) return nil }
// 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 lexText(l *lex.Lexer) lex.StateFn { Loop: for { switch r := l.Next(); { case r == leftCurl: 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: break Loop case isNameBegin(r): l.Backup() l.Emit(itemText) return lexOperationType } } if l.Pos > l.Start { l.Emit(itemText) } l.Emit(lex.ItemEOF) return nil }
// lexOperationType lexes a query or mutation operation type. func lexOperationType(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. word := l.Input[l.Start:l.Pos] if word == "mutation" { l.Emit(itemOpType) l.Mode = mutationMode } else if word == "fragment" { l.Emit(itemOpType) l.Mode = fragmentMode } else if word == "query" { l.Emit(itemOpType) l.Mode = queryMode } else { if l.Mode == 0 { l.Errorf("Invalid operation type") } } break } 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) }
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 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") } } }
// lexDirective is called right after we see a @. func lexDirective(l *lex.Lexer) lex.StateFn { r := l.Next() if !isNameBegin(r) { return l.Errorf("Unrecognized character in lexDirective: %#U", r) } l.Backup() // This gives our buffer an initial capacity. Its length is zero though. The // buffer can grow beyond this initial capacity. buf := bytes.NewBuffer(make([]byte, 0, 15)) for { // The caller already checked isNameBegin, and absorbed one rune. r = l.Next() buf.WriteRune(r) if isNameSuffix(r) { continue } l.Backup() l.Emit(itemDirectiveName) directive := buf.Bytes()[:buf.Len()-1] // The lexer may behave differently for different directives. Hence, we need // to check the directive here and go into the right state. if string(directive) == "filter" { return lexFilterInside } return l.Errorf("Unhandled directive %s", directive) } return lexInside }
// lexTextMutation lexes and absorbs the text inside a mutation operation block. func lexTextMutation(l *lex.Lexer) lex.StateFn { for { r := l.Next() if r == lex.EOF { return l.Errorf("Unclosed mutation text") } if r == quote { return lexMutationValue } if r == leftCurl { l.Depth++ } if r == rightCurl { if l.Depth > 2 { l.Depth-- continue } } if r != rightCurl { // Absorb everything until we find '}'. continue } l.Backup() l.Emit(itemMutationContent) break } return lexInsideMutation }
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]) } } }
func lexPredicate(l *lex.Lexer) lex.StateFn { r := l.Next() if r != '<' { return l.Errorf("Invalid character in lexPredicate: %v", r) } l.Depth += 1 return lexUntilClosing(l, itemPredicate, lexText) }
func lexArgumentVal(l *lex.Lexer) lex.StateFn { for { switch r := l.Next(); { case isSpace(r): l.Ignore() } } }
func lexPredicate(l *lex.Lexer) lex.StateFn { r := l.Next() // The predicate can only be an IRI according to the spec. if r != '<' { return l.Errorf("Invalid character in lexPredicate: %v", r) } l.Depth++ return lexUntilClosing(l, itemPredicate, lexText) }
func lexText(l *lex.Lexer) lex.StateFn { Loop: for { switch r := l.Next(); { case r == '<' || r == '_': if l.Depth == AT_SUBJECT { l.Backup() l.Emit(itemText) // emit whatever we have so far. return lexSubject } else if l.Depth == AT_PREDICATE { l.Backup() l.Emit(itemText) return lexPredicate } else if l.Depth == AT_OBJECT { l.Backup() l.Emit(itemText) return lexObject } else if l.Depth == AT_LABEL { l.Backup() l.Emit(itemText) return lexLabel } else { return l.Errorf("Invalid input: %v at lexText", r) } case r == '"': if l.Depth != AT_OBJECT { return l.Errorf("Invalid quote for non-object.") } l.Backup() l.Emit(itemText) return lexObject case r == lex.EOF: break Loop case r == '.': if l.Depth > AT_OBJECT { l.Emit(itemValidEnd) } break Loop } } if l.Pos > l.Start { l.Emit(itemText) } l.Emit(lex.ItemEOF) return nil }
func lexLabel(l *lex.Lexer) lex.StateFn { r := l.Next() if r == '<' { l.Depth += 1 return lexUntilClosing(l, itemLabel, lexText) } if r == '_' { l.Depth += 1 return lexBlankNode(l, itemLabel, lexText) } return l.Errorf("Invalid char: %v at lexLabel", r) }
// lexArgName lexes and emits the name part of an argument. func lexArgName(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isNameSuffix(r) { continue } l.Backup() l.Emit(itemArgName) break } return lexArgInside }
func lexFragmentSpread(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isNameSuffix(r) { continue } l.Backup() l.Emit(itemFragmentSpread) break } return lexInside }
// lexFilterFuncName expects input to look like equal("...", "..."). func lexFilterFuncName(l *lex.Lexer) lex.StateFn { for { // The caller already checked isNameBegin, and absorbed one rune. r := l.Next() if isNameSuffix(r) { continue } l.Backup() l.Emit(itemFilterFunc) break } return lexFilterFuncInside }
// lexNameMutation lexes the itemMutationOp, which could be set or delete. func lexNameMutation(l *lex.Lexer) lex.StateFn { for { // The caller already checked isNameBegin, and absorbed one rune. r := l.Next() if isNameBegin(r) { continue } l.Backup() l.Emit(itemMutationOp) break } return lexInsideMutation }
func lexSubject(l *lex.Lexer) lex.StateFn { r := l.Next() if r == '<' { l.Depth += 1 return lexUntilClosing(l, itemSubject, lexText) } if r == '_' { l.Depth += 1 return lexBlankNode(l, itemSubject, lexText) } return l.Errorf("Invalid character during lexSubject: %v", r) }
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 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 lexUntilClosing(l *lex.Lexer, styp lex.ItemType, sfn lex.StateFn) lex.StateFn { l.AcceptUntil(isClosingBracket) r := l.Next() if r == lex.EOF { return l.Errorf("Unexpected end of subject") } if r == '>' { l.Emit(styp) return sfn } return l.Errorf("Invalid character %v found for itemType: %v", r, styp) }
func lexOperationType(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isNameSuffix(r) { continue // absorb } l.Backup() word := l.Input[l.Start:l.Pos] if word == "query" || word == "mutation" { l.Emit(itemOpType) } break } return 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 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 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) }
// lexComment lexes a comment text. func lexComment(l *lex.Lexer) lex.StateFn { for { r := l.Next() if isEndOfLine(r) { l.Emit(itemComment) return lexInside } if r == lex.EOF { break } } if l.Pos > l.Start { l.Emit(itemComment) } l.Emit(lex.ItemEOF) return nil // Stop the run loop. }
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 }