#include <boost/spirit.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <string>
#include <vector>
#include <stack>

using namespace boost::spirit;
using namespace boost;
using namespace std;

typedef function2<void, const char *, const char *> grammar_cb;
struct record_grammar:public grammar<record_grammar>{
	record_grammar( grammar_cb &property_name,
		grammar_cb &property_value,
		grammar_cb &end_property,
		grammar_cb &record_type,
		grammar_cb &record_name,
		grammar_cb &end_record):
			property_name(property_name),
			property_value(property_value),
			end_property(end_property),
			record_type(record_type),
			record_name(record_name),
			end_record(end_record){
	}


	template<class ScannerT>
	struct definition{
		rule<ScannerT> identifier;
		rule<ScannerT> string_literal;
		rule<ScannerT> prop_decl;
		rule<ScannerT> prop_list;
		rule<ScannerT> record_list;
		rule<ScannerT> record;

		definition(const record_grammar &self){
			identifier = lexeme_d[
				alpha_p >> *(alnum_p | ch_p('_') )
			];

			string_literal = lexeme_d[
				ch_p('"') >>
				*(
					(anychar_p - ch_p('"') )  |
					str_p("\\\"")
				) >>
				ch_p('"')
			];

			prop_decl = (
				identifier[self.property_name] >> ch_p('=') >>
				string_literal[self.property_value]
			)[self.end_property];

			prop_list = prop_decl >> *(ch_p(',') >> prop_decl);

			record_list = record >> *(ch_p(',') >> record);

			record = (
				identifier[self.record_type] >> 
				identifier[self.record_name] >> ch_p('{') >>
				!(
					(
						prop_list >>
						!(ch_p(',') >> record_list)
					) | record_list
				) >>
				ch_p('}')
			)[self.end_record];
					
		};

		rule<ScannerT> const& start(){return record_list;}
	};

	grammar_cb &property_name;
	grammar_cb &property_value;
	grammar_cb &end_property;
	grammar_cb &record_type;
	grammar_cb &record_name;
	grammar_cb &end_record;
};

struct property_info{
	string name, value;
};

struct record_info{
	string type;
	string name;
	vector<property_info> properties;
	vector<record_info> sub_records;
};

class document{
public:
	document(){
		record_stack.push(record_info());
	}

	parse_info<> parse(const std::string &data){
		grammar_cb property_name_f(bind(&document::property_name, this, _1,_2));
		grammar_cb property_value_f(bind(&document::property_value, this, _1,_2));
		grammar_cb end_property_f(bind(&document::end_property, this, _1,_2));
		grammar_cb record_type_f(bind(&document::record_type, this, _1,_2));
		grammar_cb record_name_f(bind(&document::record_name, this, _1,_2));
		grammar_cb end_record_f(bind(&document::end_record, this, _1, _2));
		record_grammar g(
			property_name_f, 
			property_value_f,
			end_property_f,
			record_type_f,
			record_name_f,
			end_record_f);
		parse_info<> info = boost::spirit::parse(data.c_str(), g >> eps_p, space_p);
		return info;
	}

	const record_info & result(){
		return record_stack.top();
	}

	void print(){
		for(vector<record_info>::const_iterator it = record_stack.top().sub_records.begin();
                        it != record_stack.top().sub_records.end();
                        it++){
			print("", *it);
		}
	}

private:
	void print(const string &prefix, const record_info &r){
		cout << prefix << "." << r.name << endl;
		cout << "\ttype:" << r.type << endl;
		cout << "\tproperties(" <<  r.properties.size() << "):" << endl;
		for(vector<property_info>::const_iterator it = r.properties.begin();
			it != r.properties.end(); it++){
			cout << "\t\t" << it->name << "=" << it->value << endl;
		}
		for(vector<record_info>::const_iterator it = r.sub_records.begin();
			it != r.sub_records.end();
			it++){
			print(prefix + "." + r.name, *it);
		}
	}

	void property_name(const char *start, const char *end){
		current_property.name = string(start, end);
	}
	void property_value(const char *start, const char *end){
		current_property.value = string(start, end);
	}
	void end_property(const char *start, const char *end){
		record_stack.top().properties.push_back(current_property);
	}
	void record_type(const char *start, const char *end){
		record_stack.push(record_info());
		record_stack.top().type = string(start, end);
	}
	void record_name(const char *start, const char *end){
		record_stack.top().name = string(start, end);
	}
	void end_record(const char *start, const char *end){
		record_info top = record_stack.top();
		record_stack.pop();
		record_stack.top().sub_records.push_back(top);
	}
	
	stack<record_info> record_stack;
	property_info current_property;
};

int main(){
	string input;
	string temp;
	while(getline(cin, temp)){
		input += temp;
	}
	document d;
	parse_info<> info = d.parse(input);
	if(!info.full){
		cout << "Error found at location: " << info.stop << endl;
	}else{
		d.print();
	}
}
