Problem Statement

One day, you found an old scroll with strange texts on it.

You revealed that the text was actually an expression denoting the position of treasure. The expression consists of following three operations:

* From two points, yield a line on which the points lie.
* From a point and a line, yield a point that is symmetric to the given point with respect to the line.
* From two lines, yield a point that is the intersection of the lines.



The syntax of the expression is denoted by following BNF:


<expression>      ::= <point>
<point>       	  ::= <point-factor> | <line> "@" <line-factor> | <line> "@" <point-factor> | <point> "@" <line-factor>
<point-factor>    ::= "(" <number> "," <number> ")" | "(" <point> ")"
<line>            ::= <line-factor> | <point> "@" <point-factor>
<line-factor>     ::= "(" <line> ")"
<number>          ::= <zero-digit> | <positive-number> | <negative-number>
<positive-number> ::= <nonzero-digit> | <positive-number> <digit>
<negative-number> ::= "-" <positive-number>
<digit>           ::= <zero-digit> | <nonzero-digit>
<zero-digit>      ::= "0"
<nonzero-digit>   ::= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"

Each <point> or <point-factor> denotes a point, whereas each <line> or <line-factor> denotes a line. The former notion of <point-factor> $(X,Y)$ represents a point which has $X$ for $x$-coordinate and $Y$ for $y$-coordinate on the $2$-dimensional plane. "@" indicates the operations on two operands. Since each operation is distinguishable from others by its operands' types (i.e. a point or a line), all of these operations are denoted by the same character "@". Note that "@" is left-associative, as can be seen from the BNF.

Your task is to determine where the treasure is placed.

Input

The input consists of multiple datasets. Each dataset is a single line which contains an expression denoting the position of treasure.

It is guaranteed that each dataset satisfies the following conditions:

* The length of the string never exceeds $10^2$.
* If both operands of "@" are points, their distance is greater than $1$.
* If both operands of "@" are lines, they are never parallel.
* The absolute values of points' coordinates never exceed $10^2$ at any point of evaluation.



You can also assume that there are at most $100$ datasets.

The input ends with a line that contains only a single "#".

Output

For each dataset, print the $X$ and $Y$ coordinates of the point, denoted by the expression, in this order.

The output will be considered correct if its absolute or relative error is at most $10^{-2}$.

Sample Input


((0,0)@(1,1))@((4,1)@(2,5))
((0,0)@(3,1))@((1,-3)@(2,-1))
(0,0)@(1,1)@(4,1)
(0,0)@((1,1)@(4,1))
(((0,0)@((10,20)@(((30,40))))))
((0,0)@(3,1))@((1,-3)@(2,-1))@(100,-100)@(100,100)


Output for the Sample Input


3.00000000 3.00000000
3.00000000 1.00000000
1.00000000 4.00000000
0.00000000 2.00000000
-10.00000000 10.00000000
-99.83681795 -91.92248853





Example

Input

((0,0)@(1,1))@((4,1)@(2,5))
((0,0)@(3,1))@((1,-3)@(2,-1))
(0,0)@(1,1)@(4,1)
(0,0)@((1,1)@(4,1))
(((0,0)@((10,20)@(((30,40))))))
((0,0)@(3,1))@((1,-3)@(2,-1))@(100,-100)@(100,100)
#


Output

3.00000000 3.00000000
3.00000000 1.00000000
1.00000000 4.00000000
0.00000000 2.00000000
-10.00000000 10.00000000
-99.83681795 -91.92248853
#include<bits/stdc++.h>
#define range(i,a,b) for(int i = (a); i < (b); i++)
#define rep(i,b) for(int i = 0; i < (b); i++)
#define all(a) (a).begin(), (a).end()
#define show(x)  cerr << #x << " = " << (x) << endl;
using namespace std;

