code: Expr indexMethodField(Expr expr) {
  		if (expr == null) {
  			expr = map();
  		}
  		
  		// Expr expr = map();
  		while (true) {
  			Tok tok = peek();
  			// expr [ expr ]
  			if (tok.sym == Sym.LBRACK) {
  				move();
  				Expr index = expr();
  				match(Sym.RBRACK);
  				expr = new Index(expr, index, location);
  				continue;
  			}
  			if (tok.sym != Sym.DOT) {
  				return expr;
  			}
  			if ((tok = move()).sym != Sym.ID) {
  				resetForward(forward - 1);
  				return expr;
  			}
  			
  			move();
  			if (peek().sym != Sym.LPAREN) {
  				expr = new Field(expr, tok.value(), location);
  				continue;
  			}
  			
  			move();
  			// expr '.' ID '(' ')'
  			if (peek().sym == Sym.RPAREN) {
  				move();
  				expr = new Method(expr, tok.value(), location);
  				continue;
  			}
  			
  			// expr '.' ID '(' exprList ')'
  			ExprList exprList = exprList();
  			match(Sym.RPAREN);
  			expr = new Method(expr, tok.value(), exprList, location);
  		}
  	}
docs: index : expr '[' expr ']'
  method : expr '.' ID '(' exprList? ')'
  field :  expr '.' ID