File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -4914,6 +4914,20 @@ var fileTests = []fileTestCase{
49144914 }},
49154915 }}}, LangBash ),
49164916 ),
4917+ fileTest (
4918+ []string {`a=([i])` },
4919+ langFile (& CallExpr {Assigns : []* Assign {{
4920+ Name : lit ("a" ),
4921+ Array : arrValues (word (lit ("[i]" ))),
4922+ }}}, LangBash | LangZsh ),
4923+ ),
4924+ fileTest (
4925+ []string {`a=("foo"[0-9])` },
4926+ langFile (& CallExpr {Assigns : []* Assign {{
4927+ Name : lit ("a" ),
4928+ Array : arrValues (word (dblQuoted (lit ("foo" )), lit ("[0-9]" ))),
4929+ }}}, LangBash | LangZsh ),
4930+ ),
49174931 fileTest (
49184932 []string {"a]b" },
49194933 langFile (litStmt ("a]b" )),
Original file line number Diff line number Diff line change @@ -325,7 +325,7 @@ skipSpace:
325325 }
326326 p .next ()
327327 case '[' :
328- if p .quote == arrayElems {
328+ if p .quote == arrayElems && p . arrayIndexAssign () {
329329 p .rune ()
330330 p .tok = leftBrack
331331 } else {
@@ -1066,6 +1066,54 @@ func (p *Parser) zshNumRange() bool {
10661066 return len (rest ) > 0 && rest [0 ] == '>'
10671067}
10681068
1069+ // arrayIndexAssign peeks ahead after a '[' in an array literal and reports
1070+ // whether it begins an indexed assignment like [x]=y rather than a word that
1071+ // happens to start with a bracket glob, like [0-9] or [[:space:]].
1072+ func (p * Parser ) arrayIndexAssign () bool {
1073+ rest := p .bs [p .bsp :]
1074+ depth := 1
1075+ var quote byte
1076+ escaped := false
1077+ for i , b := range rest {
1078+ if quote != 0 {
1079+ if escaped {
1080+ escaped = false
1081+ continue
1082+ }
1083+ if quote == '"' && b == '\\' {
1084+ escaped = true
1085+ continue
1086+ }
1087+ if b == quote {
1088+ quote = 0
1089+ }
1090+ continue
1091+ }
1092+ if escaped {
1093+ escaped = false
1094+ continue
1095+ }
1096+ switch b {
1097+ case '\\' :
1098+ escaped = true
1099+ case '\'' , '"' :
1100+ quote = b
1101+ case '[' :
1102+ depth ++
1103+ case ']' :
1104+ depth --
1105+ if depth == 0 {
1106+ return i + 1 < len (rest ) && rest [i + 1 ] == '='
1107+ }
1108+ }
1109+ }
1110+ // If we can't find a matching closing bracket in the buffered input, keep the
1111+ // existing indexed-assignment tokenization and let the parser report any
1112+ // syntax errors. This keeps the lookahead conservative and avoids changing
1113+ // unrelated incomplete forms.
1114+ return true
1115+ }
1116+
10691117func (p * Parser ) advanceLitNone (r rune ) {
10701118 p .eqlOffs = - 1
10711119 tok := _LitWord
Original file line number Diff line number Diff line change @@ -1693,11 +1693,6 @@ var errorCases = []errorCase{
16931693 "a=([i)" ,
16941694 langErr ("1:4: reached `)` without matching `[` with `]`" , LangBash | LangZsh ),
16951695 ),
1696- errCase (
1697- "a=([i])" ,
1698- langErr ("1:4: `[x]` must be followed by `=`" , LangBash | LangZsh ),
1699- flipConfirmAll , // TODO: why is this valid?
1700- ),
17011696 errCase (
17021697 "a[i]=(y)" ,
17031698 langErr ("1:5: arrays cannot be nested" , LangBash ),
You can’t perform that action at this time.
0 commit comments