Something went wrong. Try again.
🌱 A minimal programming language and compiler. git.urbach.dev/cli/q
high-performance programming-language compiler
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132package scanner
import ( "git.urbach.dev/cli/q/src/core" "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/fs" "git.urbach.dev/cli/q/src/token")
// scanFunctionSignature scans only the function signature without the body.func scanFunctionSignature(file *fs.File, pkg string, tokens token.List, i int, delimiter token.Kind) (*core.Function, int, error) { var ( groupLevel = 0 nameStart = i inputStart = -1 inputEnd = -1 outputStart = -1 outputEnd = -1 )
i++
// Function parameters for i < len(tokens) { if tokens[i].Kind == token.GroupStart { groupLevel++ i++
if groupLevel == 1 { inputStart = i }
continue }
if tokens[i].Kind == token.GroupEnd { groupLevel--
if groupLevel < 0 { return nil, i, errors.NewAt(MissingGroupStart, file, tokens[i].Position) }
if groupLevel == 0 { inputEnd = i i++ break }
i++ continue }
if tokens[i].Kind == token.Invalid { return nil, i, errors.NewAt(&InvalidCharacter{Character: tokens[i].StringFrom(file.Bytes)}, file, tokens[i].Position) }
if tokens[i].Kind == token.EOF { if groupLevel > 0 { return nil, i, errors.NewAt(MissingGroupEnd, file, tokens[i].Position) }
return nil, i, errors.NewAt(InvalidFunctionDefinition, file, tokens[i].Position) }
if groupLevel > 0 { i++ continue }
return nil, i, errors.NewAt(InvalidFunctionDefinition, file, tokens[i].Position) }
// Return type if i < len(tokens) && tokens[i].Kind == token.ReturnType { outputStart = i + 1
for i < len(tokens) && tokens[i].Kind != delimiter { i++ }
outputEnd = i }
name := tokens[nameStart].StringFrom(file.Bytes) function := core.NewFunction(name, pkg, file) parameters := tokens[inputStart:inputEnd]
for position, param := range parameters.Split { if len(param) == 0 { return nil, i, errors.NewAt(MissingParameter, file, position) }
if len(param) == 1 { return nil, i, errors.NewAt(MissingParameterType, file, param[0].End()) }
if param[0].Kind != token.Identifier { return nil, i, errors.New(InvalidParameterName, file, param[0]) }
function.AddInput(param, token.NewSource(position, param[0].End())) }
if outputStart == -1 { return function, i, nil }
if tokens[outputStart].Kind == token.GroupStart { if tokens[outputEnd-1].Kind == token.GroupEnd { outputStart++ outputEnd-- } else { return nil, i, errors.NewAt(MissingGroupEnd, file, tokens[outputEnd-1].Position) } }
outputTokens := tokens[outputStart:outputEnd]
if len(outputTokens) == 0 { return nil, i, errors.NewAt(MissingParameter, file, tokens[outputStart].Position) }
for position, param := range outputTokens.Split { if len(param) == 0 { return nil, i, errors.NewAt(MissingParameter, file, position) }
function.AddOutput(param, token.NewSource(position, param[len(param)-1].End())) }
return function, i, nil}