package scanner import ( "git.akyoto.dev/cli/q/src/core" "git.akyoto.dev/cli/q/src/errors" "git.akyoto.dev/cli/q/src/fs" "git.akyoto.dev/cli/q/src/token" ) // scanFunctionSignature scans a function declaration without the body. func scanFunctionSignature(file *fs.File, tokens token.List, i int, delimiter token.Kind) (*core.Function, int, error) { var ( groupLevel = 0 nameStart = i paramsStart = -1 paramsEnd = -1 typeStart = -1 typeEnd = -1 ) i++ // Function parameters for i < len(tokens) { if tokens[i].Kind == token.GroupStart { groupLevel++ i++ if groupLevel == 1 { paramsStart = i } continue } if tokens[i].Kind == token.GroupEnd { groupLevel-- if groupLevel < 0 { return nil, i, errors.New(errors.MissingGroupStart, file, tokens[i].Position) } if groupLevel == 0 { paramsEnd = i i++ break } i++ continue } if tokens[i].Kind == token.Invalid { return nil, i, errors.New(&errors.InvalidCharacter{Character: tokens[i].Text(file.Bytes)}, file, tokens[i].Position) } if tokens[i].Kind == token.EOF { if groupLevel > 0 { return nil, i, errors.New(errors.MissingGroupEnd, file, tokens[i].Position) } if paramsStart == -1 { return nil, i, errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) } return nil, i, nil } if groupLevel > 0 { i++ continue } return nil, i, errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) } // Return type if i < len(tokens) && tokens[i].Kind == token.ReturnType { typeStart = i + 1 for i < len(tokens) && tokens[i].Kind != delimiter { i++ } typeEnd = i } name := tokens[nameStart].Text(file.Bytes) function := core.NewFunction(file.Package, name, file, nil) if typeStart != -1 { if tokens[typeStart].Kind == token.GroupStart && tokens[typeEnd-1].Kind == token.GroupEnd { typeStart++ typeEnd-- } outputTokens := tokens[typeStart:typeEnd] err := outputTokens.Split(func(tokens token.List) error { function.Output = append(function.Output, core.NewOutput(tokens)) return nil }) if err != nil { return nil, i, err } } parameters := tokens[paramsStart:paramsEnd] err := parameters.Split(func(tokens token.List) error { if len(tokens) == 0 { return errors.New(errors.MissingParameter, file, parameters[0].Position) } if len(tokens) == 1 { return errors.New(errors.MissingType, file, tokens[0].End()) } function.Input = append(function.Input, core.NewInput(tokens)) return nil }) return function, i, err }