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...)
);