github.com/goplus/llgo@v0.8.3/xtool/clang/types/parser/parser.go (about) 1 /* 2 * Copyright (c) 2022 The GoPlus Authors (goplus.org). All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package parser 18 19 import ( 20 "errors" 21 "fmt" 22 "go/token" 23 "go/types" 24 "io" 25 "log" 26 "strconv" 27 28 "github.com/goplus/gogen" 29 "github.com/goplus/llgo/xtool/clang/types/scanner" 30 31 ctypes "github.com/goplus/llgo/xtool/clang/types" 32 ) 33 34 const ( 35 emsgDefArrWithoutLen = "define array without length" 36 ) 37 38 var ( 39 ErrInvalidType = errors.New("invalid type") 40 ) 41 42 type TypeNotFound struct { 43 Literal string 44 StructOrUnion bool 45 } 46 47 func (p *TypeNotFound) Error() string { 48 return fmt.Sprintf("type %s not found", p.Literal) 49 } 50 51 type ParseTypeError struct { 52 QualType string 53 ErrMsg string 54 } 55 56 func (p *ParseTypeError) Error() string { 57 return p.ErrMsg // TODO 58 } 59 60 func IsArrayWithoutLen(err error) bool { 61 if e, ok := err.(*ParseTypeError); ok { 62 return e.ErrMsg == emsgDefArrWithoutLen 63 } 64 return false 65 } 66 67 // ----------------------------------------------------------------------------- 68 69 const ( 70 FlagIsParam = 1 << iota 71 FlagIsStructField 72 FlagIsExtern 73 FlagIsTypedef 74 FlagGetRetType 75 ) 76 77 func getRetType(flags int) bool { 78 return (flags & FlagGetRetType) != 0 79 } 80 81 type ParseEnv interface { 82 Pkg() *types.Package 83 Int128() types.Type 84 Uint128() types.Type 85 } 86 87 type Config struct { 88 ParseEnv 89 Scope *types.Scope 90 Anonym types.Type 91 Flags int 92 } 93 94 const ( 95 KindFConst = 1 << iota 96 KindFVolatile 97 KindFAnonymous 98 KindFVariadic 99 ) 100 101 // qualType can be: 102 // - unsigned int 103 // - struct ConstantString 104 // - volatile uint32_t 105 // - int (*)(void *, int, char **, char **) 106 // - int (*)(const char *, ...) 107 // - int (*)(void) 108 // - void (*(int, void (*)(int)))(int) 109 // - const char *restrict 110 // - const char [7] 111 // - char * 112 // - void 113 // - ... 114 func ParseType(qualType string, conf *Config) (t types.Type, kind int, err error) { 115 p := newParser(qualType, conf) 116 if t, kind, err = p.parse(conf.Flags); err != nil { 117 return 118 } 119 if p.tok != token.EOF { 120 err = p.newError("unexpect token " + p.tok.String()) 121 } 122 return 123 } 124 125 // ----------------------------------------------------------------------------- 126 127 type parser struct { 128 s scanner.Scanner 129 scope *types.Scope 130 conf *Config 131 132 tok token.Token 133 lit string 134 old struct { 135 tok token.Token 136 lit string 137 } 138 } 139 140 const ( 141 invalidTok token.Token = -1 142 ) 143 144 func newParser(qualType string, conf *Config) *parser { 145 p := &parser{scope: conf.Scope, conf: conf} 146 p.old.tok = invalidTok 147 p.s.Init(qualType) 148 return p 149 } 150 151 func (p *parser) peek() token.Token { 152 if p.old.tok == invalidTok { 153 p.old.tok, p.old.lit = p.s.Scan() 154 } 155 return p.old.tok 156 } 157 158 func (p *parser) next() { 159 if p.old.tok != invalidTok { // support unget 160 p.tok, p.lit = p.old.tok, p.old.lit 161 p.old.tok = invalidTok 162 return 163 } 164 p.tok, p.lit = p.s.Scan() 165 } 166 167 func (p *parser) unget(tok token.Token, lit string) { 168 p.old.tok, p.old.lit = p.tok, p.lit 169 p.tok, p.lit = tok, lit 170 } 171 172 func (p *parser) skipUntil(tok token.Token) bool { 173 for { 174 p.next() 175 switch p.tok { 176 case tok: 177 return true 178 case token.EOF: 179 return false 180 } 181 } 182 } 183 184 func (p *parser) newErrorf(format string, args ...interface{}) *ParseTypeError { 185 return p.newError(fmt.Sprintf(format, args...)) 186 } 187 188 func (p *parser) newError(errMsg string) *ParseTypeError { 189 return &ParseTypeError{QualType: p.s.Source(), ErrMsg: errMsg} 190 } 191 192 // TODO(xsw): check expect results 193 func (p *parser) expect(tokExp token.Token) error { 194 p.next() 195 if p.tok != tokExp { 196 return p.newErrorf("expect %v, got %v", tokExp, p.tok) 197 } 198 return nil 199 } 200 201 const ( 202 flagShort = 1 << iota 203 flagLong 204 flagLongLong 205 flagUnsigned 206 flagSigned 207 flagComplex 208 flagStructOrUnion 209 ) 210 211 func (p *parser) lookupType(tylit string, flags int) (t types.Type, err error) { 212 structOrUnion := (flags & flagStructOrUnion) != 0 213 _, o := gogen.LookupParent(p.scope, tylit, token.NoPos) 214 if o == nil { 215 return nil, &TypeNotFound{Literal: tylit, StructOrUnion: structOrUnion} 216 } 217 t = o.Type() 218 if !structOrUnion && flags != 0 { 219 tt, ok := t.(*types.Basic) 220 if !ok { 221 tyInt128 := p.conf.Int128() 222 if t == tyInt128 { 223 switch flags { 224 case flagSigned: 225 return tyInt128, nil 226 case flagUnsigned: 227 return p.conf.Uint128(), nil 228 } 229 } 230 } else if (flags & flagComplex) != 0 { 231 switch tt.Kind() { 232 case types.Float32: 233 return types.Typ[types.Complex64], nil 234 case types.Float64: 235 return types.Typ[types.Complex128], nil 236 case types.Int: 237 return types.Typ[types.Complex128], nil 238 } 239 } else { 240 switch tt.Kind() { 241 case types.Int: 242 if t = intTypes[flags&^flagSigned]; t != nil { 243 return 244 } 245 case types.Int8: 246 switch flags { 247 case flagUnsigned: 248 return types.Typ[types.Uint8], nil 249 case flagSigned: 250 return types.Typ[types.Int8], nil 251 } 252 case types.Float64: 253 switch flags { 254 case flagLong: 255 return ctypes.LongDouble, nil 256 } 257 } 258 } 259 log.Panicln("lookupType: TODO - invalid type") 260 return nil, ErrInvalidType 261 } 262 if t == types.Typ[types.Int] { 263 return ctypes.Int, nil 264 } 265 return 266 } 267 268 var intTypes = [...]types.Type{ 269 0: ctypes.Int, 270 flagShort: types.Typ[types.Int16], 271 flagLong: ctypes.Long, 272 flagLong | flagLongLong: types.Typ[types.Int64], 273 flagUnsigned: ctypes.Uint, 274 flagShort | flagUnsigned: types.Typ[types.Uint16], 275 flagLong | flagUnsigned: ctypes.Ulong, 276 flagLong | flagLongLong | flagUnsigned: types.Typ[types.Uint64], 277 flagShort | flagLong | flagLongLong | flagUnsigned: nil, 278 } 279 280 func (p *parser) parseArray(t types.Type, inFlags int) (types.Type, error) { 281 var n int64 282 var err error 283 p.next() 284 switch p.tok { 285 case token.RBRACK: // ] 286 if (inFlags & FlagIsStructField) != 0 { 287 n = 0 288 } else { 289 n = -1 290 } 291 case token.INT: 292 if n, err = strconv.ParseInt(p.lit, 10, 64); err != nil { 293 return nil, p.newError(err.Error()) 294 } 295 if err = p.expect(token.RBRACK); err != nil { // ] 296 return nil, err 297 } 298 default: 299 return nil, p.newError("array length not an integer") 300 } 301 if n >= 0 || (inFlags&(FlagIsExtern|FlagIsTypedef|FlagIsParam)) != 0 { 302 t = types.NewArray(t, n) 303 } else { 304 return nil, p.newError(emsgDefArrWithoutLen) 305 } 306 return t, nil 307 } 308 309 func (p *parser) parseArrays(t types.Type, inFlags int) (ret types.Type, err error) { 310 if t == nil { 311 return nil, p.newError("array to nil") 312 } 313 var tyArr types.Type 314 for { 315 if tyArr, err = p.parseArray(tyArr, inFlags); err != nil { 316 return 317 } 318 if p.peek() != token.LBRACK { 319 return newArraysEx(t, tyArr, inFlags), nil 320 } 321 p.next() 322 } 323 } 324 325 func (p *parser) parseFunc(pkg *types.Package, t types.Type, inFlags int) (ret types.Type, err error) { 326 var results *types.Tuple 327 if ctypes.NotVoid(t) { 328 results = types.NewTuple(types.NewParam(token.NoPos, pkg, "", t)) 329 } 330 args, variadic, err := p.parseArgs(pkg) 331 if err != nil { 332 return 333 } 334 _ = inFlags 335 return ctypes.NewFunc(types.NewTuple(args...), results, variadic), nil 336 } 337 338 func (p *parser) parseArgs(pkg *types.Package) (args []*types.Var, variadic bool, err error) { 339 for { 340 arg, kind, e := p.parse(FlagIsParam) 341 if e != nil { 342 return nil, false, e 343 } 344 if ctypes.NotVoid(arg) { 345 args = append(args, types.NewParam(token.NoPos, pkg, "", arg)) 346 } 347 if p.tok != token.COMMA { 348 variadic = (kind & KindFVariadic) != 0 349 break 350 } 351 } 352 if p.tok != token.RPAREN { // ) 353 return nil, false, p.newError("expect )") 354 } 355 return 356 } 357 358 func (p *parser) parseStars() (nstar int) { 359 for isPtr(p.peek()) { 360 p.next() 361 nstar++ 362 } 363 return 364 } 365 366 func (p *parser) parse(inFlags int) (t types.Type, kind int, err error) { 367 flags := 0 368 for { 369 p.next() 370 retry: 371 switch p.tok { 372 case token.IDENT: 373 ident: 374 switch lit := p.lit; lit { 375 case "unsigned": 376 flags |= flagUnsigned 377 case "short": 378 flags |= flagShort 379 case "long": 380 if (flags & flagLong) != 0 { 381 flags |= flagLongLong 382 } else { 383 flags |= flagLong 384 } 385 case "signed": 386 flags |= flagSigned 387 case "const": 388 kind |= KindFConst 389 case "volatile": 390 kind |= KindFVolatile 391 case "_Complex": 392 flags |= flagComplex 393 case "restrict", "_Nullable", "_Nonnull": 394 case "enum": 395 if err = p.expect(token.IDENT); err != nil { 396 return 397 } 398 if t != nil { 399 return nil, 0, p.newError("illegal syntax: multiple types?") 400 } 401 t = ctypes.Int 402 continue 403 case "struct", "union": 404 p.next() 405 switch p.tok { 406 case token.IDENT: 407 case token.LPAREN: 408 if t == nil && p.conf.Anonym != nil { 409 p.skipUntil(token.RPAREN) 410 t = p.conf.Anonym 411 kind |= KindFAnonymous 412 continue 413 } 414 fallthrough 415 default: 416 log.Panicln("c.types.ParseType: struct/union - TODO:", p.lit) 417 } 418 lit = ctypes.MangledName(lit, p.lit) 419 flags |= flagStructOrUnion 420 fallthrough 421 default: 422 if t != nil { 423 return nil, 0, p.newError("illegal syntax: multiple types?") 424 } 425 if t, err = p.lookupType(lit, flags); err != nil { 426 return 427 } 428 flags = 0 429 } 430 if flags != 0 { 431 p.next() 432 if p.tok == token.IDENT { 433 goto ident 434 } 435 if t != nil { 436 return nil, 0, p.newError("illegal syntax: multiple types?") 437 } 438 if t, err = p.lookupType("int", flags); err != nil { 439 return 440 } 441 flags = 0 442 goto retry 443 } 444 case token.MUL: // * 445 if t == nil { 446 return nil, 0, p.newError("pointer to nil") 447 } 448 t = ctypes.NewPointer(t) 449 case token.LBRACK: // [ 450 if t, err = p.parseArrays(t, inFlags); err != nil { 451 return 452 } 453 case token.LPAREN: // ( 454 if t == nil { 455 log.Panicln("TODO") 456 return nil, 0, p.newError("no function return type") 457 } 458 var nstar = p.parseStars() 459 var nstarRet int 460 var tyArr types.Type 461 var pkg, isFn = p.conf.Pkg(), false 462 var args []*types.Var 463 var variadic bool 464 if nstar == 0 { 465 if getRetType(inFlags) { 466 err = nil 467 p.tok = token.EOF 468 return 469 } 470 if args, variadic, err = p.parseArgs(pkg); err != nil { 471 return 472 } 473 isFn = true 474 } else { 475 nextTok: 476 p.next() 477 switch p.tok { 478 case token.RPAREN: // ) 479 case token.LPAREN: // ( 480 if !isFn { 481 nstar, nstarRet = p.parseStars(), nstar 482 if nstar != 0 { 483 p.expect(token.RPAREN) // ) 484 p.expect(token.LPAREN) // ( 485 } 486 if args, variadic, err = p.parseArgs(pkg); err != nil { 487 return 488 } 489 isFn = true 490 goto nextTok 491 } 492 return nil, 0, p.newError("expect )") 493 case token.LBRACK: 494 if tyArr, err = p.parseArrays(ctypes.Void, 0); err != nil { 495 return 496 } 497 p.expect(token.RPAREN) // ) 498 case token.IDENT: 499 switch p.lit { 500 case "_Nullable", "_Nonnull", "const", "volatile": 501 goto nextTok 502 } 503 fallthrough 504 default: 505 return nil, 0, p.newError("expect )") 506 } 507 } 508 p.next() 509 switch p.tok { 510 case token.LPAREN: // ( 511 if t, err = p.parseFunc(pkg, t, inFlags); err != nil { 512 return 513 } 514 case token.LBRACK: // [ 515 if t, err = p.parseArrays(t, 0); err != nil { 516 return 517 } 518 case token.EOF: 519 case token.IDENT: 520 if p.lit == "__attribute__" { 521 p.tok, p.lit = token.EOF, "" 522 p.unget(token.EOF, "") 523 break 524 } 525 fallthrough 526 default: 527 return nil, 0, p.newError("unexpected " + p.tok.String()) 528 } 529 t = newPointers(t, nstarRet) 530 if isFn { 531 if getRetType(inFlags) { 532 p.tok = token.EOF 533 return 534 } 535 var results *types.Tuple 536 if ctypes.NotVoid(t) { 537 results = types.NewTuple(types.NewParam(token.NoPos, pkg, "", t)) 538 } 539 t = ctypes.NewFunc(types.NewTuple(args...), results, variadic) 540 } 541 t = newPointers(t, nstar) 542 t = newArrays(t, tyArr) 543 case token.RPAREN: 544 if t == nil { 545 t = ctypes.Void 546 } 547 return 548 case token.COMMA, token.EOF: 549 if t == nil { 550 err = io.ErrUnexpectedEOF 551 } 552 return 553 case token.ELLIPSIS: 554 if t != nil { 555 return nil, 0, p.newError("illegal syntax: multiple types?") 556 } 557 t = ctypes.Valist 558 kind |= KindFVariadic 559 default: 560 log.Panicln("c.types.ParseType: unknown -", p.tok, p.lit) 561 } 562 } 563 } 564 565 func newPointers(t types.Type, nstar int) types.Type { 566 for nstar > 0 { 567 t = ctypes.NewPointer(t) 568 nstar-- 569 } 570 return t 571 } 572 573 func isPtr(tok token.Token) bool { 574 return tok == token.MUL || tok == token.XOR // * or ^ 575 } 576 577 func newArrays(t types.Type, tyArr types.Type) types.Type { 578 retry: 579 if arr, ok := tyArr.(*types.Array); ok { 580 t = types.NewArray(t, arr.Len()) 581 tyArr = arr.Elem() 582 goto retry 583 } 584 return t 585 } 586 587 func newArraysEx(t types.Type, tyArr types.Type, inFlags int) types.Type { 588 t = newArrays(t, tyArr) 589 if arr, ok := t.(*types.Array); ok { 590 if (inFlags & FlagIsParam) != 0 { 591 t = ctypes.NewPointer(arr.Elem()) 592 } 593 } 594 return t 595 } 596 597 // -----------------------------------------------------------------------------