template<typename T>
ostream& operator << (ostream& os, vector<T>& v){
	rep(i,v.size()){ os << v[i] << (i == v.size() - 1 ? "" : " "); } return os;
}
template<typename T>
istream& operator >> (istream& is, vector<T>& v){
	for(T& x: v){ is >> x; } return is;
}

const double INF = 1e6;

typedef complex<double> Point;
typedef Point Vector;
struct Segment{					//線分を表す構造体
	Point p1, p2;
	Segment(Point p1 = Point(), Point p2 = Point()) : p1(p1), p2(p2) {}
	void out(){
		cout << p1 << ' ' << p2 << endl;
	}
};
typedef Segment Line;			//直線を表す構造体
typedef vector<Point> Polygon;	//多角形を表す構造体

namespace std{
	bool operator < (const Point &a, const Point &b){
		return real(a) != real(b) ? real(a) < real(b) : imag(a) < imag(b);
	}
	bool operator == (const Point &a, const Point &b){
		return a.real() == b.real() && a.imag() == b.imag();
	}
	bool operator == (const Segment &a, const Segment &b){
		return (a.p1 == b.p1 and a.p2 == b.p2) or (a.p1 == b.p2 and a.p2 == b.p1);
	}
}

class Circle{
	public:
		Point p;
		double r;
		Circle(Point p = Point(), double r = 0.0): p(p), r(r) {}
};

// 許容する誤差
#define EPS (1e-10)
#define INF (1e10)

// ベクトルaの絶対値を求める
//double length = abs(a);

// 2点a,b間の距離を求める
//double distance = abs(a-b);

/*
// ベクトルaの単位ベクトルを求める
Point b = a / abs(a);

// ベクトルaの法線ベクトルn1,n2を求める
Point n1 = a * Point(0, 1);
Point n2 = a * Point(0, -1);
*/

int ccw(Point, Point, Point);

// 2つのスカラーが等しいかどうか
bool EQ(double a, double b){
	return (abs(a - b) < EPS);
}

// 2つのベクトルが等しいかどうか
bool EQV(Vector a, Vector b){
	return ( EQ(a.real(), b.real()) && EQ(a.imag(), b.imag()) );
}

// 内積 (dot product) : a・b = |a||b|cosΘ
double dot(Point a, Point b) {
	return (a.real() * b.real() + a.imag() * b.imag());
}

// 外積 (cross product) : a×b = |a||b|sinΘ
double cross(Point a, Point b) {
	return (a.real() * b.imag() - a.imag() * b.real());
}

// 2直線の直交判定 : a⊥b <=> dot(a, b) = 0
bool isOrthogonal(Point a1, Point a2, Point b1, Point b2) {
	return EQ( dot(a1-a2, b1-b2), 0.0 );
}
bool isOrthogonal(Line s1, Line s2) { return isOrthogonal(s1.p1, s1.p2, s2.p1, s2.p2); }

// 2直線の平行判定 : a//b <=> cross(a, b) = 0
bool isParallel(Point a1, Point a2, Point b1, Point b2) {
	return EQ( cross(a1-a2, b1-b2), 0.0 );
}
bool isParallel(Line s1, Line s2) { return isParallel(s1.p1, s1.p2, s2.p1, s2.p2); }

// 点cが直線a,b上にあるかないか
bool isPointOnLine(Point a, Point b, Point c) {
	return EQ( cross(b-a, c-a), 0.0 );
}
bool isPointOnLine(Line s, Point c) { return isPointOnLine(s.p1, s.p2, c); }

// 点a,bを通る直線と点cとの距離
double distanceLPoint(Point a, Point b, Point c) {
	return abs(cross(b-a, c-a)) / abs(b-a);
}
double distanceLPoint(Line s, Point c) { return distanceLPoint(s.p1, s.p2, c); }

// 点a,bを端点とする線分と点cとの距離
double distanceLsPoint(Point a, Point b, Point c) {
	if ( dot(b-a, c-a) < EPS ) return abs(c-a);
	if ( dot(a-b, c-b) < EPS ) return abs(c-b);
	return abs(cross(b-a, c-a)) / abs(b-a);
}
double distanceLsPoint(Segment s, Point c) { return distanceLsPoint(s.p1, s.p2, c); }

