共计 2167 个字符,预计需要花费 6 分钟才能阅读完成。
起因是在写一个函数的时候
func (g *Grammar) extractCommonFactors() { | |
flag := false | |
newNonTerminalCounter := 0 | |
for i, production := range g.Productions {newAlternatives := []Alternative{} | |
prefixMap := make(map[Symbol][]Alternative) | |
for _, alternative := range production.Right {if len(alternative.Symbols) > 0 {firstSymbol := alternative.Symbols[0] | |
if _, ok := prefixMap[firstSymbol]; !ok {prefixMap[firstSymbol] = []Alternative{} | |
} | |
prefixMap[firstSymbol] = append(prefixMap[firstSymbol], alternative) | |
} | |
} | |
for _, alternatives := range prefixMap {if len(alternatives) > 1 { | |
flag = true | |
commonPrefix := findLongestCommonPrefix(alternatives) | |
newNonTerminalCounter++ | |
newValue := fmt.Sprintf("A%d", newNonTerminalCounter) | |
newNonTerminal := Symbol{ | |
Value: newValue, | |
IsTerminal: false, | |
} | |
newRight := removeCommonPrefix(alternatives, commonPrefix) | |
newProduction := Production{ | |
Left: newNonTerminal, | |
Right: newRight, | |
} | |
g.Productions = append(g.Productions, newProduction) | |
var newAlternative Alternative | |
newAlternative.Symbols = commonPrefix | |
//bug 呈现的中央 | |
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal) | |
newAlternatives = append(newAlternatives, newAlternative) | |
} else {newAlternatives = append(newAlternatives, alternatives[0]) | |
} | |
} | |
g.Productions[i].Right = newAlternatives | |
} | |
if flag {fmt.Println("extractCommonFactors grammar:") | |
for _, prod := range g.Productions {rightParts := make([]string, len(prod.Right)) | |
for i, alt := range prod.Right {symbols := make([]string, len(alt.Symbols)) | |
for j, sym := range alt.Symbols {symbols[j] = sym.Value | |
} | |
rightParts[i] = strings.Join(symbols, "") | |
} | |
fmt.Printf("%s -> %s\n", prod.Left.Value, strings.Join(rightParts, "|")) | |
} | |
} | |
} |
发现每次在执行
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal)
时总会莫名其妙批改掉 g.Productions 中的数据
起因就是因为
var newAlternative Alternative | |
newAlternative.Symbols = commonPrefix | |
//bug 呈现的中央 | |
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal) |
中的 newAlternative.Symbols 是一个数组切片,这里间接对切片赋值,实质上是将 newAlternative.Symbols 的内容批改为 commonPrefix 切片所指向的数组,所以后续在批改 newAlternative.Symbols 时对别的内容也会产生影响
改过为
var newAlternative Alternative | |
commonPrefixCopy := make([]Symbol, len(commonPrefix)) | |
copy(commonPrefixCopy, commonPrefix) | |
newAlternative.Symbols = commonPrefixCopy | |
newAlternative.Symbols = append(newAlternative.Symbols, newNonTerminal) |
之后问题就隐没了
因为 copy 函数是在内存中开拓一个新的数组给复制的切片应用,这样尽管耗费了更多的内存,但也更平安,是个更好的开发习惯
正文完