q/src/scanner/scanStruct.go
2025-02-06 12:49:17 +01:00

75 lines
1.4 KiB
Go

package scanner
import (
"git.akyoto.dev/cli/q/src/errors"
"git.akyoto.dev/cli/q/src/fs"
"git.akyoto.dev/cli/q/src/token"
"git.akyoto.dev/cli/q/src/types"
)
// scanStruct scans a struct.
func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, error) {
i++
if tokens[i].Kind != token.Identifier {
return i, errors.New(errors.ExpectedStructName, file, tokens[i].Position)
}
structName := tokens[i].Text(file.Bytes)
structure := types.NewStruct(structName)
i++
if tokens[i].Kind != token.BlockStart {
return i, errors.New(errors.MissingBlockStart, file, tokens[i].Position)
}
i++
closed := false
for i < len(tokens) {
if tokens[i].Kind == token.Identifier {
fieldPosition := i
fieldName := tokens[i].Text(file.Bytes)
i++
fieldTypeName := tokens[i].Text(file.Bytes)
fieldType := types.Int
switch fieldTypeName {
case "Int", "Int64":
case "Int32":
fieldType = types.Int32
case "Int16":
fieldType = types.Int16
case "Int8":
fieldType = types.Int8
default:
panic("not implemented")
}
i++
structure.AddField(&types.Field{
Type: fieldType,
Name: fieldName,
Position: token.Position(fieldPosition),
Offset: structure.Size(),
})
}
if tokens[i].Kind == token.BlockEnd {
closed = true
break
}
i++
}
if !closed {
return i, errors.New(errors.MissingBlockEnd, file, tokens[i].Position)
}
s.types <- structure
return i, nil
}