Implemented extern functions
This commit is contained in:
parent
38b573085e
commit
4803b81845
24 changed files with 304 additions and 169 deletions
125
src/scanner/scanFunctionSignature.go
Normal file
125
src/scanner/scanFunctionSignature.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
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
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue