Code coverage for parser.li

///////////////////////////////////////////////////////////////////////////////
//                             Lisaac Compiler                               //
//                                                                           //
//                   LSIIT - ULP - CNRS - INRIA - FRANCE                     //
//                                                                           //
//   This program is free software: you can redistribute it and/or modify    //
//   it under the terms of the GNU General Public License as published by    //
//   the Free Software Foundation, either version 3 of the License, or       //
//   (at your option) any later version.                                     //
//                                                                           //
//   This program is distributed in the hope that it will be useful,         //
//   but WITHOUT ANY WARRANTY; without even the implied warranty of          //
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
//   GNU General Public License for more details.                            //
//                                                                           //
//   You should have received a copy of the GNU General Public License       //
//   along with this program.  If not, see <http://www.gnu.org/licenses/>.   //
//                                                                           //
//                     http://isaacproject.u-strasbg.fr/                     //
///////////////////////////////////////////////////////////////////////////////
Section Header

  + name      := PARSER;

  - copyright := "2003-2007 Benoit Sonntag";

  - author    := "Sonntag Benoit (bsonntag@loria.fr)";
  - comment   := "Parser for Lisaac language.";

  // You can to get with
  // `grep "//++" parser.li' : Current grammar.
  // `grep "//--" parser.li' : Syntax rules.
  // `grep "////" parser.li' : lip grammar.
Section Inherit

  - parent_any:ANY := ANY;

Section Public

  //
  // Shorter Section.
  //

  - is_active_short:BOOLEAN;

  - short_dico:HASHED_DICTIONARY(LINKED_LIST(STRING_CONSTANT),STRING_CONSTANT) :=
  HASHED_DICTIONARY(LINKED_LIST(STRING_CONSTANT),STRING_CONSTANT).create;

  - short_derive:INTEGER;

  - token:STRING := STRING.create 100;

  - short key:STRING_CONSTANT token beg:INTEGER to end:INTEGER <-
  ( + pos:INTEGER;
    + add_text:ABSTRACT_STRING;
    + fmt:LINKED_LIST(STRING_CONSTANT);

    (is_shorter).if {
      (is_active_short).if {
	//
	// SHORTER
	//
	(short_dico.fast_has key).if {
	  // Extract token.
	  token.clear;
	  pos := beg + short_derive;
	  beg.to (end-1) do { j:INTEGER;
	    token.add_last (source.item j);
	    output_code.remove pos;
	  };
	  short_derive := short_derive - token.count;
	  // Insert format.
	  fmt := short_dico.at key;
	  fmt.lower.to (fmt.upper) do { j:INTEGER;
	    (fmt.item j = NULL).if {
	      add_text := token;
	    } else {
	      add_text := fmt.item j;
	    };
	    output_code.insert_string add_text to pos;
	    pos := pos + add_text.count;
	    short_derive := short_derive + add_text.count;
	  };
	};
      };
    };
  );

  - short_remove begin:INTEGER to end:INTEGER <-
  (
    output_code.remove_between
    (begin + short_derive) to (end + short_derive);
    short_derive := short_derive - (end - begin + 1);
  );

  - short_local:HASHED_SET(STRING_CONSTANT);

