fix(parser): peel stacked labels the way the formatter renders them
Assisted-by: GLM 5.3
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
go test fuzz v1
|
||||||
|
string("A:A:")
|
||||||
+17
-11
@@ -160,12 +160,20 @@ func (p *state) parseLine(line []token.Token) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Label (ident immediately followed by a colon).
|
// Label (ident immediately followed by a colon). Stacked labels
|
||||||
|
// share one line ("a: b: MOVQ …"): each peels off as its own Label,
|
||||||
|
// the same statement sequence the canonical layout puts on separate
|
||||||
|
// lines, so a file and its formatted image parse alike. A directive
|
||||||
|
// never peels: it stays with the instruction parse, as in the
|
||||||
|
// formatter's label handling.
|
||||||
if len(line) >= 2 && line[1].Kind == token.Colon {
|
if len(line) >= 2 && line[1].Kind == token.Colon {
|
||||||
lbl := &ast.Label{Name: line[0], Colon: line[1]}
|
rest := line
|
||||||
p.addStmt(lbl)
|
for len(rest) >= 2 && rest[0].Kind == token.Ident && rest[1].Kind == token.Colon &&
|
||||||
// A label may share its line with an instruction: "loop: MOVQ …".
|
!isDirective(rest[0].Text) {
|
||||||
if rest := dropColon(line); len(rest) > 0 {
|
p.addStmt(&ast.Label{Name: rest[0], Colon: rest[1]})
|
||||||
|
rest = rest[2:]
|
||||||
|
}
|
||||||
|
if len(rest) > 0 {
|
||||||
p.parseInstr(rest)
|
p.parseInstr(rest)
|
||||||
}
|
}
|
||||||
p.pending = nil
|
p.pending = nil
|
||||||
@@ -182,12 +190,10 @@ func (p *state) parseLine(line []token.Token) {
|
|||||||
p.pending = nil
|
p.pending = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// dropColon removes the leading "ident :" of a label, returning the remainder.
|
// isDirective reports whether the identifier names a top-level declaration
|
||||||
func dropColon(line []token.Token) []token.Token {
|
// directive rather than an instruction or a label.
|
||||||
if len(line) >= 2 && line[1].Kind == token.Colon {
|
func isDirective(s string) bool {
|
||||||
return line[2:]
|
return s == "TEXT" || s == "DATA" || s == "GLOBL"
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *state) addStmt(s ast.Stmt) {
|
func (p *state) addStmt(s ast.Stmt) {
|
||||||
|
|||||||
Reference in New Issue
Block a user