From bddf993ebf121c2cc939aa2eedcd924eb8a0a9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Sun, 15 Mar 2026 00:34:33 +0800 Subject: [PATCH] feat(gen): add symbolTable --- gen/scan.go | 37 ++++++++++++++++++--------- gen/skip.go | 46 +++++++++++++++++++++++++++++++++ gen/symb.go | 73 +++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 139 insertions(+), 17 deletions(-) create mode 100644 gen/skip.go diff --git a/gen/scan.go b/gen/scan.go index 6198559..2a373b6 100644 --- a/gen/scan.go +++ b/gen/scan.go @@ -22,7 +22,7 @@ func infh(name string) string { func scanheader(name string, scan *bufio.Scanner) { ln := 0 var regionfile *os.File - symtab := map[string]symbol{ + symtab := symbolTable{ "ZE_APICALL": symbol{symbolTypeConst, "ZE_APICALL", []string{""}}, "ZE_APIEXPORT": symbol{symbolTypeConst, "ZE_APIEXPORT", []string{""}}, "ZE_DLLEXPORT": symbol{symbolTypeConst, "ZE_DLLEXPORT", []string{""}}, @@ -67,23 +67,28 @@ func scanheader(name string, scan *bufio.Scanner) { func scanblocks( name string, scan *bufio.Scanner, f *os.File, - ln int, symtab map[string]symbol, + ln int, symtab symbolTable, ) int { sb := strings.Builder{} - skip2nextblk := false - isinifndef := false + skip2nextblk := false //TODO: check logic + ifdepth := 0 + isparsing := func() bool { + //TODO: more condition + return ifdepth > 0 + } for scan.Scan() { ln++ t := scan.Text() switch { - // block barrier - case strings.HasPrefix(t, "///////////////////////////////////////////////////////////////////////////////"): + // block end + case t == "": + if isparsing() { + continue + } if sb.Len() != 0 { panic(fmt.Sprintf("%s L%d: unexpected non-0 sb at block end: %s", name, ln, &sb)) } - f.WriteString(t) - f.WriteString("\n") - skip2nextblk = false + return ln case skip2nextblk: continue // is definition's comment @@ -101,12 +106,20 @@ func scanblocks( if t[:8] != "#ifndef " { panic(fmt.Sprintf("%s L%d: unexpected #if type %s", name, ln, t)) } - isinifndef = true sname := strings.TrimSpace(t[8:]) - tab, ok := symtab[sname] + _, ok := symtab[sname] if ok { - //TODO: skip2 endif + ln = skip2endif(scan, ln) + continue } + ifdepth++ + case strings.HasPrefix(t, "#endif"): + ifdepth-- + if ifdepth < 0 { + panic(fmt.Sprintf("%s L%d: unexpected unpaired #endif", name, ln)) + } + case strings.HasPrefix(t, "#define"): + } } return ln diff --git a/gen/skip.go b/gen/skip.go new file mode 100644 index 0000000..9879b10 --- /dev/null +++ b/gen/skip.go @@ -0,0 +1,46 @@ +package main + +import ( + "bufio" + "errors" + "strings" +) + +func skip2endif(scan *bufio.Scanner, ln int) int { + depth := 1 + for scan.Scan() { + ln++ + t := scan.Text() + switch { + case strings.HasPrefix(t, "#endif"): + depth-- + case strings.HasPrefix(t, "#if"): + depth++ + default: + } + if depth <= 0 { + break + } + } + return ln +} + +func getinside0brakets(txt string) (string, int, error) { + depth := 0 + a := 0 + for i, t := range txt { + switch t { + case '(': + if depth == 0 { + a = i + 1 + } + depth++ + case ')': + depth-- + if depth <= 0 { + return txt[a:i], i, nil + } + } + } + return "", 0, errors.New("no round brakets pair in " + txt) +} diff --git a/gen/symb.go b/gen/symb.go index 52e76f3..759d226 100644 --- a/gen/symb.go +++ b/gen/symb.go @@ -6,6 +6,20 @@ import ( "strings" ) +var ( + errIsConstReplace = errors.New("is const replace") + errNoSuchSymbol = errors.New("no such sybmol") +) + +type symbolTable map[string]symbol + +func (st symbolTable) apply(t string) string { + for _, s := range st { + t = s.replace(t) + } + return t +} + type symbolType uintptr const ( @@ -26,13 +40,62 @@ type symbol struct { fields []string } -func (s *symbol) replace(txt string, args ...string) (string, error) { +func newsymbolconst(name, val string) symbol { + return symbol{ + stype: symbolTypeConst, + name: name, + fields: []string{val}, + } +} + +func newsymbolfunc(name, paras, evals string) symbol { + return symbol{ + stype: symbolTypeConst, + name: name, + fields: []string{paras, evals}, + } +} + +func (s *symbol) extractfirstfunc(txt string) (args []string, a, b int, err error) { + if s.stype == symbolTypeConst { + return nil, 0, 0, errIsConstReplace + } + a = strings.Index(txt, s.name) + if a < 0 { + return nil, 0, 0, errNoSuchSymbol + } + str, off, err := getinside0brakets(txt[a:]) + if err != nil { + return nil, 0, 0, err + } + args = strings.Split(str, ",") + for i, arg := range args { + args[i] = strings.TrimSpace(arg) + } + return args, a, a + off, nil +} + +func (s *symbol) replace(txt string) string { switch s.stype { case symbolTypeConst: - return strings.ReplaceAll(txt, s.name, s.fields[0]), nil + return strings.ReplaceAll(txt, s.name, s.fields[0]) case symbolTypeFunc: - //TODO: finish - return "", nil + paras := strings.Split(s.fields[0], ",") + for { + args, a, b, err := s.extractfirstfunc(txt) + if err == errNoSuchSymbol { + return txt + } + if len(paras) != len(args) { + panic("args " + strings.Join(args, ", ") + " count " + strconv.Itoa(len(args)) + " is different from recorded " + s.fields[0]) + } + txts := []string{txt[:a], txt[a:b], txt[b:]} + for i, p := range paras { + txts[1] = strings.ReplaceAll(txts[1], strings.TrimSpace(p), args[i]) + } + txts[1] = strings.ReplaceAll(txts[1], s.name, "") + txt = strings.Join(txts, "") + } } - return "", errors.New("unsupported symbol type " + strconv.Itoa(int(s.stype))) + panic("unsupported symbol type " + strconv.Itoa(int(s.stype))) }