diff --git a/syntax/filetests_test.go b/syntax/filetests_test.go index 79a8b479..7a5d5be1 100644 --- a/syntax/filetests_test.go +++ b/syntax/filetests_test.go @@ -1797,7 +1797,7 @@ var fileTests = []testCase{ { Strs: []string{ `$(echo '\' 'a\b' "\\" "a\a")`, - "`" + `echo '\' 'a\b' "\\\\" "a\a"` + "`", + "`" + `echo '\' 'a\\b' "\\\\" "a\a"` + "`", }, common: cmdSubst(stmt(call( litWord("echo"), @@ -4589,7 +4589,7 @@ func recursiveSanityCheck(tb testing.TB, src string, v any) { return } } - tb.Errorf("Expected one of %q at %d in %q, found %q", + tb.Errorf("Expected one of %q at %s in %q, found %q", strs, pos, src, gotErr) } checkNodePosEnd := func(n Node) { @@ -4701,7 +4701,7 @@ func recursiveSanityCheck(tb testing.TB, src string, v any) { tb.Errorf("Lit without newlines has Pos/End lines %d and %d", posLine, endLine) case strings.Contains(src, "`") && strings.Contains(src, "\\"): - // removed quotes inside backquote cmd substs + // removed backslashes inside backquote cmd substs val = "" case end < len(src) && (src[end] == '\n' || src[end] == '`'): // heredoc literals that end with the @@ -4794,7 +4794,12 @@ func recursiveSanityCheck(tb testing.TB, src string, v any) { if x.Dollar { valuePos = posAddCol(valuePos, 1) } - checkPos(valuePos, x.Value) + val := x.Value + if strings.Contains(src, "`") && strings.Contains(src, "\\") { + // removed backslashes inside backquote cmd substs + val = "" + } + checkPos(valuePos, val) if x.Dollar { checkPos(x.Left, "$'") } else { diff --git a/syntax/lexer.go b/syntax/lexer.go index 1128fa3b..588ab061 100644 --- a/syntax/lexer.go +++ b/syntax/lexer.go @@ -412,11 +412,6 @@ func (p *Parser) peekByte(b byte) bool { func (p *Parser) regToken(r rune) token { switch r { case '\'': - if p.openBquotes > 0 { - // bury openBquotes - p.buriedBquotes = p.openBquotes - p.openBquotes = 0 - } p.rune() return sglQuote case '"': diff --git a/syntax/parser.go b/syntax/parser.go index d71950b4..b675de3d 100644 --- a/syntax/parser.go +++ b/syntax/parser.go @@ -389,9 +389,6 @@ type Parser struct { // lastBquoteEsc is how many times the last backquote token was escaped lastBquoteEsc int - // buriedBquotes is like openBquotes, but saved for when the parser - // comes out of single quotes - buriedBquotes int rxOpenParens int rxFirstPart bool @@ -435,7 +432,7 @@ func (p *Parser) reset() { p.openStmts = 0 p.heredocs, p.buriedHdocs = p.heredocs[:0], 0 p.parsingDoc = false - p.openBquotes, p.buriedBquotes = 0, 0 + p.openBquotes = 0 p.accComs, p.curComs = nil, &p.accComs p.litBatch = nil p.wordBatch = nil @@ -1124,10 +1121,6 @@ func (p *Parser) wordPart() WordPart { sq.Right = p.nextPos() sq.Value = p.endLit() - // restore openBquotes - p.openBquotes = p.buriedBquotes - p.buriedBquotes = 0 - p.rune() p.next() return sq