// a1,a2を端点とする線分とb1,b2を端点とする線分の交差判定
// 端点が重なる場合も、線分が交差しているとみなす
bool isIntersectedLs(Point a1, Point a2, Point b1, Point b2) {
	return ( ccw(a1, a2, b1) * ccw(a1, a2, b2) <= 0 &&
			ccw(b1, b2, a1) * ccw(b1, b2, a2) <= 0 );
}
bool isIntersectedLs(Segment s1, Segment s2) { return isIntersectedLs(s1.p1, s1.p2, s2.p1, s2.p2); }

// 端点が重なっているかを検出する
bool isContainSamePoints(Segment s1, Segment s2){
	if(abs(s1.p1 - s2.p1) < EPS) return true;
	if(abs(s1.p1 - s2.p2) < EPS) return true;
	if(abs(s1.p2 - s2.p1) < EPS) return true;
	if(abs(s1.p2 - s2.p2) < EPS) return true;
	return false;
}

// a1,a2を端点とする線分とb1,b2を端点とする線分の交点計算
Point intersectionLs(Point a1, Point a2, Point b1, Point b2) {
	Vector base = b2 - b1;
	double d1 = abs(cross(base, a1 - b1));
	double d2 = abs(cross(base, a2 - b1));
	double t = d1 / (d1 + d2);

	return Point(a1 + (a2 - a1) * t);
}
Point intersectionLs(Segment s1, Segment s2) { return intersectionLs(s1.p1, s1.p2, s2.p1, s2.p2); }

// a1,a2を通る直線とb1,b2を通る直線の交差判定
bool isIntersectedL(Point a1, Point a2, Point b1, Point b2) {
	return !EQ( cross(a1-a2, b1-b2), 0.0 );
}
bool isIntersectedL(Line l1, Line l2) { return isIntersectedL(l1.p1, l1.p2, l2.p1, l2.p2); }

// a1,a2を通る直線とb1,b2を通る直線の交点計算
Point intersectionL(Point a1, Point a2, Point b1, Point b2) {
	Point a = a2 - a1; Point b = b2 - b1;
	return a1 + a * cross(b, b1-a1) / cross(b, a);
}
Point intersectionL(Line l1, Line l2) { return intersectionL(l1.p1, l1.p2, l2.p1, l2.p2); }

// 線分s1と線分s2の距離
double distanceLL(Segment s1, Segment s2){
	if(isIntersectedLs(s1.p1, s1.p2, s2.p1, s2.p2) ) return 0.0;
	return min(
			min(distanceLsPoint(s1.p1, s1.p2, s2.p1),
				distanceLsPoint(s1.p1, s1.p2, s2.p2)),
			min(distanceLsPoint(s2.p1, s2.p2, s1.p1),
				distanceLsPoint(s2.p1, s2.p2, s1.p2)) );
}
double distanceLL(Point p0, Point p1, Point p2, Point p3){
	Segment s1 = Segment{p0, p1}, s2 = Segment{p2, p3};
	return distanceLL(s1, s2);
}

// 線分sに対する点pの射影
Point project(Segment s, Point p){
	Vector base = s.p2 - s.p1;
	double r = dot(p - s.p1, base) / norm(base);
	return Point(s.p1 + base * r);
}

//線分sを対象軸とした点pの線対称の点
Point reflect(Segment s, Point p){
	return Point(p + (project(s, p) - p) * 2.0);
}

//点pをangle分だけ時計回りに回転
Point rotation(Point p, double angle){
	double x, y;
	x = p.real() * cos(angle) - p.imag() * sin(angle);
	y = p.real() * sin(angle) + p.imag() * cos(angle);
	return Point(x, y);
}

