// Arup Guha
// 10/18/2014
// Solution to 2013 UChicago Contest Problem K: Uniform Subtrees
// Note: This takes 16 sec. on my desktop, which, I think isn't so bad for 15 MB of output.

import java.util.*;

public class k {

	// Easier if we have access to these.
	public static int index;
	public static String line;

	public static void main(String[] args) {

		Scanner stdin = new Scanner(System.in);
		line = stdin.next();

		// Process each case.
		while (!line.equals("0")) {
			index = 0;
			node root = makeTree();
			System.out.print(root);
			line = stdin.next();
		}
	}

	// Returns the tree corresponding to the current value of index, guaranteed to be '('
	public static node makeTree() {

		// Set up.
		ArrayList<node> kids = new ArrayList<node>();
		index++;

		// We'll break out later.
		while (true) {

			// Form this new subtree.
			if (line.charAt(index) == '(') {
				node next = makeTree();
				kids.add(next);
			}

			// Our tree at this level is ending, compute it.
			else {

				// Store answer in result.
				index++;
				node result = new node(kids);

				// Store how many of each sequence there are.
				HashMap<String,Integer> map = new HashMap<String,Integer>();
				int max = 0;

				// Go through each kid.
				for (int i=0; i<kids.size(); i++) {

					// And each of their subtrees.
					for (int j=0; j<kids.get(i).subtrees.size(); j++) {

						String cur = kids.get(i).subtrees.get(j).s;

						// Add to our hash map, accordingly.
						if (map.containsKey(cur)) {
							int cnt = map.get(cur);
							map.put(cur, cnt+1);
							max = Math.max(max, cnt+1);
						}
						else {
							map.put(cur, 1);
							max = Math.max(max, 1);
						}
					}
				}

				// Extract sequences and sort.
				seq[] allSeq = new seq[map.size()];
				int cnt = 0;
				for (String s:map.keySet())
					allSeq[cnt++] = new seq(s);
				Arrays.sort(allSeq);

				// Go through each kid sequence - and build new sequences for this root node.
				for (int i=0; i<=max; i++) {
					if (i == 0) result.subtrees.add(new seq("0"));
					else {
						for (int j=0; j<allSeq.length; j++)
							if (map.get(allSeq[j].s) >= i)
								result.subtrees.add(new seq(i,allSeq[j].s));
					}
				}

				// Trying to save memory!
				for (int i=0; i<result.kids.size(); i++)
					result.kids.get(i).kill();

				// Now, we're done, return.
				return result;
			}
		}

	}
}

class node {

	// What's in a node - kids is structure, subtrees is answer.
	public ArrayList<seq> subtrees;
	public ArrayList<node> kids;

	public node() {
		subtrees = new ArrayList<seq>();
		kids = new ArrayList<node>();
	}

	public node(ArrayList<node> myKids) {
		subtrees = new ArrayList<seq>();
		kids = myKids;
	}

	// Garbage collection will do the rest.
	public void kill() {
		subtrees = null;
		kids = null;
	}

	// Return the representation desired for the output.
	public String toString() {
		StringBuilder bob = new StringBuilder();
		for (int i=0; i<subtrees.size(); i++) {
			bob.append(subtrees.get(i).toString());
			bob.append('\n');
		}
		return bob.toString();
	}
}

class seq implements Comparable<seq> {

	public String s;

	public seq(String myseq) {
		s = myseq;
	}

	// Prepend myseq with item to form this sequence.
	public seq(int item, String myseq) {

		// Multiple case - store without compression.
		if (item != 1)
			s = item + " " + myseq;

		// New 1 case - use star to allow for future compression.
		else if (myseq.charAt(0) != '*') {
			s = "*1 " + myseq;
		}

		// Compression case - adding 1 to previous sequence of 1s. *n = n 1s.
		else {
			int i = 1;
			int value = 0;
			while (i < myseq.length() && Character.isDigit(myseq.charAt(i))) {
				value = 10*value + myseq.charAt(i) - '0';
				i++;
			}
			s = "*"+(value+1)+myseq.substring(i);
		}
	}

	// Returns a string representation of this sequence.
	public String toString() {

		// Need to tokenize.
		String res = "";
		StringTokenizer tok = new StringTokenizer(s);
		int size = tok.countTokens();

		// Go through each token.
		for (int i=0; i<size; i++) {

			// spaces in between.
			if (i > 0) res = res + " ";
			String next = tok.nextToken();

			// Expand 1s or just use the number.
			if (next.charAt(0) == '*')
				res = res + form(Integer.parseInt(next.substring(1)));
			else
				res = res + next;
		}
		return res;
	}

	// Returns a sequence of n 1s
	public static String form(int n) {
		char[] arr = new char[2*n-1];
		Arrays.fill(arr, ' ');
		for (int i=0; i<arr.length; i+=2)
			arr[i] = '1';
		return new String(arr);
	}


	public int compareTo(seq other) {

		// Have to go token by token.
		StringTokenizer thistok = new StringTokenizer(s);
		StringTokenizer othertok = new StringTokenizer(other.s);

		// Avoid crashing...
		while (thistok.hasMoreTokens() && othertok.hasMoreTokens()) {

			// Get next token.
			String thiscur = thistok.nextToken();
			String othercur = othertok.nextToken();
			if (thiscur.equals(othercur)) continue;

			// Tough case - two different sequences of 1s.
			if (thiscur.charAt(0) == '*' && othercur.charAt(0) == '*') {

				// See how many ones.
				int thisnum  = Integer.parseInt(thiscur.substring(1));
				int othernum = Integer.parseInt(othercur.substring(1));

				// In both cases we must look ahead if possible and break tie with the new number from
				// the shorter sequence, if it exists.
				if (thisnum < othernum) {
					if (!thistok.hasMoreTokens()) return -1;
					int next = Integer.parseInt(thistok.nextToken());
					return next-1;
				}
				else {
					if (!othertok.hasMoreTokens()) return 1;
					int next = Integer.parseInt(othertok.nextToken());
					return 1-next;
				}
			}

			// One sequence of 1s the other isn't.
			else if (thiscur.charAt(0) == '*') {
				if (othercur.charAt(0) == '0') return 1;
				else return -1;
			}
			else if (othercur.charAt(0) == '*') {
				if (thiscur.charAt(0) == '0') return -1;
				return 1;
			}

			// Easy case - two non-ones.
			else {
				return Integer.parseInt(thiscur) - Integer.parseInt(othercur);
			}
		}

		// Tied if we get all the way here.
		return 0;
	}
}
