75 lines
1.4 KiB
Go
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
|
|
}
|