{$A+,B-,D+,E+,F-,G-,I+,L+,N-,O-,P-,Q-,R-,S+,T-,V+,X+,Y+}
{$M 16384,0,655360}
program tab;
uses dos,strings;                                {a 0 1 2}
type ppch=^tpch;                                 {va 0}
     tpch=array [0..65534] of char;              {va 1}
var collumns:integer;                            {va 2}
    fin,fout:text;
    map:array [1..40,1..40] of record
                                  used:boolean;
                                  sizex,smallx,sizey:integer;
                                  a,va,rs,cs:byte;
                                  text:pchar;
                                 end;
    colwidths,
    maxwidths,
    rowwidths:array [1..40] of integer;
    sizex,sizey:word;

 function upp(s:string):string;
 var b:byte;
 begin
  for b:=1 to length(s) do s[b]:=upcase(s[b]);
  upp:=s;
 end;

 procedure quit(s:string);
 begin
  writeln(s);
  halt;
 end;

 procedure checkfile(var f:text;s:string;b:boolean);
 begin
  assign(f,s);
  {$i-}
  if b then rewrite(f) else reset(f);
  if ioresult<>0 then if b then quit('Can''t create file '''+s+'''') else quit('Can''t open file '''+s+'''')
  {$I+}
 end;

 procedure readparam;
 var s:string;
     i,c:integer;
 begin
  if not paramcount in [2..3] then quit('Invalid count of parameters');
  if paramcount=3 then
  begin
   s:=paramstr(1);
   if s[1]<>'-' then quit('Bad parameter : '''+s+'''');
   s:=copy(s,2,255);
   val(s,i,c);
   if c<>0 then quit('Bad format of parameter : '''+s+'''');
   collumns:=i;
   checkfile(fin,paramstr(2),false);
   checkfile(fout,paramstr(3),true);
  end
  else
  begin
   collumns:=80;
   checkfile(fin,paramstr(1),false);
   checkfile(fout,paramstr(2),true);
  end;
 end;

 function returnwrap(p:pchar;ll,l:integer):string;
 var pp:ppch absolute p;
     a:word;
     wsc,wscline,lines:word;
     s:string;
 begin
  a:=0;
  wsc:=0;
  wscline:=0;
  lines:=1;
  s:='';
  repeat
   if pp^[a]=' ' then
   begin
    if wscline+wsc>ll then
    begin
     if lines=l then
     begin
      returnwrap:=s;
      exit;
     end;
     wscline:=wsc;
     inc(lines);
     s:='';
    end
    else inc(wscline,wsc);
    wsc:=0;
    s:=s+' ';
   end
   else
   begin
    s:=s+pp^[a];
    inc(wsc);
   end;
   inc(a);
  until pp^[a]=#0;
  if wscline+wsc>ll then inc(lines);
  returnwrap:=s;
 end;

 procedure processfile; {Prochazi, kontroluje soubor a hleda nejdelsi bunky}
 var s:string;          {Dela alokacni mapu bunek}
     sl:string;         {Nacita bunky do pameti}
     cx,cy:word;
     allowtext:boolean;
     w,ww:word;

  procedure error;
  begin
   quit('Error in line '''+sl+'''');
  end;

  function getnumber(s:string):integer;
  var i,c:integer;
  begin
   val(s,i,c);
   if c=0 then error;
   getnumber:=i;
  end;

  function getparam(var s:string):string;
  var b:byte;
  begin
   while s[1]=' ' do s:=copy(s,2,255);
   for b:=1 to length(s) do if s[b] in [' ','>'] then
   begin
    getparam:=copy(s,1,b-1);
    s:=copy(s,b,255);
    exit
   end;
   getparam:=s;
   s:='';
  end;

  function breakparam(var s:string):string;
  var b:byte;
  begin
   b:=pos('=',s);
   if b=0 then error;
   breakparam:=copy(s,b+1,255);
   s:=copy(s,1,b-1);
  end;

  function getpart(var s:string;var t:boolean):string;
  var b:byte;
  begin
   if s[1]='<' then
   begin
    b:=pos('>',s);
    if b in [0..2] then error;
    getpart:=upp(copy(s,2,b-2));
    s:=copy(s,b+1,255);
    t:=true;
   end
   else
   begin
    b:=pos('<',s);
    if b=0 then b:=255;
    getpart:=copy(s,1,b-1);
    s:=copy(s,b,255);
    t:=false;
   end;
  end;

  procedure addtext(var p:pchar;s:string);
  var n,nn:pchar;
      ss:word;
  begin
   if assigned(p) then
   begin
    s:=' '+s;
    ss:=strlen(p);
    getmem(n,ss+length(s)+1);
    strcopy(n,p);
    freemem(p,ss+1);
    nn:=strend(n);
    strpcopy(nn,s);
    p:=n;
   end
   else
   begin
    getmem(p,length(s)+1);
    strpcopy(p,s);
   end;
  end;

  function wordscan(p:pchar):integer;
  var pp:ppch absolute p;
      a:word;
      wsc,wscmax:word;
  begin
   a:=0;
   wsc:=0;
   wscmax:=0;
   repeat
    if pp^[a]=' ' then
    begin
     if wsc>wscmax then wscmax:=wsc;
     wsc:=0;
    end
    else inc(wsc);
    inc(a);
   until pp^[a]=#0;
   if wsc>wscmax then wscmax:=wsc;
   wordscan:=wscmax;
  end;

  function countwrap(p:pchar;ll:integer):integer;
  var pp:ppch absolute p;
      a:word;
      wsc,wscline,lines:word;
  begin
   a:=0;
   wsc:=0;
   wscline:=0;
   lines:=1;
   repeat
    if pp^[a]=' ' then
    begin
     if wscline+wsc>ll then
     begin
      wscline:=wsc;
      inc(lines);
     end
     else inc(wscline,wsc);
     wsc:=0;
    end
    else inc(wsc);
    inc(a);
   until pp^[a]=#0;
   if wscline+wsc>ll then inc(lines);
   countwrap:=lines;
  end;

  procedure processline(s:string);
  var ss,sss,sss2:string;
      t:boolean;
      p:pointer;
      rrs,ccs,r,c:byte;
      a:byte;
  begin
   while length(s)>0 do
   begin
    if s[1]=' ' then
    begin
     while s[1]=' ' do s:=copy(s,2,255);
     continue;
    end;
    ss:=getpart(s,t);
    if t then
    while length(ss)>0 do
    begin
     sss:=getparam(ss);
     if sss='TR' then
     begin
      inc(sizey);
      inc(cy);
      cx:=0;
      allowtext:=false;
     end
     else if (sss='TH') or (sss='TD') then
     begin
      inc(cx);
      if cx>sizex then sizex:=cx;
      while map[cx,cy].used do inc(cx);
      rrs:=0;
      ccs:=0;
      if sss='TH' then with map[cx,cy] do
      begin
       a:=1;
       va:=1;
      end;
      while length(ss)>0 do
      begin
       sss:=getparam(ss);
       sss2:=breakparam(sss);
       if sss='ROWSPAN=' then
       begin
        rrs:=getnumber(sss2);
        map[cx,cy].rs:=rrs;
       end
       else if sss='COLSPAN=' then
       begin
        ccs:=getnumber(sss2);
        map[cx,cy].cs:=ccs
       end
       else if sss='ALIGN' then
       begin
        if sss2='LEFT' then map[cx,cy].a:=0 else
        if sss2='RIGHT' then map[cx,cy].a:=2 else
        if sss2='CENTER' then map[cx,cy].a:=1 else error;
       end
       else if sss='VALIGN' then
       begin
        if sss2='TOP' then map[cx,cy].va:=0 else
        if sss2='BOTTOM' then map[cx,cy].a:=2 else
        if sss2='MIDDLE' then map[cx,cy].a:=1 else error;
       end
       else error;
      end;
      for r:=cy to cy+rrs do for c:=cx to cx+ccs do map[c,r].used:=true;
      allowtext:=true;
     end;
    end
    else
    begin
     if allowtext then with map[cx,cy] do
     begin
      addtext(text,ss);
      sizex:=strlen(text);
     end
     else error;
    end;
   end;
  end;

 begin
  fillchar(map,sizeof(map),0);
  sizex:=0;
  sizey:=0;
  cx:=0;
  cy:=0;
  allowtext:=false;
  reset(fin);
  while not eof(fin) do
  begin
   readln(fin,s);
   sl:=s;
   processline(s);
  end;
  fillchar(colwidths,sizeof(colwidths),0);
  fillchar(maxwidths,sizeof(maxwidths),0);
  fillchar(rowwidths,sizeof(rowwidths),0);
  for cy:=1 to sizey do for cx:=1 to sizex do with map[cx,cy] do
  begin
   smallx:=wordscan(text);
   if colwidths[cx]<smallx then colwidths[cx]:=smallx;
   if maxwidths[cx]<sizex then maxwidths[cx]:=sizex;
  end;
  w:=1;
  ww:=1;
  for cx:=1 to sizex do
  begin
   inc(w,colwidths[cx]+3);
   inc(ww,maxwidths[cx]+3);
  end;
  if ww<=collumns then for cx:=1 to sizex do colwidths[cx]:=maxwidths[cx];
  for cy:=1 to sizey do for cx:=1 to sizex do with map[cx,cy] do
  begin
   sizey:=countwrap(text,colwidths[cx]);
   if rowwidths[cy]<sizey then rowwidths[cy]:=sizey;
  end;
  if w>collumns then quit('Error: Table is too long to fit line.');
 end;

 procedure createtab;
 var a,aa,b,c:integer;
     cx,cy:word;
     s,ss:string;
 begin
  for cx:=1 to sizex do
  begin
   if cx=1 then s:='+';
   for a:=1 to colwidths[cx]+2 do s:=s+'-';
   s:=s+'+';
  end;
  writeln(fout,s);
  for cy:=1 to sizey do
  begin
   aa:=rowwidths[cy];
   for a:=1 to aa do
   begin
    s:='|';
    for cx:=1 to sizex do with map[cx,cy] do
    begin
     ss:='';
     if (va=0) and (a<=sizey) then ss:=returnwrap(text,colwidths[cx],a) else
     if va=1 then
     begin
      b:=(aa-sizey) div 2;
      if (a>b) and (a<=b+sizey) then ss:=returnwrap(text,colwidths[cx],a-b);
     end
     else if (va=2) and (a>=aa-sizey) then ss:=returnwrap(text,colwidths[cx],a-(aa-sizey));
     if a=0 then for c:=1 to colwidths[cx]-length(ss) do ss:=ss+' ';
     if a=1 then
     begin
      for c:=1 to (colwidths[cx]-length(ss)) div 2 do ss:=' '+ss;
      for c:=1 to (colwidths[cx]-length(ss)) div 2+(colwidths[cx]-length(ss)) mod 2 do ss:=ss+' ';
     end
     else if a=2 then for c:=1 to colwidths[cx]-length(ss) do ss:=' '+ss;
     s:=s+' '+ss+' |';
    end;
    writeln(fout,s);
   end;
   for cx:=1 to sizex do
   begin
    if cx=1 then s:='+';
    for a:=1 to colwidths[cx]+2 do s:=s+'-';
    s:=s+'+';
   end;
   writeln(fout,s);
  end;
 end;

begin
 readparam;
 processfile;
 createtab;
 close(fout);
end.