Section Private

  //
  // Source information.
  //

  - object   : PROTOTYPE;

  - source   : STRING;

  - position : INTEGER;

  - pos_cur  : INTEGER;
  - pos_line : INTEGER;
  - pos_col  : INTEGER;

  - begin_position:INTEGER; // begin item position

  - current_position:POSITION <-
  ( + result:POSITION;
    ? {pos_cur <= position};

    {pos_cur = position}.until_do {
      (source.item pos_cur = '\n').if {
	pos_col := 0;
	pos_line := pos_line + 1;
      } else {
	pos_col := pos_col + 1;
      };
      pos_cur := pos_cur + 1;
    };
    (pos_line > 32767).if {
      result := POSITION.create object line 32767 column pos_col;
      syntax_error (result,"Line counter overflow.");
    };
    (pos_col > 255).if {
      result := POSITION.create object line pos_line column 255;
      syntax_error (result,"Column counter overflow (line too long).");
    };
    POSITION.create object line pos_line column pos_col
  );

  //
  // AMBIGU Manager.
  //

  - old_position:INTEGER;
  - old_pos_cur :INTEGER;
  - old_pos_line:INTEGER;
  - old_pos_col :INTEGER;
  //
  - old_short_derive:INTEGER;

  - save_context <-
  (
    old_position := position;
    old_pos_cur  := pos_cur;
    old_pos_line := pos_line;
    old_pos_col  := pos_col;
    //
    old_short_derive := short_derive;
  );

  - restore_context <-
  ( + beg:INTEGER;

    (is_shorter).if {
      token.clear;
      beg := old_position + old_short_derive;
      output_code.remove_between beg to (position+short_derive-1);
      (old_position).to (position-1) do { j:INTEGER;
	token.add_last (source.item j);
      };
      output_code.insert_string token to beg;
      short_derive := old_short_derive;
    };

    position := old_position;
    pos_cur  := old_pos_cur;
    pos_line := old_pos_line;
    pos_col  := old_pos_col;
  );

  //
  // Syntax parser.
  //

  - last_character:CHARACTER <-
  ( + result:CHARACTER;
    (position > source.upper).if {
      result := 0.to_character;
      } else {
      result := source.item position;
    };
    result
  );

  - last_integer : INTEGER_64;
  - last_real    : STRING_CONSTANT;
  - last_string  : STRING_CONSTANT;
  - is_parameter_type:BOOLEAN;

  - last_comment_extern:STRING_CONSTANT;
  - last_comment_slot  :STRING_CONSTANT;
  - skip_comment:BOOLEAN;

  - put_new_line_comment str:STRING with cmt:STRING_CONSTANT <-
  ( + lst:LINKED_LIST(STRING_CONSTANT);
    + idx,idx_beg:INTEGER;
    lst := PARSER.short_dico.fast_reference_at cmt;
    (lst != NULL).if {
      {(idx := str.index_of '\n' since (idx+1)) < str.upper}.while_do {
        idx_beg := idx;
        idx := idx + 1;
        {
          (idx <= str.upper)   
          {str.item idx <= ' ' }   
          {str.item idx != '\n'}
        }.while_do {
          idx := idx + 1;
        };
        (str.item idx = '\n').if {
          str.replace_substring (lst.first) from idx_beg to (idx-1);
          idx := idx_beg + (lst.first.count)-1;
        };
      };
    };
  );

  - read_space:BOOLEAN <-
  ( + posold,pos,pos2:INTEGER;
    + level_comment:INTEGER;
    + stat:INTEGER;


    pos := position;
    posold := -1;
    (is_shorter2).if {
      string_tmp3.clear;
      string_tmp4.clear;
    };
    {posold = position}.until_do {
      posold := position;

      // Skip spaces :
      {(last_character = 0.to_character) || {last_character > ' '}}.until_do {
        ((is_shorter2) || {is_shorter}).if {
          (last_character = '\n').if {
            (stat)
            .when 0 then { stat := 1; }
            .when 1 then { stat := 2; }
            .when 2 then {            };
          };
        };
	position := position + 1;
      };

      (position < source.upper).if {
	// Skip C++ comment style :
	((last_character = '/')    {source.item (position + 1) = '/'}).if {
	  position := position + 2;
          pos2 := position;
	  {
	    (last_character = 0.to_character) ||
	    {last_character = '\n'}
          }.until_do {
            (is_shorter2).if {
              (stat)
              .when 0 or 1 then {
                string_tmp3.add_last last_character;
              }
              .when 2 then {
                string_tmp4.add_last last_character;
              };
            };
	    position := position + 1;
          };
          (is_shorter2).if {
            (stat)
            .when 0 or 1 then { string_tmp3.add_last '\n'; }
            .when 2      then { string_tmp4.add_last '\n'; };
          };
          (is_shorter).if {
            // BSBS: A revoir ...
            ((pos2-2+short_derive).in_range (output_code.lower) to (output_code.upper)).if {
              output_code.remove_between (pos2-2+short_derive) to (pos2-1+short_derive);
              short_derive := short_derive - 2;
            };
            // Bug ?
            ( + nb,p:INTEGER;
              p := pos2 - 3;
              {(p >= source.lower)    {source.item p <= ' '}}.while_do {
                (source.item p = '\n').if {
                  nb := nb + 1;
                };
                p := p - 1;
              };
              (nb > 1).if {
                stat := 2;
              };
            );
            (stat)
            .when 0 or 1 then {
              short (ALIAS_STR.short_comment_slot_line) token pos2 to position;
            }
            .when 2 then {
              short (ALIAS_STR.short_comment_line) token pos2 to position;
            };
          };
          position := position + 1;
	};
      };
      (position < source.upper).if {
	// Skip C comment style :
	pos2 := position;
	((last_character = '/')    {source.item (position+1) = '*'}).if {
	  position := position + 2;
	  level_comment := 1;
	  {
	    (last_character = 0.to_character) || {level_comment = 0}
	  }.until_do {
	    ((last_character = '/')    {source.item (position+1) = '*'}).if {
	      level_comment := level_comment + 1;
	      position := position + 2;
	    }.elseif {
	      (last_character = '*')    {source.item (position+1) = '/'}
	    } then {
	      level_comment := level_comment - 1;
	      position := position + 2;
	    } else {
	      position := position+1;
	    };
	  };
	  (level_comment != 0).if {
	    position := pos2;
	    syntax_error (current_position,"End of comment not found !");
	  };
	  //position := position+2;
	  short (ALIAS_STR.short_comment) token pos2 to position;
	};
      };
    };
    ((is_shorter2)    {! skip_comment}).if {
      (string_tmp3.is_empty).if {
        last_comment_slot := NULL;
      } else {
        put_new_line_comment string_tmp3 with (ALIAS_STR.short_comment_new_line_slot);
        last_comment_slot := ALIAS_STR.get string_tmp3;
      };
      (string_tmp4.is_empty).if_false {
        put_new_line_comment string_tmp4 with (ALIAS_STR.short_comment_new_line_extern);
        last_comment_extern := ALIAS_STR.get string_tmp4;
      };
    };
    // FALSE : Last character.
    begin_position := position;
    ((position != pos) | (last_character != 0.to_character))
  );

  - read_symbol st:STRING_CONSTANT :BOOLEAN <-
  ( + posold,j:INTEGER;
    + result:BOOLEAN;
    // On passe les espaces :
    (! read_space).if {
      result := FALSE;
    } else {
      posold := position;
      j := st.lower;
      {(last_character = 0.to_character) ||
      {(j > st.upper) || {last_character != st.item j}}}.until_do {
	j := j+1;
	position := position+1;
      };
      (j > st.upper).if {
        result := TRUE;
        last_string := st;
      } else {
	position := posold;
	result := FALSE;
      };
    };
    result
  );

  - read_character ch:CHARACTER :BOOLEAN <-
  ( + result:BOOLEAN;
    // On passe les espaces :
    (! read_space).if {
      result := FALSE;
    } else {
      (last_character = ch).if {
	position := position + 1;
	result := TRUE;
      };
    };
    result
  );

  //-- affect         -> ":=" | "<-" | "?="
  - read_affect:BOOLEAN <-
  (
    (read_symbol (ALIAS_STR.symbol_affect_immediate)) ||
    {read_symbol (ALIAS_STR.symbol_affect_cast)} ||
    {read_symbol (ALIAS_STR.symbol_affect_code)}
  );

  //-- style          -> '-' | '+'
  - read_style:CHARACTER <-
  ( + result:CHARACTER;
    read_character '-'.if {
      result := '-';
      short (ALIAS_STR.short_slot_style) token (position-1) to position;
    }.elseif {read_character '+'} then {
      result := '+';
      short (ALIAS_STR.short_slot_style) token (position-1) to position;
    } else {
      result := ' ';
    };
    result
  );

  //-- identifier     -> 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
  - read_identifier:BOOLEAN <-
  ( + result:BOOLEAN;
    + posold,idx:INTEGER;

    // On passe les espaces :
    ((! read_space) || {! last_character.is_lower}).if {
      result := FALSE;
    } else {
      posold := position;
      string_tmp.clear;
      {
	(last_character = 0.to_character) ||
	{
	  (! last_character.is_lower)   
	  {! last_character.is_digit}   
	  {last_character != '_'}
	}
      }.until_do {
	string_tmp.add_last last_character;
	position := position+1;
      };
      (! string_tmp.is_empty).if {
	idx := string_tmp.first_substring_index "__";
	(idx != 0).if {
	  position := posold+idx;
	  syntax_error (current_position,"Identifier is incorrect.");
	};
	last_string := ALIAS_STR.get string_tmp;
	result := TRUE;
      };
    };
    result
  );

  - read_word st:STRING_CONSTANT :BOOLEAN <-
  ( + posold,idx:INTEGER;
    + result:BOOLEAN;
    // On passe les espaces :
    (! read_space).if {
      result := FALSE;
    } else {
      posold := position;
      idx := st.lower;
      {(idx > st.upper) || {last_character != st.item idx}}.until_do {
	position := position+1;
	idx := idx+1;
      };
      (idx>st.upper).if {
	last_string := st;
	result := TRUE;
      } else {
	position := posold;
      };
    };
    result
  );

  - read_this_keyword st:STRING_CONSTANT :BOOLEAN <-
  ( + result:BOOLEAN;

    result := read_word st;
    (is_shorter).if {
      (result).if {
	(st = ALIAS_STR.keyword_section).if {
	  short (ALIAS_STR.short_keyword_section) token
	  (position-last_string.count) to position;
	} else {
	  short (ALIAS_STR.short_keyword) token
	  (position-last_string.count) to position;
	};
      };
    };
    result
  );

  //-- keyword        -> 'A'-'Z' 'a'-'z' {'a'-'z' | '0'-'9' | '_'}
  - read_keyword:BOOLEAN <-
  ( + result:BOOLEAN;
    // On passe les espaces :
    ((! read_space) || {! last_character.is_upper}).if {
      result := FALSE;
    } else {
      string_tmp.clear;
      string_tmp.add_last last_character;
      position := position + 1;
      (last_character.is_lower).if {
	string_tmp.add_last last_character;
	position := position + 1;
	{(last_character != 0.to_character)   
	  {(last_character.is_lower) ||
	    {last_character.is_digit} ||
	{last_character = '_'}}}.while_do {
	  string_tmp.add_last last_character;
	  position := position+1;
	};
	last_string := ALIAS_STR.get string_tmp;
	result := TRUE;
	short (ALIAS_STR.short_keyword) token
	(position-last_string.count) to position;
      } else {
	position := position - 1;
	result := FALSE;
      };
    };
    result
  );

  //-- cap_identifier -> 'A'-'Z' {'A'-'Z' | '0'-'9' | '_'}
  - read_cap_identifier:BOOLEAN <-
  ( + posold,idx:INTEGER;
    + result:BOOLEAN;
    + car:CHARACTER;
    // On passe les espaces :
    ((! read_space) || {! last_character.is_upper}).if {
      result := FALSE;
    } else {
      posold := position;
      string_tmp.clear;
      string_tmp.add_last last_character;
      position := position + 1;
      is_parameter_type := TRUE;
      {
	(last_character = 0.to_character) ||
	{
	  (! last_character.is_upper)   
	  {! last_character.is_digit}   
	  {last_character != '_'}
	}
      }.until_do {
        car := last_character;
        is_parameter_type := is_parameter_type    {car.is_digit};
	string_tmp.add_last car;
        position := position+1;
      };
      idx := string_tmp.first_substring_index "__";
      (idx != 0).if {
        position := posold + idx;
        syntax_error (current_position,"Identifier is incorrect.");
      };
      last_string := ALIAS_STR.get string_tmp;
      result := TRUE;
    };
    result
  );

  //-- integer        -> number
  //-- number         -> {'0'-'9'} ['d']
  //--                 | '0'-'9' {'0'-'9' | 'A'-'F' | 'a'-'f'} 'h'
  //--                 | {'0'-'7'} 'o'
  //--                 | {'0' | '1'} 'b'
  - read_integer:BOOLEAN <-
  ( + result:BOOLEAN;
    + pos_old:INTEGER;

    // On passe les espaces :
    ((read_space)    {last_character.is_digit}).if {
      result := TRUE;
      string_tmp.clear;
      string_tmp.add_last last_character;
      pos_old := position;
      position := position + 1;
      {(last_character.is_hexadecimal_digit) || {last_character = '_'}}.while_do {
	(last_character != '_').if {
	  string_tmp.add_last last_character;
	};
	position := position + 1;
      };
      (last_character = 'h').if {
	last_integer := string_tmp.to_hexadecimal;
	position := position+1;
      } else {
	(string_tmp.last > '9').if {
	  string_tmp.remove_last 1;
	  position := position - 1;
	};
	(last_character='o').if {
	  (! string_tmp.is_octal).if {
	    syntax_error (current_position,"Incorrect octal number.");
	  };
	  last_integer := string_tmp.to_octal;
	  position := position+1;
	}.elseif {last_character='b'} then {
	  (! string_tmp.is_bit).if {
	    syntax_error (current_position,"Incorrect binary number.");
	  };
	  last_integer := string_tmp.to_binary;
	  position := position+1;
	} else {
	  (last_character='d').if {
	    position := position+1;
	  };
	  (! string_tmp.is_integer_64).if {
	    syntax_error (current_position,"Incorrect decimal number.");
	  };
	  last_integer := string_tmp.to_integer_64;
	};
      };
    };
    (result).if {
      short (ALIAS_STR.short_integer) token pos_old to position;
    };
    result
  );

  - read_real:BOOLEAN <-
  //-- real           -> '0'-'9' {'0'-'9'_} [ '.' {'0'-'9'} ] [ 'E' ['+'|'-'] '0'-'9' {'0'-'9'}
  ( + result:BOOLEAN;
    + pos_old:INTEGER;

    // On passe les espaces :
    ((read_space)    {last_character.is_digit}).if {
      string_tmp.clear;
      string_tmp.add_last last_character;
      pos_old := position;
      position := position + 1;
      {(last_character.is_digit) || {last_character = '_'}}.while_do {
	(last_character != '_').if {
	  string_tmp.add_last last_character;
	};
	position := position + 1;
      };
      (last_character = '.').if {
	string_tmp.add_last '.';
	position := position + 1;
	(last_character.is_digit).if {
	  result := TRUE;
	  string_tmp.add_last last_character;
	  position := position + 1;
	  {last_character.is_digit}.while_do {
	    string_tmp.add_last last_character;
	    position := position + 1;
	  };
	};
	(last_character = 'E').if {
	  result := TRUE;
	  string_tmp.add_last 'E';
	  position := position + 1;
	  ((last_character = '+') || {last_character = '-'}).if {
	    string_tmp.add_last last_character;
	    position := position + 1;
	  };
	  (last_character.is_digit).if {
	    string_tmp.add_last last_character;
	    position := position + 1;
	    {last_character.is_digit}.while_do {
	      string_tmp.add_last last_character;
	      position := position + 1;
	    };
	  } else {
	    syntax_error (current_position,"Incorrect real number.");
	  };
	};
      };
      (result).if {
	last_real := ALIAS_STR.get string_tmp;
      } else {
	position := pos_old;
      };
    };
    (result).if {
      short (ALIAS_STR.short_integer) token pos_old to position;
    };
    result
  );

  //-- escape         -> '\\' separator {separator} '\\'
  //--                 | '\\' escape_seq
  //--                 | '\\' integer '\\'
  //-- escape_seq     -> 'a' | 'b'  | 'f' | 'n'  | 'r'  | 't'
  //--                 | 'v' | '\\' | '?' | '\'' | '\"' | '0'
  - read_escape_character <-
  ( + nothing:BOOLEAN;
    + val:INTEGER;
    last_character.is_separator.if {
      position := position+1;
      {
	(last_character = 0.to_character) ||
	{! last_character.is_separator}
      }.until_do {
	position := position+1;
      };
      (last_character='\\').if {
	string_tmp.remove_last 1;
	position := position+1;
      }.elseif {last_character != 0.to_character} then {
	syntax_error (current_position,"Unknown escape sequence.");
      };
    }.elseif {last_character != 0.to_character} then {
      ( (last_character = 'a')  ||
	{last_character = 'b'}  ||
	{last_character = 'f'}  ||
	{last_character = 'n'}  ||
	{last_character = 'r'}  ||
	{last_character = 't'}  ||
	{last_character = 'v'}  ||
	{last_character = '\\'} ||
	{last_character = '?'}  ||
	{last_character = '\''} ||
	{last_character = '\"'}
      ).if {
	string_tmp.add_last last_character;
	position := position+1;
      }.elseif {last_character.in_range '0' to '9'} then {
	(
          (last_character='0')   
	  {position<source.upper}   
          {! source.item(position+1).is_hexadecimal_digit}
        ).if {
	  string_tmp.add_last last_character;
	  position := position+1;
	} else {
	  string_tmp2.copy string_tmp;
	  nothing := read_integer; // result is Always TRUE.
	  string_tmp.copy string_tmp2;
	  (last_integer > 255).if {
	    syntax_error (current_position,
	    "Invalid range character number [0,255].");
	  };
	  val := last_integer.to_integer;
	  string_tmp.add_last ((val / 64).decimal_digit);
	  string_tmp.add_last (((val % 64) / 8).decimal_digit);
	  string_tmp.add_last ((val % 8).decimal_digit);
	  (last_character='\\').if {
	    position := position + 1;
	  } else {
	    syntax_error (current_position,"Character '\' is needed.");
	  };
	};
      } else {
	syntax_error (current_position,"Unknown escape sequence.");
      };
    };
  );

  //-- character      -> '\'' ascii '\''
  - read_characters:BOOLEAN <-
  ( + result:BOOLEAN;
    + old_pos:INTEGER;
    + count:INTEGER;
    // On passe les espaces :
    ((read_space)    {last_character='\''}).if {
      old_pos := position;
      position := position+1;
      string_tmp.clear;
      {
        (last_character=0.to_character) ||
	{last_character='\n'} ||
        {last_character='\''}
      }.until_do {
	string_tmp.add_last last_character;
	(last_character='\\').if {
	  position := position+1;
          read_escape_character;
          count := count + 1;
	} else {
          position := position+1;
          count := count + 1;
	};
      };
      (last_character='\'').if {
	position := position+1;
	last_string := ALIAS_STR.get string_tmp;
	(count != 1).if {
	  position := begin_position;
	  syntax_error (current_position,"Character constant too long.");
	};
	result := TRUE;
	short (ALIAS_STR.short_character) token old_pos to position;
      } else {
	position := begin_position;
	syntax_error (current_position,"Unterminated character constant.");
      };
    };
    result
  );

  //-- string         -> '\"' string_char '\"'
  //-- string_char    -> escape
  //--                 | ascii
  - read_string:BOOLEAN <-
  ( + result:BOOLEAN;
    + old_pos:INTEGER;
    // On passe les espaces :
    ((read_space)    {last_character='\"'}).if {
      old_pos := position;
      position := position+1;
      string_tmp.clear;
      {
        (last_character=0.to_character) ||
	{last_character='\n'} ||
        {last_character='\"'}
      }.until_do {
	string_tmp.add_last last_character;
	(last_character='\\').if {
	  position := position+1;
	  read_escape_character;
	} else {
	  position := position+1;
	};
      };
      (last_character='\"').if {
	position := position+1;
	last_string := ALIAS_STR.get string_tmp;
	result := TRUE;
	short (ALIAS_STR.short_string) token old_pos to position;
      } else {
	position := begin_position;
	syntax_error (current_position,"Unterminated string constant.");
      };
    };
    result
  );

  //-- external       -> '`' ascii_c_code '`'
  - read_external:BOOLEAN <-
  ( + result:BOOLEAN;
    + pos_old:INTEGER;
    // On passe les espaces :
    ((! read_space) || {last_character != '`'}).if {
      result := FALSE;
    } else {
      pos_old:=position;
      position := position+1;
      string_tmp.clear;
      {(last_character = 0.to_character) | (last_character='`')}.until_do {
	string_tmp.add_last last_character;
	(last_character='\\').if {
	  position := position+1;
	  string_tmp.add_last last_character;
	  (last_character != 0.to_character).if {
	    position := position+1;
	  };
	} else {
	  position := position+1;
	};
      };
      (last_character != 0.to_character).if {
	position := position+1;
	last_string := ALIAS_STR.get string_tmp;
	result := TRUE;
	short (ALIAS_STR.short_external) token pos_old to position;
      } else {
	result := FALSE;
      };
    };
    result
  );

  //-- operator       -> '!' | '@' | '#' | '$' | '%' | '^' | ' ' | '<' | '|'
  //--                 | '*' | '-' | '+' | '=' | '~' | '/' | '?' | '\' | '>'
  - read_operator:BOOLEAN <-
  ( + result:BOOLEAN;
    + old_pos:INTEGER;
    // On passe les espaces :
    (read_space).if {
    };
    old_pos:=position;
    string_tmp.clear;
    {(last_character = 0.to_character) ||
    {! "!@#$%^ <|*-+=~/?\\>".has last_character}}.until_do {
      string_tmp.add_last last_character;
      position := position+1;
    };
    (! string_tmp.is_empty).if {
      last_string := ALIAS_STR.get string_tmp;
      (
	(last_string = ALIAS_STR.symbol_affect_immediate) ||
	{last_string = ALIAS_STR.symbol_affect_code} ||
	{last_string = ALIAS_STR.symbol_affect_cast}
      ).if {
	syntax_error (current_position,"Incorrect operator.");
      };
      short (ALIAS_STR.short_operator) token old_pos to position;

      ((last_string = ALIAS_STR.symbol_equal) || {last_string = ALIAS_STR.symbol_not_equal}).if {
        count_equal_parse := count_equal_parse + 1;
      };

      result := TRUE;
    };
    result
  );

  //
  // Variable   function Global.
  //

  - last_slot:ITM_SLOT;

  - last_group:ITM_LIST;

  - last_section:SECTION_;

  //
  // PARSER
  //

  //++ PROGRAM      -> { "Section" (section|TYPE_LIST) { SLOT } } [CONTRACT ';']
  - read_program:BOOLEAN <-
  ( + result:BOOLEAN;
    + pos_sec,old_derive:INTEGER;
    + t:FAST_ARRAY(ITM_TYPE_MONO);

    result := TRUE;

    pos_sec := position;
    old_derive := short_derive;

    read_space;

    (is_shorter).if {
      output_code.remove_between (source.lower+old_derive) to (position-1+short_derive);
      short_derive := short_derive - ((position+short_derive) - (source.lower+old_derive));
    };
    pos_sec := position;
    old_derive := short_derive;
    last_comment_extern := NULL;
    //
    // Read Section Header.
    //
    (read_this_keyword (ALIAS_STR.keyword_section)).if_false {
      syntax_error (current_position,"`Section' is needed.");
    };
    (read_this_keyword (ALIAS_STR.section_header)).if_false {
      syntax_error (current_position,"Section `Header' is needed.");
    };
    (read_slot_header TRUE).if_false {
      syntax_error (current_position,"Slot `name' not found.");
    };
    {read_slot_header FALSE}.while_do {
    }; // loop

    (is_shorter2).if {
      object.set_comment_header last_comment_extern;
    };

    //
    // Read Section Other.
    //
    {read_this_keyword (ALIAS_STR.keyword_section)}.while_do {
      last_comment_extern := NULL;
      (read_keyword).if {
	// Public, Private, ...
	(ALIAS_STR.is_section last_string).if_false {
	  syntax_error (current_position,"Incorrect type section.");
	};
	last_section := SECTION_.get_name last_string;
	(last_section.is_mapping).if {
          object.set_mapping;
        }.elseif {last_section.is_external} then {
          object.set_external;
	}.elseif {
	  (last_section.is_inherit_or_insert)   
	  {object.last_slot != NULL}   
	  {! object.last_slot.id_section.is_inherit_or_insert}
	} then {
	  syntax_error (current_position,
	  "`Section Inherit/Insert' must to be first section.");
	}.elseif {
	  (last_section.is_inherit)   
	  {object.type_style = ALIAS_STR.keyword_expanded}   
	  {object.name != ALIAS_STR.prototype_true }   
	  {object.name != ALIAS_STR.prototype_false}
	} then {
	  warning_error (current_position,
	  "`Section Inherit' is not possible with Expanded object (Use `Section Insert').");
	};
      } else {
	// TYPE_LIST.
	t := read_type_list TRUE;
	(t = NULL).if {
	  syntax_error (current_position,"Incorrect type section.");
	};
	last_section := SECTION_.get_type_list t;
      };
      {read_slot}.while_do {
      }; // loop

      (is_shorter).if {
	(
	  (! is_short_private)   
	  {last_section.is_private}
	).if {
	  output_code.remove_between
	  (pos_sec + old_derive) to (position + short_derive - 1);
	  short_derive := old_derive - (position - pos_sec);
	};

	pos_sec:=position;
	old_derive:=short_derive;
      };

    }; // loop
    (read_invariant).if {
      warning_error (current_position,"Invariant: Sorry, Not yet implemented.");
    };

    // End of file :
    result := result | read_space;
    (last_character != 0.to_character).if {
      syntax_error (current_position,"Incorrect symbol.");
    };
    result
  );  // read_program

  //++ SLOT         -> style TYPE_SLOT [':' (TYPE|'('TYPE_LIST')') ][ affect DEF_SLOT ]';'
  - read_slot:BOOLEAN <-
  ( + result:BOOLEAN;
    + t:ITM_TYPE;
    + lt:FAST_ARRAY(ITM_TYPE_MONO);
    + style:CHARACTER;
    + affect:CHARACTER;
    + old_pos,old_derive:INTEGER;
    + s:ITM_SLOT;

    style  := read_style;
    (style != ' ').if {
      //
      // Classic slot.
      //
      result := TRUE;
      //
      last_slot := read_type_slot;
      (last_slot = NULL).if {
	syntax_error (current_position,"Incorrect slot declaration.");
      };

      last_slot.set_style style;

      (read_affect).if {
	affect := last_string.first;
      } else {
	affect := ' ';
      };

      // ':' (TYPE|'('TYPE_LIST')'
      ((affect = ' ')    {read_character ':'}).if {
	(read_character '(').if {
	  lt := read_type_list FALSE;
	  (lt = NULL).if {
	    syntax_error (current_position,"Incorrect result type.");
	  };
	  (read_character ')').if_false {
	    warning_error (current_position,"Added ')' is needed.");
	  };
	  t := ITM_TYPE_MULTI.get lt;
	} else {
	  t := read_type FALSE;
	  (t = NULL).if {
	    syntax_error (current_position,"Incorrect result type.");
	  };
	};

	(read_affect).if {
	  affect := last_string.first;
	};
      } else {
	t := ITM_TYPE_SIMPLE.type_void;
      };
      last_slot.set_result_type t;
      last_slot.set_affect affect;

      (affect != ' ').if {
        read_space;
        (is_shorter2).if {
          (last_comment_slot != NULL).if {
            last_slot.set_comment last_comment_slot;
          };
          (last_comment_extern != NULL).if {
            last_slot.set_comment_chapter last_comment_extern;
          };
          skip_comment := TRUE;
        };
	old_pos    := position;
        old_derive := short_derive;
	read_def_slot;
      };

      (read_character ';').if_false {
	warning_error (current_position,"Added ';'.");
      };
      (is_shorter2).if {
        skip_comment := FALSE;
        read_space;
        ((last_slot.comment = NULL)    {last_comment_slot != NULL}).if {
          last_slot.set_comment last_comment_slot;
        };
      };

      (is_shorter).if {
	(
	  (! is_short_code)   
	  {old_pos != 0}   
	  {! last_section.is_header}
	).if {
	  (current_position.column<5).if {
	    {
	      (last_character != 0.to_character)   
	      {last_character.is_separator}   
	      {last_character != '\n'}
	    }.while_do {
	      position := position + 1;
	    };
	    (last_character = '\n').if {
	      position := position + 1;
	    };
	  };
	  output_code.remove_between
	  (old_pos + old_derive) to (position + short_derive - 1);
	  short_derive := old_derive - (position - old_pos);
	};
      };

      // Added slot in prototype :
      s := object.slot_list.fast_reference_at (last_slot.name);
      (s != NULL).if {
	POSITION.put_error semantic text "Double slot declaration.";
	s.position.put_position;
	last_slot.position.put_position;
	POSITION.send_error;
      };
      object.add_slot last_slot;

      (is_shorter).if {
	short_local.clear;
      };
    };
    result
  );  // read_slot

  //++ TYPE_SLOT    -> [ LOC_ARG '.' ] identifier [ LOC_ARG { identifier LOC_ARG } ]
  //++               | [ LOC_ARG ] '\'' operator '\'' [("Left"|"Right") [integer]] [LOC_ARG]
  - read_type_slot:ITM_SLOT <-
  ( + arg:ITM_ARGUMENT;
    + result:ITM_SLOT;
    + list_arg:FAST_ARRAY(ITM_ARGUMENT);

    list_arg := ALIAS_ARRAY(ITM_ARGUMENT).new;
    arg := read_loc_arg FALSE with_self TRUE;

    (arg = NULL).if {
      (read_character '\'').if {
	result := read_slot_operator list_arg;
      } else {
	arg := ITM_ARG.create current_position
        name (ALIAS_STR.variable_self) type (ITM_TYPE_SIMPLE.type_self);
	list_arg.add_last arg;
	result := read_slot_keyword list_arg;
      };
    } else {
      list_arg.add_last arg;
      (read_character '.').if {
	result := read_slot_keyword list_arg;
      }.elseif {read_character '\''} then {
	result := read_slot_operator list_arg;
      };
    };
    (result != NULL).if {
      list_arg := ALIAS_ARRAY(ITM_ARGUMENT).copy list_arg;
      result.set_argument_list list_arg;
    };
    result
  );

  - read_slot_keyword list_arg:FAST_ARRAY(ITM_ARGUMENT) :ITM_SLOT <-
  ( + n:STRING;
    + arg:ITM_ARGUMENT;
    + result:ITM_SLOT;

    read_identifier.if {
      short (ALIAS_STR.short_slot) token
      (position-last_string.count) to position;

      n  := ALIAS_STR.new;
      n.copy last_string;
      arg := read_loc_arg FALSE with_self FALSE;
      (arg != NULL).if {
	list_arg.add_last arg;
	(read_identifier).if {
	  (last_section.is_external).if {
	    syntax_error (current_position,"Incorrect in `Section External'.");
	  };
	  {
	    short (ALIAS_STR.short_slot) token
	    (position-last_string.count) to position;
	    n.append (ALIAS_STR.separate);
	    n.append last_string;
	    arg := read_loc_arg FALSE with_self FALSE;
	    (arg = NULL).if {
	      syntax_error (current_position,"Incorrect symbol.");
	    }; // if
	    list_arg.add_last arg;
	  }.do_while {read_identifier}; // loop
	};
      }; // if
      result := ITM_SLOT.create current_position name (ALIAS_STR.alias n) feature last_section;
    };
    result
  );

  - read_slot_operator list_arg:FAST_ARRAY(ITM_ARGUMENT) :ITM_SLOT <-
  ( + name,pretty_name:STRING_CONSTANT;
    + associativity:STRING_CONSTANT;
    + priority:INTEGER;
    + arg:ITM_ARGUMENT;
    + result:ITM_SLOT_OPERATOR;

    (! read_operator).if {
      syntax_error (current_position,"Operator is needed.");
    };
    (
      (last_string = ALIAS_STR.symbol_equal) ||
      {last_string = ALIAS_STR.symbol_not_equal}
    ).if {
      syntax_error (current_position,"Incorrect operator.");
    };
    pretty_name := name := last_string;
    (! read_character '\'').if {
      warning_error (current_position,"Added `''.");
    };
    (
      (read_this_keyword (ALIAS_STR.keyword_left)) ||
      {read_this_keyword (ALIAS_STR.keyword_right)}
    ).if {
      associativity := last_string;
      (read_integer).if {
	priority := last_integer.to_integer;
      };
    };

    (list_arg.is_empty).if {
      // Prefix operator.
      arg := read_loc_arg FALSE with_self TRUE;
      (arg = NULL).if {
	syntax_error (current_position,"Operator declaration invalid.");
      };
      list_arg.add_last arg;
      name := operator (ALIAS_STR.slot_prefix) name name;
      (associativity != NULL).if {
	syntax_error (current_position,"Not associativity for postfix operator.");
      };
    } else {
      arg := read_loc_arg FALSE with_self FALSE;
      (arg != NULL).if {
	// Infix operator.
	list_arg.add_last arg;
	name := operator (ALIAS_STR.slot_infix) name name;
	(associativity = NULL).if {
	  associativity := ALIAS_STR.keyword_left;
	};
      } else {
	// Postfix operator.
	name := operator (ALIAS_STR.slot_postfix) name name;
	(associativity != NULL).if {
	  syntax_error (current_position,"Not associativity for prefix operator.");
	};
      };
    };
    result := ITM_SLOT_OPERATOR.create current_position name name feature last_section;
    result.set_associativity associativity priority priority;
    result.set_pretty_name pretty_name;
    result
  );  // read_slot_operator

  //++ DEF_SLOT     -> [CONTRACT] EXPR [CONTRACT]
  - read_def_slot <-
  ( + expr:ITM_CODE;

    read_require;
    expr := read_expr;
    (expr = NULL).if {
      syntax_error (current_position,"Incorrect expression.");
    };
    last_slot.set_value expr type object;
    read_ensure;
  );

  //++ LOC_ARG      -> identifier ':' TYPE
  //++               | '(' LOCAL ')'
  - read_loc_arg mute:BOOLEAN with_self self_first:BOOLEAN :ITM_ARGUMENT <-
  ( + result:ITM_ARGUMENT;
    + t:ITM_TYPE_MONO;
    + pos:POSITION;
    + n:STRING_CONSTANT;
    + tb:ITM_TYPE_BLOCK;

    (
      ((  self_first)    {read_this_keyword (ALIAS_STR.variable_self)}) ||
      {(! self_first)    {read_identifier}}
    ).if {
      pos := current_position;
      n   := last_string;
      ((read_character ':')    {last_character != '='}).if {
	t := read_type TRUE;
	(t = NULL).if {
	  syntax_error (current_position,"Incorrect type.");
        };

	(
	  (self_first)   
          {t != ITM_TYPE_SIMPLE.type_self}   
          {
            (object.name != ALIAS_STR.prototype_block) ||
            {tb ?= t; tb = NULL}
          }
        ).if {
	  syntax_error (current_position,"Type `SELF' is needed.");
	};
	result := ITM_ARG.create pos name n type t;

	(is_shorter).if {
	  short_local.add n;
	};
      } else {
	mute.if_false {
	  warning_error (current_position,"Added ':' is needed.");
	};
      };
    }.elseif {read_character '('} then {
      result := read_local_arg mute with_self self_first;
      (result = NULL).if {
	mute.if_false {
	  syntax_error (current_position,"Incorrect argument definition.");
	};
      } else {
	(read_character ')').if_false {
	  warning_error (current_position,"Added ')'.");
	};
      };
    };
    result
  );

  //++ LOCAL        -> { identifier [ ':' TYPE ] ',' } identifier ':' TYPE
  - read_local m:BOOLEAN :FAST_ARRAY(ITM_LOCAL) <-
  ( + t:ITM_TYPE_MONO;
    + loc:ITM_LOCAL;
    + result:FAST_ARRAY(ITM_LOCAL);
    + beg:INTEGER;
    + mute:BOOLEAN;

    mute := m;
    (read_identifier).if {
      result := ALIAS_ARRAY(ITM_LOCAL).new;
      beg := result.lower;
      {
	((result.count != 0)    {! read_identifier}    {! mute}).if {
	  syntax_error (current_position,"Incorrect identifier.");
	};
	loc := ITM_LOCAL.create current_position name last_string;
	result.add_last loc;
	((read_character ':')    {last_character != '='}).if {
	  mute := FALSE;
	  t := read_type TRUE;
	  (t = NULL).if {
	    syntax_error (current_position,"Incorrect local type.");
	  };
	  beg.to (result.upper) do { j:INTEGER;
	    result.item j.set_type t;
	  };
	  beg := result.upper + 1;
	};
      }.do_while {read_character ','};
      (beg != result.upper + 1).if {
	(mute).if {
	  ALIAS_ARRAY(ITM_LOCAL).free result;
	  result := NULL;
	} else {
	  syntax_error (current_position,"Incorrect local type.");
	};
      } else {
	result := ALIAS_ARRAY(ITM_LOCAL).copy result;

	(is_shorter).if {
	  (result.lower).to (result.upper) do { j:INTEGER;
	    short_local.add (result.item j.name);
	  };
	};
      };
    };

    result
  );  // read_local

  - read_local_arg m:BOOLEAN with_self s:BOOLEAN :ITM_ARGUMENT <-
  ( + t:ITM_TYPE_MONO;
    + tm:ITM_TYPE_MULTI;
    + type:FAST_ARRAY(ITM_TYPE_MONO);
    + name:FAST_ARRAY(STRING_CONSTANT);
    + beg:INTEGER;
    + mute:BOOLEAN;
    + result:ITM_ARGUMENT;
    + tb:ITM_TYPE_BLOCK;

    mute := m;
    (
      ((s)    {read_this_keyword (ALIAS_STR.variable_self)}) ||
      {read_identifier}
    ).if {
      name := ALIAS_ARRAY(STRING_CONSTANT).new;
      type := ALIAS_ARRAY(ITM_TYPE_MONO).new;
      beg  := name.lower;
      {
	((name.count != 0)    {! read_identifier}    {! mute}).if {
	  syntax_error (current_position,"Incorrect argument identifier.");
	};
	name.add_last last_string;
	((read_character ':')    {last_character != '='}).if {
	  mute := FALSE;
	  t := read_type TRUE;
	  (t = NULL).if {
	    syntax_error (current_position,"Incorrect argument type.");
	  };
	  beg.to (name.upper) do { j:INTEGER;
	    type.add_last t;
	  };
	  beg := name.upper + 1;
	};
      }.do_while {read_character ','};
      (beg != name.upper + 1).if {
	(mute).if_false {
	  syntax_error (current_position,"Incorrect argument type.");
	};
	ALIAS_ARRAY(STRING_CONSTANT).free name;
	ALIAS_ARRAY(ITM_TYPE_MONO).free type;
      } else {
	(
	  (s)    {
	    (type.first != ITM_TYPE_SIMPLE.type_self) || {
	      (object.name = ALIAS_STR.prototype_block)   
	      {tb ?= type.first; tb = NULL}
	    }
	  }
	).if {
	  syntax_error (current_position,"Type `SELF' is needed.");
	};
	(name.count = 1).if {
	  // Single Argument.
	  result := ITM_ARG.create current_position
	  name (name.first)
	  type (type.first);
	  ALIAS_ARRAY(STRING_CONSTANT).free name;
	  ALIAS_ARRAY(ITM_TYPE_MONO).free type;
	} else {
	  // Vector Arguments.
	  name := ALIAS_ARRAY(STRING_CONSTANT).alias name;
	  type := ALIAS_ARRAY(ITM_TYPE_MONO).alias type;
	  tm := ITM_TYPE_MULTI.get type;
	  result := ITM_ARGS.create current_position name name type tm;
	};

	(is_shorter).if {
	  (name.lower).to (name.upper) do { j:INTEGER;
	    short_local.add (name.item j);
	  };
	};
      };
    };

    result
  );  // read_local

  //++ TYPE_LIST    -> TYPE { ',' TYPE }
  - read_type_list is_section:BOOLEAN :FAST_ARRAY(ITM_TYPE_MONO) <-
  ( + lst:FAST_ARRAY(ITM_TYPE_MONO);
    + t:ITM_TYPE_MONO;
    + ts:ITM_TYPE_SIMPLE;

    t := read_type FALSE;
    (t != NULL).if {
      (is_section).if {
	ts ?= t;
	(ts = NULL).if {
	  syntax_error (current_position,
	  "For a section, the prototype name only (without '['...']').");
	};
      };
      lst := ALIAS_ARRAY(ITM_TYPE_MONO).new;
      lst.add_last t;
      {read_character ','}.while_do {
	t := read_type FALSE;
	(t = NULL).if {
	  syntax_error (current_position,"Incorrect type list.");
	};
	(is_section).if {
	  ts ?= t;
	  (ts = NULL).if {
	    syntax_error (current_position,
	    "For a section, the prototype name only (without '['...']').");
	  };
	};
	lst.add_last t;
      };
      lst := ALIAS_ARRAY(ITM_TYPE_MONO).alias lst;
    };
    lst
  );

  //++ TYPE         -> '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
  //++               | [type] PROTOTYPE [ CONTRACT ]
  - read_type is_local:BOOLEAN :ITM_TYPE_MONO <-
  ( + style:STRING_CONSTANT;
    + result:ITM_TYPE_MONO;
    + lst:FAST_ARRAY(ITM_TYPE_MONO);
    + typ_arg,typ_res:ITM_TYPE;
    + contract:ITM_LIST;

    (read_character '{').if {
      // '{' [ (TYPE | '(' TYPE_LIST ')') ';' ] [ TYPE_LIST ] '}'
      (read_character '(').if {
	// Read vector argument.
	lst := read_type_list FALSE;
	(lst = NULL).if {
	  syntax_error (current_position,"Incorrect type list.");
	};
	(lst.count = 1).if {
	  typ_arg := lst.first;
	} else {
	  typ_arg := ITM_TYPE_MULTI.get lst;
	};
	(! read_character ')').if {
	  warning_error (current_position,"Added ')'.");
	}; // if
	(! read_character ';').if {
	  warning_error (current_position,"Added ';'.");
        }; // if
        lst := read_type_list FALSE;
      } else {
	lst := read_type_list FALSE;
	(lst != NULL).if {
	  (read_character ';').if {
	    (lst.count = 1).if {
	      typ_arg := lst.first;
	    } else {
	      typ_arg := ITM_TYPE_MULTI.get lst;
	      string_tmp.copy "Added '";
	      typ_arg.append_in string_tmp;
	      string_tmp.append "'.";
	      warning_error (current_position,string_tmp);
            };
            lst := read_type_list FALSE;
          };
	};
      };
      (lst != NULL).if {
        (lst.count = 1).if {
          typ_res := lst.first;
        } else {
          typ_res := ITM_TYPE_MULTI.get lst;
        };
      };
      (! read_character '}').if {
	warning_error (current_position,"Added '}'.");
      }; // if
      result := ITM_TYPE_BLOCK.get typ_arg and typ_res;
    } else {
      // Expanded | Strict
      (
	(read_this_keyword (ALIAS_STR.keyword_expanded)) ||
	{read_this_keyword (ALIAS_STR.keyword_strict)}
      ).if {
	style := last_string;
	((is_local)    {last_string = ALIAS_STR.keyword_expanded}).if {
	  syntax_error (current_position,"`Expanded' is not possible.");
	};
      };
      // PROTOTYPE
      result := read_prototype style;
      contract := read_contract;
      (contract != NULL).if {
        warning_error (current_position,"Sorry, not yet implemented.");
      };
    };
    result
  );  // read_type

  //++ PROTOTYPE    -> cap_identifier{('.'|'...')cap_identifier}['('PARAM_TYPE{','PARAM_TYPE}')']
  - read_prototype styl:STRING_CONSTANT :ITM_TYPE_MONO <-
  ( + nam:STRING_CONSTANT;
    + genericity:FAST_ARRAY(ITM_TYPE_MONO);
    + result,t:ITM_TYPE_MONO;
    + old_pos,old_derive,sav_derive,pos_before:INTEGER;
    + continue:BOOLEAN;


    (read_cap_identifier).if {
      old_pos    := position;
      old_derive := short_derive;
      string_tmp2.copy last_string;
      {
        continue := read_word (ALIAS_STR.keyword_ldots);
        (continue).if {
          (read_cap_identifier).if_false {
            syntax_error (current_position,"Prototype name needed.");
          };
          string_tmp2.append (ALIAS_STR.keyword_ldots);
          string_tmp2.append last_string;
        } else {
          pos_before := position;
          ((read_character '.')    {read_cap_identifier}).if {
            continue := TRUE;
            string_tmp2.add_last '.';
            string_tmp2.append last_string;
          } else {
            position := pos_before;
          };
        };
      }.do_while {continue};
      nam := ALIAS_STR.get string_tmp2;
      //
      (read_character '(').if {
	// Multiple Genericity.
        genericity := ALIAS_ARRAY(ITM_TYPE_MONO).new;
        {
          t := read_param_type;
          (t = NULL).if {
            syntax_error (current_position,"Type needed.");
          };
          genericity.add_last t;
        }.do_while {read_character ','};
        genericity := ALIAS_ARRAY(ITM_TYPE_MONO).alias genericity;
        result     := ITM_TYPE_GENERIC.get nam style styl with genericity;
        (read_character ')').if_false {
          warning_error (current_position,"Added ')'.");
        };
      } else {
        // Simple type.
        (is_parameter_type).if {
          (styl != NULL).if {
            string_tmp.copy "Style `";
            string_tmp.append styl;
            string_tmp.append "' for parameter type is ignored.";
            warning_error (current_position,string_tmp);
          };
          result := ITM_TYPE_PARAMETER.get nam;
        }.elseif {styl = NULL} then {
	  result := ITM_TYPE_SIMPLE.get nam;
	} else {
	  (nam = ALIAS_STR.prototype_self).if {
	    string_tmp.copy "Style `";
	    string_tmp.append styl;
	    string_tmp.append "' ignored.";
            warning_error (current_position,string_tmp);
	    result := ITM_TYPE_SIMPLE.type_self;
	  } else {
	    result := ITM_TYPE_STYLE.get nam style styl;
	  };
	};
      }; // if
      (is_shorter).if {
        sav_derive := short_derive;
        short_derive := old_derive;
        (
          (result = ITM_TYPE_SIMPLE.type_self) ||
          {result = ITM_TYPE_SIMPLE.type_null}
        ).if {
          short (ALIAS_STR.short_keyprototype) token
          (old_pos - nam.count) to old_pos;
        } else {
          short (ALIAS_STR.short_prototype) token
          (old_pos - nam.count) to old_pos;
        };
        short_derive := sav_derive + (short_derive - old_derive);
      };
    }; // if
    result
  );  // read_prototype

  - read_param_type:ITM_TYPE_MONO <-
  //++ PARAM_TYPE   -> TYPE
  //++               | CONSTANT
  //++               | identifier
  ( + result:ITM_TYPE_MONO;
    + cst:ITM_CONSTANT;

    result := read_type FALSE;
    (result = NULL).if {
      cst := read_constant;
      (cst != NULL).if {
        syntax_error (current_position,"1) Sorry, not yet implemented.");
        //result :=
      }.elseif {read_identifier} then {
        syntax_error (current_position,"2) Sorry, not yet implemented.");
        //result :=
      };
    };
    result
  );

  //++ EXPR         -> { ASSIGN !!AMBIGU!! affect } EXPR_OPERATOR
  //++ ASSIGN       -> '(' IDF_ASSIGN { ',' IDF_ASSIGN } ')'
  //++               | IDF_ASSIGN
  //++ IDF_ASSIGN   -> identifier { identifier }
  - read_expr:ITM_CODE <-
  ( + result,value:ITM_CODE;
    + affect:CHARACTER;
    + again:BOOLEAN;
    + l_assignment:FAST_ARRAY(STRING_CONSTANT);
    + p:INTEGER;
    + name:STRING_CONSTANT;

    // !! AMBIGU resolution !!
    save_context;
    (read_character '(').if {
      l_assignment := ALIAS_ARRAY(STRING_CONSTANT).new;
      {
	again := FALSE;
	(read_identifier).if {
	  p := position - last_string.count;
	  string_tmp2.copy last_string;
	  {read_identifier}.while_do {
	    string_tmp2.append (ALIAS_STR.separate);
	    string_tmp2.append last_string;
	  };
	  name := ALIAS_STR.get string_tmp2;
	  l_assignment.add_last name;

	  (is_shorter).if {
	    (! short_local.fast_has name).if {
	      short (ALIAS_STR.short_slot_call) token p to position;
	    };
	  };

	  (read_character ',').if {
	    again := TRUE;
	  };
	};
      }.do_while {again};
      ((! l_assignment.is_empty)    {read_character ')'}    {read_affect}).if {
	l_assignment := ALIAS_ARRAY(STRING_CONSTANT).copy l_assignment;
	result := ITM_LIST_IDF.create current_position with l_assignment;
	affect := last_string.first;
	value  := read_expr;
	(value = NULL).if {
	  syntax_error (current_position,"Incorrect expression.");
	};
	(affect)
	.when ':' then {
	  result := ITM_WRITE_VALUE.create (result.position) assign result with value;
	}
	.when '<' then {
	  syntax_error (current_position,"Impossible '<-' style assignment with vector.");
	}
	.when '?' then {
	  syntax_error (current_position,"Sorry, Not yet implemented !");
	  result := ITM_WRITE_CAST.create (result.position) assign result with value;
	};
      } else {
	ALIAS_ARRAY(STRING_CONSTANT).free l_assignment;
      };
    }.elseif {read_identifier} then {
      p := position - last_string.count;
      string_tmp2.copy last_string;
      {read_identifier}.while_do {
	string_tmp2.append (ALIAS_STR.separate);
	string_tmp2.append last_string;
      };
      name := ALIAS_STR.get string_tmp2;

      (is_shorter).if {
	(! short_local.fast_has name).if {
	  short (ALIAS_STR.short_slot_call) token p to position;
	};
      };

      (read_affect).if {
	result := ITM_READ.create current_position name name;
	affect := last_string.first;
	value  := read_expr;
	(value = NULL).if {
	  syntax_error (current_position,"Incorrect expression.");
	};
	(affect)
	.when ':' then {
	  result := ITM_WRITE_VALUE.create (result.position) assign result with value;
	}
	.when '<' then {
	  result := ITM_WRITE_CODE.create (result.position) assign result with value;
	}
	.when '?' then {
	  result := ITM_WRITE_CAST.create (result.position) assign result with value;
	};
      };
    };
    (result = NULL).if {
      restore_context;
      result := read_expr_operator;
    };
    result
  );

  //++ EXPR_OPERATOR-> { operator } EXPR_MESSAGE { operator {operator} EXPR_MESSAGE } {operator}
  - read_expr_operator:ITM_CODE <-
  ( + result:ITM_CODE;
    + expr :ITM_CODE;
    + l_expr:FAST_ARRAY(ITM_CODE);
    + itm_op:ITM_OPERATOR;
    + last_msg,first_msg:INTEGER;

    l_expr := ALIAS_ARRAY(ITM_CODE).new;
    {read_operator}.while_do {
      expr := ITM_OPERATOR.create current_position name last_string;
      l_expr.add_last expr;
    };
    expr := read_expr_message;
    (expr = NULL).if {
      // Error.
      (! l_expr.is_empty).if {
	syntax_error (current_position,"Incorrect expression.");
      };
      ALIAS_ARRAY(ITM_CODE).free l_expr;
    } else {
      // { operator {operator} EXPR_MESSAGE } {operator}
      first_msg := l_expr.count;
      {
	last_msg := l_expr.count;
	l_expr.add_last expr;
	(read_operator).if {
	  {
	    expr := ITM_OPERATOR.create current_position name last_string;
	    l_expr.add_last expr;
	  }.do_while {read_operator};
	  expr := read_expr_message;
	} else {
	  expr := NULL;
	};
      }.do_while {expr != NULL};

      // Last Post-fix operator.
      {last_msg < l_expr.upper}.while_do {
	itm_op ?= l_expr.item (last_msg + 1);
	expr := ITM_READ_ARG1.create (itm_op.position)
	name (operator (ALIAS_STR.slot_postfix) name (itm_op.name))
	arg (l_expr.item last_msg);
	l_expr.put expr to last_msg;
	l_expr.remove (last_msg + 1);
      };
      ((last_msg - first_msg) < 3).if {
	// First Pre-fix operator.
	{first_msg != 0}.while_do {
	  itm_op ?= l_expr.item (first_msg - 1);
	  expr := ITM_READ_ARG1.create (itm_op.position)
	  name (operator (ALIAS_STR.slot_prefix) name (itm_op.name))
	  arg (l_expr.item first_msg);
	  l_expr.put expr to first_msg;
	  first_msg := first_msg - 1;
	  l_expr.remove first_msg;
	};
      };
      (l_expr.count = 1).if {
	result := l_expr.first;
	ALIAS_ARRAY(ITM_CODE).free l_expr;
      }.elseif {l_expr.count = 3} then {
	// Simple binary message.
	itm_op ?= l_expr.second;
	result := ITM_READ_ARG2.create (itm_op.position)
	name (operator (ALIAS_STR.slot_infix) name (itm_op.name))
	args (l_expr.first,l_expr.item 2);
	//
	ALIAS_ARRAY(ITM_CODE).free l_expr;
      } else {
	// Complex expression.
	l_expr := ALIAS_ARRAY(ITM_CODE).copy l_expr;
	result := ITM_EXPRESSION.create l_expr;
      };
    };
    result
  );  // read_expr_operator

  //++ EXPR_MESSAGE -> EXPR_BASE { '.' SEND_MSG }
  - read_expr_message:ITM_CODE <-
  ( + result:ITM_CODE;

    result := read_expr_base;
    (result != NULL).if {
      {read_character '.'}.while_do {
	result := read_send_msg result;
	(result=NULL).if {
	  syntax_error (current_position,"Incorrect message.");
	}; // if
      }; // loop
    }; //if
    result
  );  // read_expr_message

  //++ EXPR_BASE    -> "Old" EXPR
  //++               | EXPR_PRIMARY
  //++               | SEND_MSG
  - read_expr_base:ITM_CODE <-
  ( + result,old_value:ITM_CODE;

    (read_this_keyword (ALIAS_STR.keyword_old)).if {
      old_value := read_expr;
      (old_value = NULL).if {
	syntax_error (current_position,"Incorrect `Old' expression.");
      };
      result := ITM_OLD.create current_position value old_value;
    } else {
      result := read_expr_primary;
      (result = NULL).if {
	result := read_send_msg NULL;
      };
    };
    result
  );  // read_expr_base

  //++ EXPR_PRIMARY -> "Self"
  //++               | result
  //++               | PROTOTYPE
  //++               | CONSTANT
  //++               | '(' GROUP ')'
  //++               | '{' [ LOC_ARG ';' !! AMBIGU!! ] GROUP '}'
  //++               | external [ ':' ['('] TYPE ['{' TYPE_LIST '}'] [')'] ]
  - read_expr_primary:ITM_CODE <-
  ( + result:ITM_CODE;
    + type :ITM_TYPE_MONO;
    + ltype:FAST_ARRAY(ITM_TYPE_MONO);
    + ext  :ITM_EXTERNAL_TYPE;
    + group_sav:ITM_LIST;
    + arg:ITM_ARGUMENT;
    + result_id:STRING_CONSTANT;
    + pos : POSITION;

    pos := current_position; // Get the position before consuming the tokens

    (read_this_keyword (ALIAS_STR.variable_self)).if {
      result := ITM_READ.create current_position name last_string;
    }.elseif {read_this_keyword (ALIAS_STR.keyword_result)} then {
      (last_character = '_').if {
	position := position + 1;
	string_tmp.copy (ALIAS_STR.keyword_result);
	string_tmp.add_last '_';
	{last_character.is_digit}.while_do {
	  string_tmp.add_last last_character;
	  position := position + 1;
	};
	(string_tmp.is_empty).if {
	  syntax_error (current_position,"Incorrect Result number.");
	};
	result_id := ALIAS_STR.get string_tmp;
      } else {
	result_id := ALIAS_STR.keyword_result;
      };
      result := ITM_READ.create current_position name result_id;
    }.elseif {
      type := read_prototype NULL;
      type != NULL
    } then {
      result := ITM_PROTOTYPE.create current_position type type;
    }.elseif {(result := read_constant) != NULL} then {
    }.elseif {read_character '(' } then {
      group_sav := last_group;
      // @bookmark Create list
      last_group := ITM_LIST.create pos;
      result := last_group;
      last_group.set_code read_group;
      (read_character ')').if_false {
	warning_error (current_position,"Added ')'.");
      }; // if
      last_group := group_sav;
    }.elseif {read_character '{' } then {
      short (ALIAS_STR.short_block) token (position-1) to position;
      group_sav := last_group;
      // @bookmark Create block
      last_group := ITM_LIST.create pos;

      save_context; // !! SAVE CONTEXT !!

      //
      arg := read_loc_arg TRUE with_self FALSE;
      //
      (arg != NULL).if {
	(read_character ';').if_false {
	  warning_error (current_position,"Added ';'.");
	}; // if
      } else {

	restore_context; // !! RESTORE CONTEXT !!

      };
      result := ITM_BLOCK.create last_group argument arg;

      last_group.set_code read_group;
      (! read_character '}').if {
	warning_error (current_position,"Added '}'.");
      }; // if
      short (ALIAS_STR.short_block) token (position-1) to position;
      last_group := group_sav;
    }.elseif {read_external} then {
      (! read_character ':').if {
	result := ITM_EXTERNAL.create current_position text last_string;
      } else {
	ext := ITM_EXTERNAL_TYPE.create current_position text
	last_string persistant (read_character '(');
	type := read_type FALSE;
	(type = NULL).if {
	  syntax_error (current_position,"Incorrect type.");
	};
	ext.set_type type;
	(read_character '{').if {
	  ltype := read_type_list FALSE;
	  (ltype = NULL).if {
	    syntax_error (current_position,"Incorrect live type list.");
	  };
	  (! read_character '}').if {
	    warning_error (current_position,"Added '}'.");
	  };
	  ext.set_type_list ltype;
	};
	((ext.is_persistant)    {! read_character ')'}).if {
	  warning_error (current_position,"Added ')'.");
	};
	result := ext;
      };
    };
    result
  );  // read_expr_primaire

  - read_constant:ITM_CONSTANT <-
  //++ CONSTANT     -> integer
  //++               | real
  //++               | characters
  //++               | string
  ( + result:ITM_CONSTANT;

    (read_real).if {
      result := ITM_REAL.create current_position value last_real;
    }.elseif {read_integer} then {
      result := ITM_NUMBER.create current_position value last_integer;
    }.elseif {read_characters} then {
      result := ITM_CHARACTER.create current_position char last_string;
    }.elseif {read_string} then {
      result := ITM_STRING.create current_position text last_string;
    };
    result
  );

  //++ GROUP        -> DEF_LOCAL {EXPR ';'} [ EXPR {',' {EXPR ';'} EXPR } ]
  - read_group:FAST_ARRAY(ITM_CODE) <-
  ( + e:ITM_CODE;
    + result:FAST_ARRAY(ITM_CODE);

    read_def_local;

    result := ALIAS_ARRAY(ITM_CODE).new;
    e := read_expr;
    {(e != NULL)    {read_character ';'}}.while_do {
      result.add_last e;
      e := read_expr;
    };
    (e != NULL).if {
      (read_character ',').if {
	{
	  e := ITM_RESULT.create e;
	  result.add_last e;
	  e := read_expr;
	  {(e != NULL)    {read_character ';'}}.while_do {
	    result.add_last e;
	    e := read_expr;
	  };
	  (e = NULL).if {
	    syntax_error (current_position,"Incorrect multiple result expression.");
	  };
        }.do_while {read_character ','};
      };
      e := ITM_RESULT.create e;
      result.add_last e;
    };
    read_space;
    last_group.insert_code_coverage_hook current_position in result;
    ALIAS_ARRAY(ITM_CODE).copy result
  );

  - read_invariant:BOOLEAN <-
  ( + lst:ITM_LIST;

    lst := read_contract;
    lst != NULL
  );

  - read_require:BOOLEAN <-
  ( + lst:ITM_LIST;
    + result:BOOLEAN;

    lst := read_contract;
    (lst != NULL).if {
      last_slot.set_require lst;
      result := TRUE;
    };
    result
  );

  - read_ensure:BOOLEAN <-
  ( + lst:ITM_LIST;
    + result:BOOLEAN;

    lst := read_contract;
    (lst != NULL).if {
      last_slot.set_ensure lst;
      result := TRUE;
    };
    result
  );

  //++ CONTRACT     -> '[' DEF_LOCAL { ( EXPR ';' | "..." ) } ']'
  - read_contract:ITM_LIST <-
  ( + continue:BOOLEAN;
    + e:ITM_CODE;
    + result:ITM_LIST;
    + lst:FAST_ARRAY(ITM_CODE);
    + pos : POSITION;

    pos := current_position;

    (read_character '[').if {
      // @bookmark: create contract
      result := last_group := ITM_LIST.create pos;
      read_def_local;

      lst := ALIAS_ARRAY(ITM_CODE).new;
      {
	e := read_expr;
	(e = NULL).if {
	  continue := read_word (ALIAS_STR.keyword_ldots);
	  (continue).if {
	    lst.add_last (ITM_LDOTS.create current_position);
	  };
	} else {
	  lst.add_last e;
	  (! read_character ';').if {
	    warning_error (current_position,"Added ';'.");
	  };
	  continue := TRUE;
	};
      }.do_while {continue};

      read_space;
      pos := current_position;

      (! read_character ']').if {
	warning_error (current_position,"Added ']'.");
      };

      result.insert_code_coverage_hook pos in lst;
      e := ITM_PROTOTYPE.create current_position type (ITM_TYPE_SIMPLE.type_void);
      lst.add_last e;
      //
      result.set_code (ALIAS_ARRAY(ITM_CODE).copy lst);
    };
    result
  );

  //++ DEF_LOCAL    -> { style LOCAL ';' } !! AMBIGU !!
  - read_def_local <-
  ( + loc_lst:FAST_ARRAY(ITM_LOCAL);
    + local_list,static_list:FAST_ARRAY(ITM_LOCAL);
    + styl:CHARACTER;

    save_context; // !! SAVE CONTEXT !!

    styl    := read_style;
    local_list  := ALIAS_ARRAY(ITM_LOCAL).new;
    static_list := ALIAS_ARRAY(ITM_LOCAL).new;
    {styl != ' '}.while_do {
      loc_lst := read_local TRUE;
      (loc_lst != NULL).if {
	(styl = '+').if {
	  local_list.append_collection loc_lst;
	} else {
	  static_list.append_collection loc_lst;
	};
	(read_character ';').if_false {
	  warning_error (current_position,"Added ';'.");
	};

	save_context; // !! SAVE CONTEXT !!

	styl := read_style;
      } else {

	restore_context; // !! RESTORE CONTEXT !!

	styl := ' ';
      };
    };
    (local_list.is_empty).if {
      ALIAS_ARRAY(ITM_LOCAL).free local_list;
    } else {
      last_group.set_local_list  (ALIAS_ARRAY(ITM_LOCAL).copy local_list);
    };
    (static_list.is_empty).if {
      ALIAS_ARRAY(ITM_LOCAL).free static_list;
    } else {
      last_group.set_static_list (ALIAS_ARRAY(ITM_LOCAL).copy static_list);
    };
  );

  //++ SEND_MSG     -> identifier [ ARGUMENT { identifier ARGUMENT } ]
  - read_send_msg first_arg:ITM_CODE :ITM_CODE <-
  ( + result:ITM_CODE;
    + name :STRING_CONSTANT;
    + n:STRING;
    + l_arg:FAST_ARRAY(ITM_CODE);
    + arg:ITM_CODE;
    + p1,p2,old_derive,sav_derive:INTEGER;

    read_identifier.if {
      //
      // Classic Message.
      //
      p1 := position - last_string.count;
      p2 := position;
      old_derive := short_derive;

      n := ALIAS_STR.new;
      n.copy last_string;
      // Argument list.
      l_arg := ALIAS_ARRAY(ITM_CODE).new;
      arg := read_argument;
      (arg != NULL).if {
	l_arg.add_last arg;
	{read_identifier}.while_do {

	  short (ALIAS_STR.short_slot_call) token
	  (position-last_string.count) to position;

	  n.append (ALIAS_STR.separate);
	  n.append last_string;
	  arg := read_argument;
	  (arg = NULL).if {
	    syntax_error (current_position,"Incorrect argument.");
	  }; // if
	  l_arg.add_last arg;
	}; // loop
      }; // if
      name := ALIAS_STR.alias n;

      (is_shorter).if {
	(
	  (! l_arg.is_empty) ||
	  {first_arg != NULL} ||
	  {! short_local.fast_has last_string}
	).if {
	  sav_derive := short_derive;
	  short_derive := old_derive;
	  short (ALIAS_STR.short_slot_call) token p1 to p2;
	  short_derive := sav_derive + (short_derive-old_derive);
	};
      };

      l_arg.is_empty.if {
	(first_arg=NULL).if {
	  // Local ou Implicite Slot without argument.
	  result := ITM_READ.create current_position name name;
	} else {
	  result := ITM_READ_ARG1.create current_position name name arg first_arg;
	};
	ALIAS_ARRAY(ITM_CODE).free l_arg;
      }.elseif {l_arg.count=1} then {
	result := ITM_READ_ARG2.create current_position name
	name args (first_arg,(l_arg.first));
	ALIAS_ARRAY(ITM_CODE).free l_arg;
      } else {
	l_arg.add_first first_arg;
	l_arg := ALIAS_ARRAY(ITM_CODE).copy l_arg;
	result := ITM_READ_ARGS.create current_position name name args l_arg;
      };
    }; // if
    result
  );  // read_send_msg

  //++ ARGUMENT     -> EXPR_PRIMARY
  //++               | identifier
  - read_argument:ITM_CODE <-
  ( + result:ITM_CODE;
    result := read_expr_primary;
    ((result = NULL)    {read_identifier}).if {
      (is_shorter).if {
	(short_local.fast_has last_string).if_false {
	  short (ALIAS_STR.short_slot_call) token
	  (position-last_string.count) to position;
	};
      };
      result := ITM_READ.create current_position name last_string;
    };
    result
  );  // read_argument

  // name, export, import, type, default, external, version, lip,
  // date, comment, author, bibliography, language, bug_report,
  // copyright.
  - read_slot_header first:BOOLEAN :BOOLEAN <-
  ( + result:BOOLEAN;
    + v:ITM_CODE;
    + cast:FAST_ARRAY(ITM_TYPE_MONO);
    + style:CHARACTER;
    + is_export:BOOLEAN;
    + parameter_type:ITM_TYPE_PARAMETER;
    + instr:LIP_CODE;
    + param:{ITM_TYPE_PARAMETER};

    style := read_style;
    (style != ' ').if {
      result := TRUE;
      ((! first)    {style = '+'}).if {
	warning_error (current_position,"Incorrect style slot ('-').");
      };
      (first).if {
	(read_word (ALIAS_STR.slot_name)).if {
	  //
	  // Read `name' slot.
	  //

          (style = '-').if {
            semantic_error (current_position,"COP not yet implemented.");
            is_cop := TRUE;
            (is_java).if {
              semantic_error (current_position,"COP not yet implemented.");
            } else {
              output_decl.append
              "#include <pthread.h>\n\
              \#include <limits.h>\n\n\
              \void print_char(char car);\n\
              \int die_with_code(int code);\n\n\
              \static pthread_key_t current_thread;\n\
              \static pthread_attr_t thread_attr;\n\
              \pthread_t c_thread;\n\
              \int thread_counter;\n\n\
              \static char thread_stack[512][PTHREAD_STACK_MIN];\n\n\
              \typedef struct lith_object_struct lith_object;\n\
              \typedef struct lith_node_struct lith_node;\n\
              \struct lith_node_struct {\n\
                \  pthread_mutex_t mutex;\n\
                \  lith_node *next;\n\
                \  lith_object *object;\n\
              \};\n\
              \struct lith_object_struct {\n\
                \  unsigned long __id; // Just for late binding.\n\
                \  lith_node *first;\n\
                \  lith_node *last;\n\
                \  lith_object *(*procedure)(lith_object *obj,pthread_mutex_t *mutex);\n\
                \  pthread_mutex_t mutex;\n\
              \};\n\
              \struct {\n\
                \  lith_node *first;\n\
                \  pthread_mutex_t mutex;\n\
              \} pool;\n\n\
              \void *thread_life(void *ptr)\n\
              \{ lith_node node,*n;\n\
                \  lith_object *obj,*new_obj;\n\n\
                \  pthread_mutex_init( node.mutex,NULL);\n\
                \  pthread_mutex_lock( node.mutex);\n\
                \  node.object = (lith_object *)ptr;\n\
                \  do {\n\
                  \    // Append fifo object.\n\
                  \    obj = node.object;\n\
                  \    node.next = NULL;\n\
                  \    n = obj->last;\n\
                  \    if (n == NULL) {\n\
                    \      obj->first =  node;\n\
                    \      pthread_mutex_unlock( node.mutex);\n\
                  \    } else {\n\
                    \      n->next =  node;\n\
                  \    };\n\
                  \    obj->last =  node;\n\
                  \    pthread_setspecific(current_thread,(void *)obj);\n\
                  \    // Run procedure.\n\
                  \    new_obj = obj->procedure(obj, node.mutex);\n\
                  \    // Remove fifo object.\n\
                  \    pthread_mutex_lock( obj->mutex);\n\
                  \    n = obj->first->next;\n\
                  \    if (n != NULL) {\n\
                    \      pthread_mutex_unlock( n->mutex);\n\
                  \    } else {\n\
                    \      obj->last = NULL;\n\
                  \    };\n\
                  \    obj->first = n;\n\
                  \    pthread_mutex_unlock( obj->mutex);\n\
                  \    if (new_obj != NULL) {\n\
                    \      node.object = new_obj;\n\
                  \    } else {\n\
                    \      // Add in pool.\n\
                    \      pthread_mutex_lock( pool.mutex);\n\
                    \      node.next = pool.first;\n\
                    \      pool.first =  node;\n\
                    \      pthread_mutex_unlock( pool.mutex);\n\
                    \      // Sleep.\n\
                    \      pthread_mutex_lock( node.mutex);\n\
                  \    };\n\
                \  } while (1);\n\
                \  return NULL;\n\
              \};\n\n\
              \void run_procedure(lith_object *obj)\n\
              \{ lith_node *node;\n\
                \  char *msg=\"COP Error!\\n\";\n\
                \  // Pool manager.\n\
                \  pthread_mutex_lock( pool.mutex);\n\
                \  node = pool.first;\n\
                \  if (node != NULL) {\n\
                  \    pool.first = node->next;\n\
                \  };\n\
                \  pthread_mutex_unlock( pool.mutex);\n\
                \  // Run thread.\n\
                \  if (node == NULL) {\n\
                  \    pthread_attr_setstack( thread_attr, thread_stack[thread_counter++],PTHREAD_STACK_MIN);\n\
                  \    if ((thread_counter>512) || pthread_create( c_thread, thread_attr, thread_life, (void *)obj)) {\n\
                    \      while (*msg != 0) print_char(*(msg++));\n\
                    \      die_with_code(1);\n\
                  \    };\n\
                \  } else {\n\
                  \    node->object = obj;\n\
                  \    pthread_mutex_unlock( node->mutex);\n\
                \  };\n\
              \};\n\n";
            };
	  };

	  // style "name" ':=' [type] cap_identifier [ '(' PARAM {',' PARAM}')' ]
	  // PARAM -> cap_identifier | identifier ':' TYPE
	  short (ALIAS_STR.short_slot) token
	  (position-last_string.count) to position;

	  object.set_position current_position;
          object.set_style style;
	  (read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	    warning_error (current_position,"Added ':='.");
	  };

	  (
	    (read_this_keyword (ALIAS_STR.keyword_expanded)) ||
	    {read_this_keyword (ALIAS_STR.keyword_strict)}
	  ).if {
	    object.set_type_style last_string;
	  };

	  (! read_cap_identifier).if {
	    syntax_error (current_position,"Prototype identifier is needed.");
	  };
	  short (ALIAS_STR.short_prototype) token
	  (position-last_string.count) to position;

	  (object.shortname != last_string).if {
	    syntax_error (current_position,"Incorrect name (filename != name).");
          };
	  (read_character '(').if {
	    //
	    // Generic loader.
            //
            param := { + res:ITM_TYPE_PARAMETER;
              (read_identifier).if {
                (read_character ':').if_false {
                  warning_error (current_position,"Added ':'.");
                };
                (read_type TRUE = NULL).if {
                  syntax_error (current_position,"Type needed.");
                };
                // BSBS: Warning: type::{INTEGER,CHARACTER,REAL,STRING_CONSTANT}
                semantic_error (current_position,"Sorry, not yet implemented.");
              }.elseif {read_cap_identifier} then {
                (is_parameter_type).if_false {
                  syntax_error (current_position,"Identifier parameter type is needed.");
                };
                short (ALIAS_STR.short_keyprototype) token
                (position - last_string.count) to position;
                res ?= ITM_TYPE_PARAMETER.get last_string;
              };
	      res
	    };

	    ((! is_shorter)    {! is_shorter2}).if {
              (object.generic_count = 0).if {
		syntax_error (current_position,"Object can't be generic.");
	      };
            };
            parameter_type := param.value;
            (parameter_type = NULL).if {
              syntax_error (current_position,"Identifier parameter type is needed.");
            };

	    object.idf_generic_list.add_last parameter_type;
	    {read_character ','}.while_do {
	      parameter_type := param.value;
	      (parameter_type = NULL).if {
                syntax_error (current_position,"Identifier parameter type is needed.");
              };
	      object.idf_generic_list.add_last parameter_type;
	    }; // loop

	    (! read_character ')').if {
	      warning_error (current_position,"Added ')'.");
	    };

	    ((! is_shorter)    {! is_shorter2}).if {
	      (object.idf_generic_list.count != object.generic_count).if {
		syntax_error (current_position,"Invalid generic list number.");
	      };
	    };
	  };
	} else {
	  syntax_error (current_position,"Slot `name' must to be first slot.");
	};
      }.elseif {
	(is_export := read_word (ALIAS_STR.slot_export)) ||
	{read_word (ALIAS_STR.slot_import)}
      } then {
	// - ("export"|"import") ':=' TYPE_LIST
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	cast := read_type_list FALSE;
	(cast = NULL).if {
	  syntax_error (current_position,"Incorrect type list.");
	};
	(is_export).if {
	  object.set_export_list cast;
	} else {
	  object.set_import_list cast;
	};
      }.elseif {read_word (ALIAS_STR.slot_external)} then {
	//
	// Read `external' slot.
	//

	// - "external" ':=' `<code_c>`
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	(read_external).if_false {
	  syntax_error (current_position,"Incorrect external.");
	};
	output_decl.append "/* ";
	output_decl.append (object.name);
	output_decl.append " */\n";
	output_decl.append last_string;
	output_decl.add_last '\n';
      }.elseif {read_word(ALIAS_STR.slot_default)} then {
	//
	// Read `default' slot.
	//

	// '-' "default" ':=' EXPR_PRIMARY
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	v := read_expr_primary;
	(v = NULL).if {
	  syntax_error (current_position,"Incorrect expr.");
	};
	(object.default_value != NULL).if {
	  semantic_error (current_position,"Double `default' slot definition.");
	};
	object.set_default_value v;
      }.elseif {read_word (ALIAS_STR.slot_type)} then {
	//
	// Read `type' slot.
	//

	// '-' "type" ':=' `<type C>`
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	(read_external).if_false {
	  syntax_error (current_position,"Incorrect external.");
	};
	(object.type_c != NULL).if {
	  semantic_error (current_position,"Double `type' slot definition.");
	};
	object.set_c_type last_string;
      }.elseif {read_word (ALIAS_STR.slot_version)} then {
	//
	// Read `version' slot.
	//

	// '-' "version" ':=' integer
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	(read_integer).if_false {
	  syntax_error (current_position,"Incorrect number.");
        };

      }.elseif {read_word (ALIAS_STR.slot_lip)} then {
	//
	// LIP interpreter.
	//

        // '-' lip <- ( { LIP_EXPR ';' } )
        (read_symbol (ALIAS_STR.symbol_affect_code)).if_false {
          warning_error (current_position,"Added '<-' is needed.");
        };
        (read_character '(').if_false {
          warning_error (current_position,"Added '(' is needed.");
        };
        {(instr := readlip_expr) != NULL}.while_do {
          ((! is_shorter)    {! is_shorter2}).if {
            instr.run;
          };
          (read_character ';').if_false {
            warning_error (current_position,"Added ';' is needed.");
          };
        };
        (read_character ')').if_false {
          warning_error (current_position,"Added ')' is needed.");
        };
      }.elseif {
	(read_word (ALIAS_STR.slot_date)) ||
	{read_word (ALIAS_STR.slot_comment)} ||
	{read_word (ALIAS_STR.slot_author)} ||
	{read_word (ALIAS_STR.slot_bibliography)} ||
	{read_word (ALIAS_STR.slot_language)} ||
	{read_word (ALIAS_STR.slot_copyright)} ||
	{read_word (ALIAS_STR.slot_bug_report)}
      } then {
	//
	// Read `date', `comment', `author', `bibliography',
	// `language', `copyright' or `bug_report' slots.
	//

	// '-' ("date"|"comment"|"author"|"bibliography"|"language"|"copyright"|"bug_report")
        // ':=' string
	short (ALIAS_STR.short_slot) token
	(position-last_string.count) to position;

	(read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	  warning_error (current_position,"Added ':='.");
	};
	(read_string).if_false {
	  syntax_error (current_position,"Incorrect string.");
        };
        (is_shorter2).if {
          object.set_comment_slot last_string;
        };
      } else {
	warning_error (current_position,"Incorrect slot.");
      };
      (read_character ';').if_false {
	warning_error (current_position,"Added ';'.");
      };
    };
    result
  );

  //
  // Parser for LIP file.
  //

  - readlip_program <-
  //// PROGRAM      -> { 'Section' ('Inherit' | 'Public' | 'Private') { SLOT ';' } }
  ( + idx:INTEGER;
    + section:STRING_CONSTANT;

    idx := LIP_CODE.list_parent.lower;
    {read_this_keyword (ALIAS_STR.keyword_section)}.while_do {
      (read_this_keyword (ALIAS_STR.section_inherit)).if {
        // { '+' string ':' STRING [ ':=' string ] ';' }
        {read_character '+'}.while_do {
          (read_identifier).if_false {
            warning_error (current_position,"Identifier needed.");
          };
          (read_character ':').if_false {
            warning_error (current_position,"Added ':' is needed.");
          };
          (read_word (ALIAS_STR.prototype_string)).if_false {
            warning_error (current_position,"`STRING' type needed.");
          };
          (read_symbol (ALIAS_STR.symbol_affect_immediate)).if {
            (read_string).if_false {
              syntax_error (current_position,"String needed.");
            };
            string_tmp.copy (object.filename);
            {
              (!string_tmp.is_empty)      
              {string_tmp.last != '/'}    
              {string_tmp.last != '\\'}
            }.while_do {
              string_tmp.remove_last 1;
            };
            string_tmp.append last_string;
          } else {
            string_tmp.clear;
          };
          LIP_CODE.list_parent.add (ALIAS_STR.get string_tmp) to idx;
          idx := idx + 1;
          (read_character ';').if_false {
            warning_error (current_position,"Added ';' is needed.");
          };
        };
      }.elseif {
        (read_this_keyword (ALIAS_STR.section_public))  ||
        {read_this_keyword (ALIAS_STR.section_private)}
      } then {
        section := last_string;
        {readlip_slot section}.while_do {
          (read_character ';').if_false {
            warning_error (current_position,"Added ';' is needed.");
          };
        };
      } else {
        syntax_error (current_position,"`Public' or `Private' or `Inherit' needed.");
      };
    };
  );

  - readlip_slot sec:STRING_CONSTANT :BOOLEAN <-
  //// SLOT         -> '+' identifier ':' TYPE [ ':=' EXPR_CONSTANT ]
  ////               | '-' identifier [ identifier ':' TYPE ] '<-' EXPR
  ( + result:BOOLEAN;
    + t:LIP_CONSTANT;
    + n,na:STRING_CONSTANT;
    + data:LIP_SLOT_DATA;
    + slot_code:LIP_SLOT_CODE;
    + exp:LIP_CODE;
    + pos:POSITION;
    + cst:LIP_CONSTANT;

    (read_character '+').if {
      // Data.
      result := TRUE;
      (sec = ALIAS_STR.section_public).if {
        syntax_error (current_position,"No data in Public section.");
      };
      (read_identifier).if_false {
        syntax_error (current_position,"Identifier is incorrect.");
      };
      n := last_string;
      (read_character ':').if_false {
        warning_error (current_position,"Added ':' is needed.");
      };
      t := readlip_type;
      (t = NULL).if {
        syntax_error (current_position,"type is incorrect.");
      };
      (! read_symbol (ALIAS_STR.symbol_affect_immediate)).if {
        data := LIP_SLOT_DATA.create current_position name n value t argument FALSE;
      } else {
        cst := readlip_expr_constant;
        (cst = NULL).if {
          syntax_error (current_position,"Incorrect expression.");
        };
        (cst.name !== t.name).if {
          syntax_error (current_position,"Incorrect expression type.");
        };
        data := LIP_SLOT_DATA.create current_position name n value cst argument FALSE;
        //data.set_value cst;
        //cst.free;
      };
    }.elseif {read_character '-'} then {
      // Function.
      result := TRUE;
      (read_identifier).if_false {
        syntax_error (current_position,"Identifier is incorrect.");
      };
      pos := current_position;
      n := last_string;
      (read_identifier).if {
        na := last_string;
        (read_character ':').if_false {
          warning_error (current_position,"Added ':' is needed.");
        };
        t := readlip_type;
        (t = NULL).if {
          syntax_error (current_position,"Incorrect type.");
        };
        data := LIP_SLOT_DATA.create current_position name na value t argument TRUE;
      };
      //
      (read_symbol (ALIAS_STR.symbol_affect_code)).if_false {
        warning_error (current_position,"Added '<-' is needed.");
      };
      is_shorter2 := TRUE;
      read_space;
      is_shorter2 := FALSE;
      exp := readlip_expr;
      (exp = NULL).if {
        syntax_error (current_position,"Expression needed.");
      };
      slot_code := LIP_SLOT_CODE.create pos section sec
      name n argument data code exp;
      (sec = ALIAS_STR.section_public).if {
        (last_comment_slot = NULL).if {
          warning_error (pos,"Comment needed.");
        } else {
          slot_code.set_comment (ALIAS_STR.get last_comment_slot);
        };
      };
    };
    result
  );

  - readlip_type:LIP_CONSTANT <-
  //// TYPE         -> 'BOOLEAN' | 'STRING' | 'INTEGER' | 'LIP'
  ( + result:LIP_CONSTANT;

    (read_cap_identifier).if {
      (last_string = ALIAS_STR.prototype_integer).if {
        result := LIP_INTEGER.get 0;
      }.elseif {last_string = ALIAS_STR.prototype_string} then {
        result := LIP_STRING.get (ALIAS_STR.get "");
      }.elseif {last_string = ALIAS_STR.prototype_boolean} then {
        result := LIP_BOOLEAN.get FALSE;
      }.elseif {last_string = ALIAS_STR.prototype_lip} then {
        not_yet_implemented;
      } else {
        syntax_error (current_position,"Incorrect type.");
      };
    };
    result
  );

  - readlip_expr_affect:LIP_CODE <-
  //// EXPR_AFFECT  -> [ identifier !!AMBIGU!! ':=' ] EXPR
  ( + result,val:LIP_CODE;
    + nam:STRING_CONSTANT;

    save_context; // !! SAVE CONTEXT !!

    (read_identifier).if {
      nam := last_string;
      (read_symbol (ALIAS_STR.symbol_affect_immediate)).if {
        val := readlip_expr;
        (val = NULL).if {
          syntax_error (current_position,"Incorrect expression.");
        };
        result := LIP_AFFECT.create current_position name nam value val;
      } else {
        restore_context; // !! RESTORE CONTEXT !!
      };
    };
    (result = NULL).if {
      result := readlip_expr;
    };
    result
  );

  - readlip_expr:LIP_CODE <-
  //// EXPR         -> EXPR_CMP { ('|' | ' ') EXPR_CMP }
  ( + result,right:LIP_CODE;
    + is_or:BOOLEAN;

    result := readlip_expr_cmp;
    (result != NULL).if {
      {(is_or := read_character '|') || {read_character ' '}}.while_do {
        right := readlip_expr_cmp;
        (right = NULL).if {
          syntax_error (current_position,"Incorrect expression.");
        };
        (is_or).if {
          result := LIP_BINARY.create current_position with result operator '|' and right;
        } else {
          result := LIP_BINARY.create current_position with result operator ' ' and right;
        };
      };
    };
    result
  );

  - readlip_expr_cmp:LIP_CODE <-
  //// EXPR_CMP     -> EXPR_BINARY { ('='|'!='|'>'|'<'|'>='|'<=') EXPR_BINARY }
  ( + result,right:LIP_CODE;
    + op:STRING_CONSTANT;
    + type:CHARACTER;

    result := readlip_expr_binary;
    (result != NULL).if {
      {
        (read_symbol (ALIAS_STR.symbol_great_equal)) ||
        {read_symbol (ALIAS_STR.symbol_less_equal)}  ||
        {read_symbol (ALIAS_STR.symbol_not_equal)}   ||
        {read_symbol (ALIAS_STR.symbol_equal)}       ||
        {read_symbol (ALIAS_STR.symbol_great)}       ||
        {read_symbol (ALIAS_STR.symbol_less)}
      }.while_do {
        op := last_string;
        right := readlip_expr_binary;
        (right = NULL).if {
          syntax_error (current_position,"Incorrect expression.");
        };
        (op)
        .when ">=" then { type := 'S'; }
        .when "<=" then { type := 'I'; }
        .when "!=" then { type := 'E'; }
        .when "="  then { type := '='; }
        .when ">"  then { type := '>'; }
        .when "<"  then { type := '<'; };
        result := LIP_BINARY.create current_position with result operator type and right;
      };
    };
    result
  );

  - readlip_expr_binary:LIP_CODE <-
  //// EXPR_BINARY  -> EXPR_UNARY { ('-'|'+') EXPR_UNARY }
  ( + result,right:LIP_CODE;
    + is_sub:BOOLEAN;

    result := readlip_expr_unary;
    (result != NULL).if {
      {(is_sub := read_character '-') || {read_character '+'}}.while_do {
        right := readlip_expr_unary;
        (right = NULL).if {
          syntax_error (current_position,"Incorrect expression.");
        };
        (is_sub).if {
          result := LIP_BINARY.create current_position with result operator '-' and right;
        } else {
          result := LIP_BINARY.create current_position with result operator '+' and right;
        };
      };
    };
    result
  );

  - readlip_expr_unary:LIP_CODE <-
  //// EXPR_UNARY   -> ( '-' | '!' ) EXPR_UNARY
  ////               | EXPR_BASE
  ( + result:LIP_CODE;
    + is_neg:BOOLEAN;
    + type:CHARACTER;

    ((is_neg := read_character '-') || {read_character '!'}).if {
      result := readlip_expr_unary;
      (result = NULL).if {
        syntax_error (current_position,"Incorrect expression.");
      };
      (is_neg).if {
        type := '-';
      } else {
        type := '!';
      };
      result := LIP_UNARY.create current_position operator type with result;
    } else {
      result := readlip_expr_base;
    };
    result
  );

  - readlip_expr_list cod:FAST_ARRAY(LIP_CODE) <-
  //// EXPR_LIST    -> { EXPR_AFFECT ';' } [ EXPR_AFFECT ]
  ( + instr:LIP_CODE;
    {
      ((instr := readlip_expr_affect) != NULL)   
      {read_character ';'}
    }.while_do {
      cod.add_last instr;
    };
    cod.add_last instr;
  );

  - readlip_expr_base:LIP_CODE <-
  //// EXPR_BASE    -> EXPR_RECEIVER { '.' EXPR_MESSAGE }
  ( + result:LIP_CODE;

    result := readlip_expr_receiver;
    {read_character '.'}.while_do {
      result := readlip_expr_message result;
      (result = NULL).if {
        syntax_error (current_position,"Incorrect message.");
      };
    };
    result
  );

  - readlip_expr_receiver:LIP_CODE <-
  //// EXPR_RECEIVER-> EXPR_PRIMARY
  ////               | EXPR_MESSAGE
  ( + result:LIP_CODE;
    result := readlip_expr_primary;
    (result = NULL).if {
      result := readlip_expr_message NULL;
    };
    result
  );

  - readlip_expr_message rec:LIP_CODE :LIP_CODE <-
  //// EXPR_MESSAGE -> identifier [ EXPR_ARGUMENT ]
  ////               | 'if' '{' EXPR_LIST '}' [ 'else' '{' EXPR_LIST '}' ]
  ( + result,arg:LIP_CODE;
    + nam:STRING_CONSTANT;
    + the,els:FAST_ARRAY(LIP_CODE);

    (read_word (ALIAS_STR.slot_if)).if {
      the := ALIAS_ARRAY(LIP_CODE).new;
      (read_character '{').if_false {
        warning_error (current_position,"Added '(' is needed.");
      };
      readlip_expr_list the;
      (read_character '}').if_false {
        warning_error (current_position,"Added '(' is needed.");
      };
      the := ALIAS_ARRAY(LIP_CODE).copy the;
      (read_word (ALIAS_STR.slot_else)).if {
        els := ALIAS_ARRAY(LIP_CODE).new;
        (read_character '{').if_false {
          warning_error (current_position,"Added '(' is needed.");
        };
        readlip_expr_list els;
        (read_character '}').if_false {
          warning_error (current_position,"Added '(' is needed.");
        };
        els := ALIAS_ARRAY(LIP_CODE).copy els;
      };
      result := LIP_IF.create current_position if rec then the else els;
    }.elseif {read_identifier} then {
      nam := last_string;
      arg := readlip_expr_argument;
      result := LIP_CALL.create current_position
      receiver rec name nam with arg;
    };
    result
  );

  - readlip_expr_argument:LIP_CODE <-
  //// EXPR_ARGUMENT-> identifier
  ////               | EXPR_PRIMARY
  ( + result:LIP_CODE;

    (read_identifier).if {
      result := LIP_CALL.create current_position
      receiver NULL name last_string with NULL;
    } else {
      result := readlip_expr_primary;
    };
    result
  );

  - readlip_expr_primary:LIP_CODE <-
  //// EXPR_PRIMARY -> EXPR_CONSTANT
  ////               | '(' EXPR_LIST ')'
  ( + result:LIP_CODE;
    + val:LIP_CONSTANT;
    + lst:FAST_ARRAY(LIP_CODE);

    val := readlip_expr_constant;
    (val != NULL).if {
      result := LIP_VALUE.create current_position with val;
    }.elseif {read_character '('} then {
      lst := ALIAS_ARRAY(LIP_CODE).new;
      readlip_expr_list lst;
      (read_character ')').if_false {
        warning_error (current_position,"Added ')'.");
      };
      lst := ALIAS_ARRAY(LIP_CODE).copy lst;
      result := LIP_LIST.create current_position with lst;
    };
    result
  );

  - readlip_expr_constant:LIP_CONSTANT <-
  //// EXPR_CONSTANT-> integer
  ////               | string
  ////               | TRUE
  ////               | FALSE
  ( + result:LIP_CONSTANT;

    (read_integer).if {
      result := LIP_INTEGER.get last_integer;
    }.elseif {read_string} then {
      result := LIP_STRING.get last_string;
    }.elseif {read_cap_identifier} then {
      (last_string = ALIAS_STR.prototype_true).if {
        result := LIP_BOOLEAN.get TRUE;
      }.elseif {last_string = ALIAS_STR.prototype_false} then {
        result := LIP_BOOLEAN.get FALSE;
      } else {
        syntax_error (current_position,"Type incorrect.");
      };
    };
    result
  );

  //
  // Parser for FORMAT.LI
  //

  //|| FORMAT -> { '-' identifier ':=' SHORT_DEF ';' }
  - read_format <-
  ( + def:LINKED_LIST(STRING_CONSTANT);

    {read_character '-'}.while_do {
      (read_identifier).if_false {
	syntax_error (current_position,"Incorrect slot identifier.");
      };
      def := LINKED_LIST(STRING_CONSTANT).create;
      (short_dico.fast_has last_string).if {
	syntax_error (current_position,"Double definition slot.");
      };
      short_dico.fast_put def to last_string;
      (read_symbol (ALIAS_STR.symbol_affect_immediate)).if_false {
	syntax_error (current_position,"Assignment ':=' is needed.");
      };
      (read_short_def def).if_false {
	syntax_error (current_position,"Incorrect definition.");
      };
      (read_character ';').if_false {
	warning_error (current_position,"Added ';' is needed.");
      };
    };

    // End of file :
    read_space;
    (last_character != 0.to_character).if {
      syntax_error (current_position,"Incorrect symbol.");
    };
  );

  //|| SHORT_DEF -> { SHORT_ELT '+' } SHORT_ELT
  - read_short_def def:LINKED_LIST(STRING_CONSTANT) :BOOLEAN <-
  ( + result:BOOLEAN;

    read_short_elt.if {
      result := TRUE;
      def.add_last last_string;
      {read_character '+'}.while_do {
	(read_short_elt).if_false {
	  syntax_error (current_position,"Incorrect format expression.");
	};
	def.add_last last_string;
      };
    };
    result
  );

  //|| SHORT_ELT -> "token" | string
  - read_short_elt:BOOLEAN <-
  ( + result:BOOLEAN;
    + j:INTEGER;

    read_identifier.if {
      (last_string != ALIAS_STR.short_token).if {
	warning_error (current_position,"Variable not `token'.");
      };
      last_string := NULL;
      result := TRUE;
    }.elseif {read_string} then {
      string_tmp.clear;
      j := last_string.lower;
      {j <= last_string.upper}.while_do {
	(last_string.item j = '\\').if {
	  j := j+1;
	  last_string.item j
	  .when 'a'  then { string_tmp.add_last '\a'; }
	  .when 'b'  then { string_tmp.add_last '\b'; }
	  .when 'f'  then { string_tmp.add_last '\f'; }
	  .when 'n'  then { string_tmp.add_last '\n'; }
	  .when 'r'  then { string_tmp.add_last '\r'; }
	  .when 't'  then { string_tmp.add_last '\t'; }
	  .when 'v'  then { string_tmp.add_last '\v'; }
	  .when '\\' then { string_tmp.add_last '\\'; }
	  .when '?'  then { string_tmp.add_last '\?'; }
	  .when '\'' then { string_tmp.add_last '\''; }
	  .when '\"' then { string_tmp.add_last '\"'; };
	} else {
	  string_tmp.add_last (last_string.item j);
	};
	j := j+1;
      };
      last_string := ALIAS_STR.get string_tmp;
      result := TRUE;
    };
    result
  );