//円cと線分lの交点
pair<Point, Point> getCrossPoints(Circle c, Line l){
	Vector pr = project(l, c.p);
	Vector e = (l.p2 - l.p1) / abs(l.p2 - l.p1);
	double base = sqrt(c.r * c.r - norm(pr - c.p));
	return make_pair(pr + e * base, pr - e * base);
}

//円c1と円c2の交点
double arg(Vector p) { return atan2(p.imag(), p.real()); }
Vector polar(double a, double r) { return Point(cos(r) * a, sin(r) *a); }

pair<Point, Point> getCrossPoints(Circle c1, Circle c2){
	double d = abs(c1.p - c2.p);
	double a = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
	double t = arg(c2.p - c1.p);
	return make_pair(Point(c1.p + polar(c1.r, t + a)), Point(c1.p + polar(c1.r, t - a)));
}

static const int COUNTER_CLOCKWISE = 1;
static const int CLOCKWISE = -1;
static const int ONLINE_BACK = 2;
static const int ONLINE_FRONT = -2;
static const int ON_SEGMENT = 0;

int ccw(Point p0, Point p1, Point p2){
	Vector a = p1 - p0;
	Vector b = p2 - p0;
	if( cross(a, b) > EPS ) return COUNTER_CLOCKWISE;
	if( cross(a, b) < -EPS ) return CLOCKWISE;
	if( dot(a, b) < -EPS ) return ONLINE_BACK;
	if( abs(a) < abs(b) ) return ONLINE_FRONT;

	return ON_SEGMENT;
}


typedef string::const_iterator State;
typedef pair<Point,Point> P;
double number(State&);
P factor(State&);
P expression(State&);

bool isPoint(P &p){
	return p.second == Point(INF,INF);
}

double number(State &begin) {
	double ret = 0;
	bool minus;
	if(*begin == '-'){
		minus = true;
		begin++;
	}else minus = false;

	while (isdigit(*begin)) {
		ret *= 10;
		ret += *begin - '0';
		begin++;
	}

	if(minus) ret *= -1;
	return ret;
}

Point point(State &begin){
	double x, y;
	x = number(begin);
	begin++;
	y = number(begin);
	return Point(x,y);
}

// 括弧か数をパースして、その評価結果を返す。
P factor(State &begin) {
	if (*begin == '(') {
		begin++; // '('を飛ばす。
		P ret = expression(begin);
		begin++; // ')'を飛ばす。
		return ret;
	} else {
		P res;
		res = make_pair(point(begin), Point(INF,INF));
		return res;
	}
}

// 四則演算の式をパースして、その評価結果を返す。
P expression(State &begin) {
	P ret = factor(begin);

	for (;;) {
		if (*begin == '@') {
			begin++;

			P p = factor(begin);
			if(isPoint(ret) and isPoint(p)){
				ret = P(ret.first, p.first);
			}else if(isPoint(ret) and not isPoint(p)){
				ret = P(reflect(Segment{p.first, p.second}, ret.first), Point(INF,INF));
			}else if(not isPoint(ret) and isPoint(p)){
				ret = P(reflect(Segment{ret.first, ret.second}, p.first), Point(INF,INF));
			}else{
				ret = P(intersectionL(Line{ret.first, ret.second}, Line{p.first, p.second}), Point(INF,INF));
			}
		} else {
			break;
		}
	}

	return ret;
}

//beginがexpectedを指していたらbeginを一つ進める。
void consume(State &begin, char expected) {
	if (*begin == expected) {
		begin++;
	} else {
		cerr << "Expected '" << expected << "' but got '" << *begin << "'" << endl;
		cerr << "Rest string is '";
		while (*begin) {
			cerr << *begin++;
		}
		cerr << "'" << endl;
		//throw ParseError();
	}
}

int main(){
	string s;
	while(cin >> s, s != "#"){
		State tmp = s.begin();
		P res = expression(tmp);
		cout << fixed << setprecision(10) << res.first.real() << ' ' << res.first.imag() << endl;
	}
}

