code: Expr atom() {
  		Tok tok = peek();
  		switch (tok.sym) {
  		case LPAREN:
  			move();
  			Expr expr = expr();
  			match(Sym.RPAREN);
  			return expr;
  		case ID:
  			move();
  			return new Id(tok.value());
  		case STR:
  			move();
  			return new Const(tok.sym, tok.value());
  		case INT:
  		case LONG:
  		case FLOAT:
  		case DOUBLE:
  			move();
  			return new Const(tok.sym, ((NumTok)tok).getNumberValue());
  		case TRUE:
  			move();
  			return Const.TRUE;
  		case FALSE:
  			move();
  			return Const.FALSE;
  		case NULL:
  			move();
  			return Const.NULL;
  		case COMMA:
  		case SEMICOLON:
  		case QUESTION:	// support "c ?? ? a : b"
  		case AND: case OR: case EQUAL: case NOTEQUAL:	// support "a.b ?? && expr"
  		case RPAREN:	// support "(a.b ??)"
  		case RBRACK:	// support "[start .. end ??]"
  		case RBRACE:	// support "{key : value ??}"
  		case RANGE:		// support "[start ?? .. end]"
  		case COLON:		// support "c ? a ?? : b"
  		case EOF:
  			return null;
  		default :
  			throw new ParseException("Expression error: can not match the symbol \"" + tok.value() + "\"", location);
  		}
  	}
docs: atom : '(' expr ')' | ID | STR | 'true' | 'false' | 'null'
  | INT | LONG | FLOAT | DOUBLE