Program Tab;

Uses
   Crt;

Const
   BufLen = 1024;
   MaxWidthInCells = 10;
   MaxHeightInCells = 100;
   MaxCells = 100;

   LEFT = 0;
   CENTER = 1;
   RIGHT = 2;

   TOP = 0;
   MIDDLE = 1;
   BOTTOM = 2;

Type
   TBuf = Array[0..BufLen - 1] of Char;

Var
   N: Integer;

   InBuf: TBuf;
   InPtr: Word;
   FI: File;
   FO: Text;

   OptParam : Integer;

   Table: Array[1..MaxHeightInCells, 1..MaxWidthInCells] of record
      StrIndex: Word;
      Align: Byte;
      Valign: Byte;
      RowsPan, ColsPan: Word;
   End;
   ColsWidth: Array[1..MaxWidthInCells] of byte;

   Strs: Array[1..MaxCells] of String;
   NumStr: Word;

   Row: Integer;
   Ch: Char;

Function IntToStr(S: String): Integer;
Var
   Result, Code: Integer;
Begin
   Val(S, Result, Code);
   if Code <> 0 then begin
      Writeln('Blbe cislo');
      Halt;
   End;
   IntToStr := Result;
End;

Function GetChar: Char;
Var
   Count: Word;
Begin
   if InPtr >= BufLen then Begin
      InPtr := 0;
      BlockRead(FI, InBuf, BufLen, Count);
      if Count <> BufLen then InBuf[Count] := #255;
   end;
   GetChar := InBuf[InPtr];
   Inc(InPtr);
End;

Function Find(S: String): Boolean;
Var
   Idx: Integer;
Begin
   Find := False;
   For Idx := 1 to Length(S) do Begin
      Repeat
         Ch := UpCase(GetChar);
         if Ch = #255 then Exit;
      Until (Ch = S[Idx]);
   End;
   Find := True;
End;

Procedure AddCell(Row: Integer; S: String; _Align, _VAlign: Byte; _RowsPan, _ColsPan: Word);
Var
   Idx: Integer;
   I, J: Integer;
Begin
   Inc(NumStr);
   Strs[NumStr] := S;

   Idx := 1;
   While (Table[Row, Idx].StrIndex <> 0) do Inc(Idx);

   For J := 0 to _RowsPan - 1 do For I := 0 to _ColsPan - 1 do with Table[Row + J, Idx + I] do begin
      Align := _Align;
      VAlign := _Valign;
      RowsPan := _RowsPan - J;
      ColsPan := _ColsPan - I;
      StrIndex := NumStr;
   End;
End;

Procedure DoLine;
Var
   TH: Boolean;
   Attr, AttrPar: String;
   Align, VAlign: Byte;
   RowsPan, ColsPan: Word;
   S: String;
