def _ReadArithSub2Part(self): """Non-standard arith sub $[a + 1].""" left_span_id = self.cur_token.span_id anode = self._ReadArithExpr() if not anode: self.AddErrorContext("Error parsing arith sub part") return None if self.token_type != Id.Arith_RBracket: self.AddErrorContext("Expected ], got %s", self.cur_token) return None right_span_id = self.cur_token.span_id node = ast.ArithSubPart(anode) node.spids.append(left_span_id) node.spids.append(right_span_id) return node
def _ReadArithSubPart(self): """ Read an arith substitution, which contains an arith expression, e.g. $((a + 1)). """ left_span_id = self.cur_token.span_id # The second one needs to be disambiguated in stuff like stuff like: # $(echo $(( 1+2 )) ) self.lexer.PushHint(Id.Op_RParen, Id.Right_ArithSub) # NOTE: To disambiguate $(( as arith sub vs. command sub and subshell, we # could save the lexer/reader state here, and retry if the arithmetic parse # fails. But we can almost always catch this at parse time. There could # be some exceptions like: # $((echo * foo)) # looks like multiplication # $((echo / foo)) # looks like division anode = self._ReadArithExpr() if not anode: self.AddErrorContext("Error parsing arith sub part") return None if self.token_type != Id.Arith_RParen: self._BadToken('Expected first paren to end arith sub, got %s', self.cur_token) return None self._Next(LexMode.OUTER) # TODO: This could be DQ or ARITH too # PROBLEM: $(echo $(( 1 + 2 )) ) # Two right parens break the Id.Eof_RParen scheme self._Peek() if self.token_type != Id.Right_ArithSub: self._BadToken('Expected second paren to end arith sub, got %s', self.cur_token) return None right_span_id = self.cur_token.span_id node = ast.ArithSubPart(anode) node.spids.append(left_span_id) node.spids.append(right_span_id) return node