def _ReadArithSub2Part(self): # type: () -> word_part__ArithSubPart """Non-standard arith sub $[a + 1].""" left_span_id = self.cur_token.span_id self._Next(lex_mode_e.Arith) anode = self._ReadArithExpr() if self.token_type != Id.Arith_RBracket: p_die('Expected ], got %r', self.cur_token.val, token=self.cur_token) right_span_id = self.cur_token.span_id node = word_part.ArithSubPart(anode) node.spids.append(left_span_id) node.spids.append(right_span_id) return node
def _ReadArithSubPart(self): # type: () -> word_part__ArithSubPart """ 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 self._Next(lex_mode_e.Arith) anode = self._ReadArithExpr() if self.token_type != Id.Arith_RParen: p_die('Expected first ) to end arith sub, got %r', self.cur_token.val, token=self.cur_token) self._Next(lex_mode_e.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: p_die('Expected second ) to end arith sub, got %r', self.cur_token.val, token=self.cur_token) right_span_id = self.cur_token.span_id node = word_part.ArithSubPart(anode) node.spids.append(left_span_id) node.spids.append(right_span_id) return node