Begin
   if not Find('<') then Exit;
   Repeat
      if not Find('T') then Exit;
      Repeat
         Ch := UpCase(GetChar);
         if Ch = #255 then begin
            AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);
            Exit;
         End;
      Until (Ch in ['R', 'H', 'D']);
      if Ch = 'R' then begin
         Find('>');
{         AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);}
         Exit;
      End;
      TH := (Ch = 'H');
      Repeat
         Attr := '';
         AttrPar := '';
         Repeat
            Ch := UpCase(GetChar);
            if Ch = #255 then begin
               AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);
               Exit;
            End;
            if not (Ch in [' ', '=', '>']) then Attr := Attr + Ch;
         Until Ch in ['=', '>'];
         if Ch <> '>'  then begin
            Repeat
               Ch := UpCase(GetChar);
               if Ch = #255 then begin
                  AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);
                  Exit;
               End;
               if not (Ch in [' ', '>']) then AttrPar := AttrPar + Ch;
            Until Ch in [' ', '>'];
         end;
         if TH then begin
            Align := CENTER;
            VAlign := MIDDLE;
         end else begin
            Align := LEFT;
            VAlign := TOP;
         end;
         RowsPan := 1;
         ColsPan := 1;
         if Attr = 'ALIGN' then begin
            if AttrPar = 'LEFT' then Align := LEFT else
            if AttrPar = 'CENTER' then Align := CENTER else
            if AttrPar = 'RIGHT' then Align := RIGHT;
         end;
         if Attr = 'VALIGN' then begin
            if AttrPar = 'TOP' then VAlign := TOP else
            if AttrPar = 'MIDDLE' then VAlign := MIDDLE else
            if AttrPar = 'BOTTOM' then VAlign := BOTTOM;
         end;
         if Attr = 'ROWSPAN' then RowsPan := IntToStr(AttrPar);
         if Attr = 'COLSPAN' then ColsPan := IntToStr(AttrPar);
      Until Ch = '>';
      S := '';
      Repeat
         Ch := GetChar;
         if Ch = #255 then begin
            AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);
            Exit;
         End;
         if not (Ch in ['<', #13, #10]) then S := S + Ch;
      Until Ch = '<';

      AddCell(Row, S, Align, VAlign, RowsPan, ColsPan);
   Until False;
End;

Procedure CutStrs;
Var
   Idx, J: Word;
   Ch, LastCh: Char;
   S: String;
Begin
   LastCh := #0;
   For Idx := 1 to NumStr do begin
      J := 1;
      S := '';
      While (J <= Length(Strs[Idx])) do begin
         Ch := Strs[Idx, J];
         if not (Ch in [' ', '&']) then S := S + Ch else
         if (Ch = ' ') and (LastCh <> ' ') then S := S + ' ' else
         if Ch = '&' then begin
            Inc(J);
            Case UpCase(Strs[Idx, J]) of
               'L': S := S + '<';
               'G': S := S + '>';
               'A': Begin
                  S := S + '&';
                  Inc(J);
               End;
            End;
            Inc(J);
         End;
         LastCh := S[Length(S)];
         Inc(J);
      End;
      J := Length(S);
      While (S[J] = ' ') do begin
         Dec(S[0]);
         Dec(J);
      End;
      Strs[Idx] := S;
   End;
End;

Procedure MakeTable;
Var
   Idx, J, K: Word;
   Width: Word;
   S: String;
   Cols: Word;
Begin
   Cols := 0;
   Write(FO, '+');
   For Idx := 1 to N-2 do Write(FO, '-');
   Dec(N);
   Dec(Row);
   Writeln(FO, '+');
   For Idx := 1 To Row do begin
      J := 1;
      While (Table[Idx, J].StrIndex <> 0) do begin
         Width := Length(Strs[Table[Idx, J].StrIndex]) + 3;
         if Width > ColsWidth[J] then ColsWidth[J] := Width;
         Inc(J);
      End;
      if J - 1 >= Cols then Cols := J - 1;
   End;
   Width := 0;
   For Idx := 1 to Cols do Inc(Width, ColsWidth[Idx]);
   if Width < N then Inc(ColsWidth[Cols], N - Width) else
      if Width > N then Dec(ColsWidth[Cols], Width - N);

   For Idx := 1 to Row do begin
      J := 1;
      While (Table[Idx, J].StrIndex <> 0) do begin
         S := ' ' + Strs[Table[Idx, J].StrIndex] + ' ';
         Width := 0;
         For K := 0 to Table[Idx, J].ColsPan - 1 do Inc(Width, ColsWidth[J + K]);
{         if Length(S) >= Width - 1 then begin
            Writeln('Error: Table is too long to fit line');
            Halt;
         End;}

         While Length(S) < Width - 1 do begin
            case Table[Idx, J].Align of
               LEFT: S := S + ' ';
               CENTER: begin
                  S := ' ' + S + ' ';
                  if Length(S) > Width - 1 then Dec(S[0]);
               end;
               RIGHT: S := ' '+ S;
            end;
         end;
         Write(FO, '|', S);
         Inc(J, Table[Idx, J].ColsPan);
      End;
      Writeln(FO, '|');
      For J := 1 to Cols Do Begin
         if Idx = Row then Write(FO, '+') else
         if J = 1 then Write(FO, '|') else Write(FO, '+');
         For K := 1 to ColsWidth[J] - 1 do Write(FO, '-');
      End;
      if Idx = Row then Writeln(FO, '+') else Writeln(FO, '|');
   End;
   Inc(N);
End;

Procedure Main;
Begin
   NumStr := 0;
   Row := 1;
   FillChar(Table, SizeOf(Table), 0);
   FillChar(ColsWidth, SizeOf(ColsWidth), 0);
   if not Find('<TR>') then Exit;
   Repeat
      DoLine;
      Inc(Row);
   Until (Ch = #255);
   CutStrs;
   MakeTable;
End;

Begin
   if Copy(ParamStr(1), 1, 1) = '-' then begin
      N := IntToStr(Copy(ParamStr(1), 2, 255));
      OptParam := 1;
   end else begin
      N := 80;
      OptParam := 0;
   end;

   Assign(FI, ParamStr(1 + OptParam));
   Reset(FI, 1);
   Assign(FO,ParamStr(2 + OptParam));
   ReWrite(FO);

   InPtr := 65535;

   ClrScr;
   Main;
   Close(FI);
   Close(FO);
End.