#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <cfloat>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
#include <time.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


enum Type{
	POINT,
	LINE,
};

struct Point{
	void set(double arg_x,double arg_y){
		x = arg_x;
		y = arg_y;
	}
	double x,y;
};

struct Data{
	Type type;
	Point p1,p2;
};

Point calc_Cross_Point(double x1,double x2,double x3,double x4,double y1,double y2,double y3,double y4){
	Point ret;
	ret.x = ((x2-x1)*(y3*(x4-x3)+x3*(y3-y4))-(x4-x3)*(y1*(x2-x1)+x1*(y1-y2)))/((y2-y1)*(x4-x3)-(y4-y3)*(x2-x1));
	if(x1 != x2){
		ret.y = ((y2-y1)*ret.x+y1*(x2-x1)+x1*(y1-y2))/(x2-x1);
	}else{
		ret.y = ((y4-y3)*ret.x+y3*(x4-x3)+x3*(y3-y4))/(x4-x3);
	}
	return ret;
}

Point calc_Reflection_Point(double x1,double y1,double x2,double y2,double xp,double yp){

	Point ret;

	bool X_FLG = false,Y_FLG = false;
	double slope;

	if(y1 == y2){
		X_FLG = true;
	}else if(x1 == x2){
		Y_FLG = true;
	}else{
		slope = (y2-y1)/(x2-x1);
	}

	if(X_FLG){
		ret.x = xp,ret.y=y1;
	}else if(Y_FLG){
		ret.x = x1,ret.y = yp;
	}else{
		ret.x = (yp*(x2-x1)*(y2-y1)+xp*(x2-x1)*(x2-x1)-y1*(y2-y1)*(x2-x1)+x1*(y2-y1)*(y2-y1))/((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1));
		ret.y = ((x1-x2)*ret.x+yp*(y2-y1)+xp*(x2-x1))/(y2-y1);
	}
	ret.x = 2*ret.x-xp;
	ret.y = 2*ret.y-yp;

	return ret;
}

char buf[101];

Data recursive(int left,int right){

	queue<int> Q;

	int depth = 0,max_depth = 0;
	for(int i = left; i <= right; i++){
		if(buf[i] == '('){
			depth++;
			max_depth = max(max_depth,depth);
		}else if(buf[i] == ')'){
			depth--;
		}else if(buf[i] == '@'){
			if(depth == 0)Q.push(i);
		}
	}

	int tmp,index;

	if(Q.empty()){

		if(max_depth >= 2){
			return recursive(left+1,right-1);
		}else{

			Data ret;
			bool negFLG = false;

			tmp = 0;
			for(index = left+1; buf[index] != ','; index++){
				if(buf[index] == '-'){
					negFLG = true;
					continue;
				}

				tmp = 10*tmp+(buf[index]-'0');
			}
			if(negFLG)tmp *= -1;
			ret.p1.x = (double)tmp;

			tmp = 0;
			negFLG = false;
			for(++index; buf[index] != ')'; index++){
				if(buf[index] == '-'){
					negFLG = true;
					continue;
				}
				tmp = 10*tmp+(buf[index]-'0');
			}
			if(negFLG)tmp *= -1;
			ret.p1.y = (double)tmp;
			ret.type = POINT;

			return ret;
		}
	}else{

		Data ret = recursive(left,Q.front()-1);

		Data calc;
		int loc = Q.front();
		Q.pop();
		while(!Q.empty()){
			calc = recursive(loc+1,Q.front()-1);
			if(ret.type == POINT && calc.type == POINT){
				ret.p2 = calc.p1;
				ret.type = LINE;
			}else if(ret.type == LINE && calc.type == LINE){
				ret.p1 = calc_Cross_Point(ret.p1.x,ret.p2.x,calc.p1.x,calc.p2.x,ret.p1.y,ret.p2.y,calc.p1.y,calc.p2.y);
				ret.type = POINT;
			}else{
				if(calc.type == LINE)swap(ret,calc);
				ret.p1 = calc_Reflection_Point(ret.p1.x,ret.p1.y,ret.p2.x,ret.p2.y,calc.p1.x,calc.p1.y);
				ret.type = POINT;
			}
			loc = Q.front();
			Q.pop();
		}
		calc = recursive(loc+1,right);
		if(ret.type == POINT && calc.type == POINT){
			ret.p2 = calc.p1;
			ret.type = LINE;
		}else if(ret.type == LINE && calc.type == LINE){
			ret.p1 = calc_Cross_Point(ret.p1.x,ret.p2.x,calc.p1.x,calc.p2.x,ret.p1.y,ret.p2.y,calc.p1.y,calc.p2.y);
			ret.type = POINT;
		}else{
			if(calc.type == LINE)swap(ret,calc);
			ret.p1 = calc_Reflection_Point(ret.p1.x,ret.p1.y,ret.p2.x,ret.p2.y,calc.p1.x,calc.p1.y);
			ret.type = POINT;
		}
		return ret;
	}
}

void func(){

	int length;

	for(length = 0; buf[length] != '\0'; length++);

	Data ret = recursive(0,length-1);

	printf("%.10lf %.10lf\n",ret.p1.x,ret.p1.y);
}

int main(){

	while(true){
		scanf("%s",buf);
		if(buf[0] == '#')break;

		func();
	}

	return 0;
}