diff --git a/.gitignore b/.gitignore index 3506f20..27b42c1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ vendor/ .vscode/ -/removecomments \ No newline at end of file +/removecomments +/snake2camel \ No newline at end of file diff --git a/makefile b/makefile index 0835af5..c9b8c9e 100644 --- a/makefile +++ b/makefile @@ -22,11 +22,7 @@ docs: dots parser/docs/minimal_types.png parser/docs/falco_types.png parser/docs .PHONY: snake2camel snake2camel: - @awk -i inplace '{ \ - while ( match($$0, /(.*)([a-z]+[0-9]*)_([a-zA-Z0-9])(.*)/, cap) ) \ - $$0 = cap[1] cap[2] toupper(cap[3]) cap[4]; \ - print \ - }' $(file) + @go build ./tools/snake2camel .PHONY: removecomments removecomments: @@ -78,10 +74,12 @@ parser/machine.go: parser/machine.go.rl common/common.rl parser/machine.go: removecomments +parser/machine.go: snake2camel + parser/machine.go: $(RAGEL) -Z -G2 -e -o $@ $< @./removecomments $@ - $(MAKE) file=$@ snake2camel + @./snake2camel $@ $(GOFMT) $@ .PHONY: tests diff --git a/tools/snake2camel/main.go b/tools/snake2camel/main.go new file mode 100644 index 0000000..a277d71 --- /dev/null +++ b/tools/snake2camel/main.go @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: Apache-2.0 +// +// Copyright © 2020- Leonardo Di Donato +package main + +import ( + "fmt" + "os" + "regexp" + "strings" +) + +func exitWithError(msg string) { + err := fmt.Sprintf("error: %s\n", msg) + fmt.Fprintln(os.Stderr, err) + os.Exit(1) +} + +func replaceAllStringSubmatchFunc(re *regexp.Regexp, str string, repl func([]string) string) (string, int) { + result := "" + lastIndex := 0 + + for _, v := range re.FindAllSubmatchIndex([]byte(str), -1) { + groups := []string{} + for i := 0; i < len(v); i += 2 { + if v[i] == -1 || v[i+1] == -1 { + groups = append(groups, "") + } else { + groups = append(groups, str[v[i]:v[i+1]]) + } + } + + result += str[lastIndex:v[0]] + repl(groups) + lastIndex = v[1] + } + + return result + str[lastIndex:], lastIndex +} + +func snake2camel(content []byte) []byte { + re := regexp.MustCompile(`(.*)([a-z]+[0-9]*)_([a-zA-Z0-9])(.*)`) + res := string(content) + last := -1 + + for last != 0 { + res, last = replaceAllStringSubmatchFunc(re, res, func(groups []string) string { + return groups[1] + groups[2] + strings.ToUpper(groups[3]) + groups[4] + }) + } + + return []byte(res) +} + +func snake2camelFile(path string) error { + content, err := os.ReadFile(path) + if err != nil { + return err + } + updated := snake2camel(content) + + return os.WriteFile(path, updated, 0) +} + +func main() { + if len(os.Args) != 2 { + exitWithError("must be called with the file path as the only argument") + } + path := os.Args[1] + if err := snake2camelFile(path); err != nil { + exitWithError(err.Error()) + } +}