Section Public

  //
  // Parser Entry.
  //

  //- counter_line:INTEGER;

  - go_on obj:PROTOTYPE <-
  (
    ? { object=NULL};

    // Source information.
    object   := obj;
    source   := obj.source;

    //counter_line := counter_line + source.occurrences '\n';

    position := source.lower;
    pos_cur  := source.lower;
    pos_line := 1;
    pos_col  := 0;

    (is_shorter).if {
      is_active_short := TRUE;
      short_derive := 0;
      output_code.copy source;
      short_local := HASHED_SET(STRING_CONSTANT).create;
      short (ALIAS_STR.short_begin) token 1 to 1;
    };

    // Parse.
    (! read_program).if {
      syntax_error (current_position,"Incorrect symbol.");
    };

    short (ALIAS_STR.short_end) token (source.upper) to (source.upper);

    object := NULL; // Parser is Free (see require test...)
  );

  - read_lip path_lip:STRING_CONSTANT :BOOLEAN <-
  ( + entry:POINTER;

    entry := FS_MIN.open_read path_lip;
    (entry != NULL).if {
      FS_MIN.close entry;
      object := PROTOTYPE.create path_lip
      name path_lip generic_count 0;

      source  := object.source;
      position := source.lower;
      pos_cur := source.lower;
      pos_line:=1;
      pos_col :=0;
      is_shorter := is_shorter2 := FALSE;

      // Parse.
      readlip_program;
      //
      is_shorter  := Old is_shorter;
      is_shorter2 := Old is_shorter2;
      object := NULL; // Parser is Free (see require test...)
    }
  );

  - parse_format fmt_name:STRING_CONSTANT <-
  (
    // Source information.
    (FILE_SYSTEM.get_entry fmt_name = NULL).if {
      STD_ERROR.put_string "Error: File format `";
      STD_ERROR.put_string fmt_name;
      STD_ERROR.put_string "' is not open !\n";
      die_with_code exit_failure_code;
    };

    object := PROTOTYPE.create fmt_name
    name (ALIAS_STR.short_format)
    generic_count 0;

    source   := object.source;
    position := source.lower;
    pos_cur  := source.lower;
    pos_line := 1;
    pos_col  := 0;

    // Parse.
    read_format;

    object := NULL; // Parser is Free (see require test...)
  );