github.com/goplus/llgo@v0.8.3/chore/llpyg/pysig/parse.go (about) 1 /* 2 * Copyright (c) 2024 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 pysig 18 19 import ( 20 "strings" 21 ) 22 23 type Arg struct { 24 Name string 25 Type string 26 DefVal string 27 } 28 29 // Parse parses a Python function signature. 30 func Parse(sig string) (args []*Arg) { 31 sig = strings.TrimPrefix(sig, "(") 32 for { 33 pos := strings.IndexAny(sig, ",:=)") 34 if pos <= 0 { 35 return 36 } 37 arg := &Arg{Name: strings.TrimSpace(sig[:pos])} 38 args = append(args, arg) 39 c := sig[pos] 40 sig = sig[pos+1:] 41 switch c { 42 case ',': 43 continue 44 case ':': 45 arg.Type, sig = parseType(sig) 46 if strings.HasPrefix(sig, "=") { 47 arg.DefVal, sig = parseDefVal(sig[1:]) 48 } 49 case '=': 50 arg.DefVal, sig = parseDefVal(sig) 51 case ')': 52 return 53 } 54 sig = strings.TrimPrefix(sig, ",") 55 } 56 } 57 58 const ( 59 allSpecials = "([<'\"" 60 ) 61 62 var pairStops = map[byte]string{ 63 '(': ")" + allSpecials, 64 '[': "]" + allSpecials, 65 '<': ">" + allSpecials, 66 '\'': "'" + allSpecials, 67 '"': "\"", 68 } 69 70 func parseText(sig string, stops string) (left string) { 71 for { 72 pos := strings.IndexAny(sig, stops) 73 if pos < 0 { 74 return sig 75 } 76 if c := sig[pos]; c != stops[0] { 77 if pstop, ok := pairStops[c]; ok { 78 sig = strings.TrimPrefix(parseText(sig[pos+1:], pstop), pstop[:1]) 79 continue 80 } 81 } 82 return sig[pos:] 83 } 84 } 85 86 // stops: "=,)" 87 func parseType(sig string) (string, string) { 88 left := parseText(sig, "=,)"+allSpecials) 89 return resultOf(sig, left), left 90 } 91 92 // stops: ",)" 93 func parseDefVal(sig string) (string, string) { 94 left := parseText(sig, ",)"+allSpecials) 95 return resultOf(sig, left), left 96 } 97 98 func resultOf(sig, left string) string { 99 return strings.TrimSpace(sig[:len(sig)-len(left)]) 100 }