Implement .max and .min type properties
This commit is contained in:
		| @@ -89,12 +89,6 @@ const                   { | |||||||
| var                     { | var                     { | ||||||
|                             return yy::parser::make_VAR(this->location); |                             return yy::parser::make_VAR(this->location); | ||||||
|                         } |                         } | ||||||
| array                   { |  | ||||||
|                             return yy::parser::make_ARRAY(this->location); |  | ||||||
|                         } |  | ||||||
| of                      { |  | ||||||
|                             return yy::parser::make_OF(this->location); |  | ||||||
|                         } |  | ||||||
| type                    { | type                    { | ||||||
|                             return yy::parser::make_TYPE(this->location); |                             return yy::parser::make_TYPE(this->location); | ||||||
|                         } |                         } | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ along with GCC; see the file COPYING3.  If not see | |||||||
| %token <std::string> STRING "string" | %token <std::string> STRING "string" | ||||||
| %token <bool> BOOLEAN | %token <bool> BOOLEAN | ||||||
| %token IF WHILE DO THEN ELSE ELSIF RETURN | %token IF WHILE DO THEN ELSE ELSIF RETURN | ||||||
| %token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO UNION | %token CONST VAR PROCEDURE TYPE RECORD POINTER TO UNION | ||||||
| %token BEGIN_BLOCK END_BLOCK EXTERN DEFER | %token BEGIN_BLOCK END_BLOCK EXTERN DEFER | ||||||
| %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA | %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA | ||||||
| %token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT | %token AND OR NOT CAST SHIFT_LEFT SHIFT_RIGHT | ||||||
| @@ -414,9 +414,9 @@ statement: | |||||||
|         } |         } | ||||||
|     | defer_statement { $$ = $1; } |     | defer_statement { $$ = $1; } | ||||||
| statements: | statements: | ||||||
|     statement SEMICOLON statements |     statement statements | ||||||
|         { |         { | ||||||
|             std::swap($$, $3); |             std::swap($$, $2); | ||||||
|             $$.emplace($$.cbegin(), $1); |             $$.emplace($$.cbegin(), $1); | ||||||
|         } |         } | ||||||
|     | statement { $$.push_back($1); } |     | statement { $$.push_back($1); } | ||||||
| @@ -433,7 +433,7 @@ field_list: | |||||||
|         } |         } | ||||||
|     | field_declaration { $$.emplace_back($1); } |     | field_declaration { $$.emplace_back($1); } | ||||||
| type_expression: | type_expression: | ||||||
|     ARRAY INTEGER OF type_expression |     LEFT_SQUARE INTEGER RIGHT_SQUARE type_expression | ||||||
|         { |         { | ||||||
|             $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2); |             $$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -952,6 +952,14 @@ namespace gcc | |||||||
|                 this->current_expression = build_int_cstu(elna_word_type_node, |                 this->current_expression = build_int_cstu(elna_word_type_node, | ||||||
|                         TYPE_ALIGN_UNIT(this->current_expression)); |                         TYPE_ALIGN_UNIT(this->current_expression)); | ||||||
|             } |             } | ||||||
|  |             else if (expression->field() == "min" && is_integral_type(this->current_expression)) | ||||||
|  |             { | ||||||
|  |                 this->current_expression = TYPE_MIN_VALUE(this->current_expression); | ||||||
|  |             } | ||||||
|  |             else if (expression->field() == "max" && is_integral_type(this->current_expression)) | ||||||
|  |             { | ||||||
|  |                 this->current_expression =  TYPE_MAX_VALUE(this->current_expression); | ||||||
|  |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 error_at(expression_location, "type '%s' does not have property '%s'", |                 error_at(expression_location, "type '%s' does not have property '%s'", | ||||||
|   | |||||||
							
								
								
									
										348
									
								
								source.elna
									
									
									
									
									
								
							
							
						
						
									
										348
									
								
								source.elna
									
									
									
									
									
								
							| @@ -174,22 +174,22 @@ proc write_i(value: Int); | |||||||
| var | var | ||||||
|   digit: Int |   digit: Int | ||||||
|   n: Word |   n: Word | ||||||
|   buffer: array 10 of Char |   buffer: [10]Char | ||||||
| begin | begin | ||||||
|   n := 10u; |   n := 10u | ||||||
|  |  | ||||||
|   if value = 0 then |   if value = 0 then | ||||||
|     write_c('0') |     write_c('0') | ||||||
|   end; |   end | ||||||
|   while value <> 0 do |   while value <> 0 do | ||||||
|     digit := value % 10; |     digit := value % 10 | ||||||
| 	value := value / 10; | 	value := value / 10 | ||||||
|  |  | ||||||
| 	buffer[n] := cast(cast('0': Int) + digit: Char); | 	buffer[n] := cast(cast('0': Int) + digit: Char) | ||||||
| 	n := n - 1u | 	n := n - 1u | ||||||
|   end; |   end | ||||||
|   while n < 10u do |   while n < 10u do | ||||||
|     n := n + 1u; |     n := n + 1u | ||||||
|     write_c(buffer[n]) |     write_c(buffer[n]) | ||||||
|   end |   end | ||||||
| end | end | ||||||
| @@ -233,8 +233,8 @@ proc string_dup(origin: String) -> String; | |||||||
| var | var | ||||||
|   copy: pointer to Char |   copy: pointer to Char | ||||||
| begin | begin | ||||||
|   copy := cast(malloc(origin.length): pointer to Char); |   copy := cast(malloc(origin.length): pointer to Char) | ||||||
|   strncpy(copy, origin.ptr, origin.length); |   strncpy(copy, origin.ptr, origin.length) | ||||||
|  |  | ||||||
|   return String(copy, origin.length) |   return String(copy, origin.length) | ||||||
| end | end | ||||||
| @@ -254,28 +254,28 @@ var | |||||||
|   source_size: Int |   source_size: Int | ||||||
|   input: pointer to Byte |   input: pointer to Byte | ||||||
| begin | begin | ||||||
|   input_file := fopen(filename, "rb\0".ptr); |   input_file := fopen(filename, "rb\0".ptr) | ||||||
|  |  | ||||||
|   if input_file = nil then |   if input_file = nil then | ||||||
|     return false |     return false | ||||||
|   end; |   end | ||||||
|   defer |   defer | ||||||
|     fclose(input_file) |     fclose(input_file) | ||||||
|   end; |   end | ||||||
|   if fseek(input_file, 0, SEEK_END) <> 0 then |   if fseek(input_file, 0, SEEK_END) <> 0 then | ||||||
|     return false |     return false | ||||||
|   end; |   end | ||||||
|   source_size := ftell(input_file); |   source_size := ftell(input_file) | ||||||
|   if source_size < 0 then |   if source_size < 0 then | ||||||
|     return false |     return false | ||||||
|   end; |   end | ||||||
|   rewind(input_file); |   rewind(input_file) | ||||||
|  |  | ||||||
|   input := malloc(cast(source_size: Word)); |   input := malloc(cast(source_size: Word)) | ||||||
|   if fread(input, cast(source_size: Word), 1u, input_file) <> 1u then |   if fread(input, cast(source_size: Word), 1u, input_file) <> 1u then | ||||||
|     return false |     return false | ||||||
|   end; |   end | ||||||
|   result^ := String(cast(input: pointer to Char), cast(source_size: Word)); |   result^ := String(cast(input: pointer to Char), cast(source_size: Word)) | ||||||
|  |  | ||||||
|   return true |   return true | ||||||
| end | end | ||||||
| @@ -283,40 +283,40 @@ end | |||||||
| proc escape_char(escape: Char, result: pointer to Char) -> Bool; | proc escape_char(escape: Char, result: pointer to Char) -> Bool; | ||||||
| begin | begin | ||||||
|   if escape = 'n' then |   if escape = 'n' then | ||||||
| 	result^ := '\n'; | 	result^ := '\n' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 'a' then |   elsif escape = 'a' then | ||||||
| 	result^ := '\a'; | 	result^ := '\a' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 'b' then |   elsif escape = 'b' then | ||||||
| 	result^ := '\b'; | 	result^ := '\b' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 't' then |   elsif escape = 't' then | ||||||
| 	result^ := '\t'; | 	result^ := '\t' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 'f' then |   elsif escape = 'f' then | ||||||
| 	result^ := '\f'; | 	result^ := '\f' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 'r' then |   elsif escape = 'r' then | ||||||
| 	result^ := '\r'; | 	result^ := '\r' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = 'v' then |   elsif escape = 'v' then | ||||||
| 	result^ := '\v'; | 	result^ := '\v' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = '\\' then |   elsif escape = '\\' then | ||||||
| 	result^ := '\\'; | 	result^ := '\\' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = '\'' then |   elsif escape = '\'' then | ||||||
| 	result^ := '\''; | 	result^ := '\'' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = '"' then |   elsif escape = '"' then | ||||||
| 	result^ := '"'; | 	result^ := '"' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = '?' then |   elsif escape = '?' then | ||||||
| 	result^ := '\?'; | 	result^ := '\?' | ||||||
| 	return true | 	return true | ||||||
|   elsif escape = '0' then |   elsif escape = '0' then | ||||||
| 	result^ := '\0'; | 	result^ := '\0' | ||||||
| 	return true | 	return true | ||||||
|   else |   else | ||||||
| 	return false | 	return false | ||||||
| @@ -325,8 +325,8 @@ end | |||||||
|  |  | ||||||
| proc advance_source(source_code: SourceCode, length: Word) -> SourceCode; | proc advance_source(source_code: SourceCode, length: Word) -> SourceCode; | ||||||
| begin | begin | ||||||
|   source_code.text := open_substring(source_code.text, length); |   source_code.text := open_substring(source_code.text, length) | ||||||
|   source_code.position.column := source_code.position.column + length; |   source_code.position.column := source_code.position.column + length | ||||||
|  |  | ||||||
|   return source_code |   return source_code | ||||||
| end | end | ||||||
| @@ -335,13 +335,13 @@ proc skip_spaces(source_code: SourceCode) -> SourceCode; | |||||||
| begin | begin | ||||||
|   while source_code.text.length > 0u and is_space(source_code.text[1u]) do |   while source_code.text.length > 0u and is_space(source_code.text[1u]) do | ||||||
|     if source_code.text[1u] = '\n' then |     if source_code.text[1u] = '\n' then | ||||||
|       source_code.position.line := source_code.position.line + 1u; |       source_code.position.line := source_code.position.line + 1u | ||||||
|       source_code.position.column := 1u |       source_code.position.column := 1u | ||||||
| 	else | 	else | ||||||
| 	  source_code.position.column := source_code.position.column + 1u | 	  source_code.position.column := source_code.position.column + 1u | ||||||
| 	end; | 	end | ||||||
|     source_code.text := open_substring(source_code.text, 1u) |     source_code.text := open_substring(source_code.text, 1u) | ||||||
|   end; |   end | ||||||
|   return source_code |   return source_code | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -349,13 +349,13 @@ proc lex_identifier(source_code: pointer to SourceCode, token_content: pointer t | |||||||
| var | var | ||||||
|   content_length: Word |   content_length: Word | ||||||
| begin | begin | ||||||
|   content_length := 0u; |   content_length := 0u | ||||||
|   token_content^ := source_code^.text; |   token_content^ := source_code^.text | ||||||
|  |  | ||||||
|   while is_alnum(source_code^.text[1u]) or source_code^.text[1u] = '_' do |   while is_alnum(source_code^.text[1u]) or source_code^.text[1u] = '_' do | ||||||
|     content_length := content_length + 1u; |     content_length := content_length + 1u | ||||||
| 	source_code^ := advance_source(source_code^, 1u) | 	source_code^ := advance_source(source_code^, 1u) | ||||||
|   end; |   end | ||||||
|   token_content^ := substring(token_content^, 0u, content_length) |   token_content^ := substring(token_content^, 0u, content_length) | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -363,19 +363,19 @@ proc lex_comment(source_code: pointer to SourceCode, token_content: pointer to S | |||||||
| var | var | ||||||
|   content_length: Word |   content_length: Word | ||||||
| begin | begin | ||||||
|   content_length := 0u; |   content_length := 0u | ||||||
|   token_content^ := source_code^.text; |   token_content^ := source_code^.text | ||||||
|  |  | ||||||
|   while source_code^.text.length > 1u do |   while source_code^.text.length > 1u do | ||||||
|     if source_code^.text[1u] = '*' and source_code^.text[2u] = ')' then |     if source_code^.text[1u] = '*' and source_code^.text[2u] = ')' then | ||||||
| 	  source_code^ := advance_source(source_code^, 2u); | 	  source_code^ := advance_source(source_code^, 2u) | ||||||
| 	  token_content^ := substring(token_content^, 0u, content_length); | 	  token_content^ := substring(token_content^, 0u, content_length) | ||||||
|  |  | ||||||
| 	  return true | 	  return true | ||||||
| 	end; | 	end | ||||||
|     content_length := content_length + 1u; |     content_length := content_length + 1u | ||||||
| 	source_code^ := advance_source(source_code^, 1u) | 	source_code^ := advance_source(source_code^, 1u) | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   return false |   return false | ||||||
| end | end | ||||||
| @@ -383,14 +383,14 @@ end | |||||||
| proc lex_character(input: pointer to Char, current_token: pointer to Token) -> pointer to Char; | proc lex_character(input: pointer to Char, current_token: pointer to Token) -> pointer to Char; | ||||||
| begin | begin | ||||||
|   if input^ = '\\' then |   if input^ = '\\' then | ||||||
|     input := input + 1; |     input := input + 1 | ||||||
| 	if escape_char(input^, @current_token^.value.char_value) then | 	if escape_char(input^, @current_token^.value.char_value) then | ||||||
| 	  input := input + 1 | 	  input := input + 1 | ||||||
| 	end | 	end | ||||||
|   elsif input^ <> '\0' then |   elsif input^ <> '\0' then | ||||||
|     current_token^.value.char_value := input^; |     current_token^.value.char_value := input^ | ||||||
| 	input := input + 1 | 	input := input + 1 | ||||||
|   end; |   end | ||||||
|   return input |   return input | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -400,35 +400,35 @@ var | |||||||
|   token_length: Word |   token_length: Word | ||||||
|   is_valid: Bool |   is_valid: Bool | ||||||
| begin | begin | ||||||
|   token_end := input; |   token_end := input | ||||||
|  |  | ||||||
|   while token_end^ <> '\0' and not ((token_end - 1)^ <> '\\' and token_end^ = '"') do |   while token_end^ <> '\0' and not ((token_end - 1)^ <> '\\' and token_end^ = '"') do | ||||||
|     token_end := token_end + 1 |     token_end := token_end + 1 | ||||||
|   end; |   end | ||||||
|   if token_end^ <> '\"' then |   if token_end^ <> '\"' then | ||||||
|     return input |     return input | ||||||
|   end; |   end | ||||||
|   token_length := cast(token_end - input: Word); |   token_length := cast(token_end - input: Word) | ||||||
|   current_token^.value.string_value := cast(calloc(token_length, 1u): pointer to Char); |   current_token^.value.string_value := cast(calloc(token_length, 1u): pointer to Char) | ||||||
|  |  | ||||||
|   is_valid := true; |   is_valid := true | ||||||
|   constructed_string := current_token^.value.string_value; |   constructed_string := current_token^.value.string_value | ||||||
|   while input < token_end and is_valid do |   while input < token_end and is_valid do | ||||||
|  |  | ||||||
|     if input^ = '\\' then |     if input^ = '\\' then | ||||||
|       input := input + 1; |       input := input + 1 | ||||||
|       if escape_char(input^, constructed_string) then |       if escape_char(input^, constructed_string) then | ||||||
|         input := input + 1 |         input := input + 1 | ||||||
| 	  else | 	  else | ||||||
| 	    is_valid := false | 	    is_valid := false | ||||||
|       end |       end | ||||||
|     elsif input^ <> '\0' then |     elsif input^ <> '\0' then | ||||||
|       constructed_string^ := input^; |       constructed_string^ := input^ | ||||||
|       input := input + 1 |       input := input + 1 | ||||||
|     end; |     end | ||||||
|  |  | ||||||
|     constructed_string := constructed_string + 1 |     constructed_string := constructed_string + 1 | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   return token_end |   return token_end | ||||||
| end | end | ||||||
| @@ -438,9 +438,9 @@ var | |||||||
|   current_token: pointer to Token |   current_token: pointer to Token | ||||||
|   i: Word |   i: Word | ||||||
| begin | begin | ||||||
|   i := 0u; |   i := 0u | ||||||
|   while i < tokens_size do |   while i < tokens_size do | ||||||
|     current_token := tokens + i; |     current_token := tokens + i | ||||||
|  |  | ||||||
|     if current_token^.kind = TOKEN_IF then |     if current_token^.kind = TOKEN_IF then | ||||||
| 	  write_s("IF") | 	  write_s("IF") | ||||||
| @@ -481,8 +481,8 @@ begin | |||||||
| 	elsif current_token^.kind = TOKEN_TO then | 	elsif current_token^.kind = TOKEN_TO then | ||||||
| 	  write_s("TO") | 	  write_s("TO") | ||||||
| 	elsif current_token^.kind = TOKEN_BOOLEAN then | 	elsif current_token^.kind = TOKEN_BOOLEAN then | ||||||
| 	  write_s("BOOLEAN<"); | 	  write_s("BOOLEAN<") | ||||||
| 	  write_b(current_token^.value.boolean_value); | 	  write_b(current_token^.value.boolean_value) | ||||||
| 	  write_c('>') | 	  write_c('>') | ||||||
| 	elsif current_token^.kind = TOKEN_NIL then | 	elsif current_token^.kind = TOKEN_NIL then | ||||||
| 	  write_s("NIL") | 	  write_s("NIL") | ||||||
| @@ -501,8 +501,8 @@ begin | |||||||
| 	elsif current_token^.kind = TOKEN_SHIFT_RIGHT then | 	elsif current_token^.kind = TOKEN_SHIFT_RIGHT then | ||||||
| 	  write_s(">>") | 	  write_s(">>") | ||||||
| 	elsif current_token^.kind = TOKEN_IDENTIFIER then | 	elsif current_token^.kind = TOKEN_IDENTIFIER then | ||||||
| 	  write_c('<'); | 	  write_c('<') | ||||||
|       write_s(current_token^.value.string); |       write_s(current_token^.value.string) | ||||||
| 	  write_c('>') | 	  write_c('>') | ||||||
| 	elsif current_token^.kind = TOKEN_LEFT_PAREN then | 	elsif current_token^.kind = TOKEN_LEFT_PAREN then | ||||||
| 	  write_s("(") | 	  write_s("(") | ||||||
| @@ -551,30 +551,30 @@ begin | |||||||
| 	elsif current_token^.kind = TOKEN_COMMENT then | 	elsif current_token^.kind = TOKEN_COMMENT then | ||||||
| 	  write_s("(* COMMENT *)") | 	  write_s("(* COMMENT *)") | ||||||
| 	elsif current_token^.kind = TOKEN_INTEGER then | 	elsif current_token^.kind = TOKEN_INTEGER then | ||||||
| 	  write_c('<'); | 	  write_c('<') | ||||||
|       write_i(current_token^.value.int_value); |       write_i(current_token^.value.int_value) | ||||||
| 	  write_c('>') | 	  write_c('>') | ||||||
| 	elsif current_token^.kind = TOKEN_WORD then | 	elsif current_token^.kind = TOKEN_WORD then | ||||||
| 	  write_c('<'); | 	  write_c('<') | ||||||
|       write_i(current_token^.value.int_value); |       write_i(current_token^.value.int_value) | ||||||
| 	  write_s("u>") | 	  write_s("u>") | ||||||
| 	elsif current_token^.kind = TOKEN_CHARACTER then | 	elsif current_token^.kind = TOKEN_CHARACTER then | ||||||
| 	  write_c('<'); | 	  write_c('<') | ||||||
|       write_i(cast(current_token^.value.char_value: Int)); |       write_i(cast(current_token^.value.char_value: Int)) | ||||||
| 	  write_s("c>") | 	  write_s("c>") | ||||||
| 	elsif current_token^.kind = TOKEN_STRING then | 	elsif current_token^.kind = TOKEN_STRING then | ||||||
| 	  write_s("\"...\"") | 	  write_s("\"...\"") | ||||||
| 	elsif current_token^.kind = TOKEN_DEFER then | 	elsif current_token^.kind = TOKEN_DEFER then | ||||||
| 	  write_s("DEFER") | 	  write_s("DEFER") | ||||||
| 	else | 	else | ||||||
| 	  write_s("UNKNOWN<"); | 	  write_s("UNKNOWN<") | ||||||
| 	  write_i(current_token^.kind); | 	  write_i(current_token^.kind) | ||||||
| 	  write_c('>') | 	  write_c('>') | ||||||
| 	end; | 	end | ||||||
| 	write_c(' '); | 	write_c(' ') | ||||||
|  |  | ||||||
| 	i := i + 1u | 	i := i + 1u | ||||||
|   end; |   end | ||||||
|   write_c('\n') |   write_c('\n') | ||||||
| end | end | ||||||
|  |  | ||||||
| @@ -621,10 +621,10 @@ begin | |||||||
|   elsif "to" = token_content then |   elsif "to" = token_content then | ||||||
| 	current_token.kind := TOKEN_TO | 	current_token.kind := TOKEN_TO | ||||||
|   elsif "true" = token_content then |   elsif "true" = token_content then | ||||||
| 	current_token.kind := TOKEN_BOOLEAN; | 	current_token.kind := TOKEN_BOOLEAN | ||||||
| 	current_token.value.boolean_value := true | 	current_token.value.boolean_value := true | ||||||
|   elsif "false" = token_content then |   elsif "false" = token_content then | ||||||
| 	current_token.kind := TOKEN_BOOLEAN; | 	current_token.kind := TOKEN_BOOLEAN | ||||||
| 	current_token.value.boolean_value := false | 	current_token.value.boolean_value := false | ||||||
|   elsif "nil" = token_content then |   elsif "nil" = token_content then | ||||||
| 	current_token.kind := TOKEN_NIL | 	current_token.kind := TOKEN_NIL | ||||||
| @@ -641,9 +641,9 @@ begin | |||||||
|   elsif "defer" = token_content then |   elsif "defer" = token_content then | ||||||
| 	current_token.kind := TOKEN_DEFER | 	current_token.kind := TOKEN_DEFER | ||||||
|   else |   else | ||||||
| 	current_token.kind := TOKEN_IDENTIFIER; | 	current_token.kind := TOKEN_IDENTIFIER | ||||||
| 	current_token.value.string := string_dup(token_content) | 	current_token.value.string := string_dup(token_content) | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   return current_token |   return current_token | ||||||
| end | end | ||||||
| @@ -656,40 +656,40 @@ var | |||||||
|   first_char: Char |   first_char: Char | ||||||
|   token_content: String |   token_content: String | ||||||
| begin | begin | ||||||
|   tokens_size^ := 0u; |   tokens_size^ := 0u | ||||||
|   tokens := nil; |   tokens := nil | ||||||
|   source_code := skip_spaces(source_code); |   source_code := skip_spaces(source_code) | ||||||
|  |  | ||||||
|   while source_code.text.length <> 0u do |   while source_code.text.length <> 0u do | ||||||
| 	tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, Token.size): pointer to Token); | 	tokens := cast(reallocarray(cast(tokens: pointer to Byte), tokens_size^ + 1u, Token.size): pointer to Token) | ||||||
|     current_token := tokens + tokens_size^; |     current_token := tokens + tokens_size^ | ||||||
| 	first_char := source_code.text[1u]; | 	first_char := source_code.text[1u] | ||||||
|  |  | ||||||
|     if is_alpha(first_char) or first_char = '_' then |     if is_alpha(first_char) or first_char = '_' then | ||||||
|       lex_identifier(@source_code, @token_content); |       lex_identifier(@source_code, @token_content) | ||||||
|       current_token^ := categorize_identifier(token_content) |       current_token^ := categorize_identifier(token_content) | ||||||
| 	elsif is_digit(first_char) then | 	elsif is_digit(first_char) then | ||||||
| 	  token_end := nil; | 	  token_end := nil | ||||||
| 	  current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10); | 	  current_token^.value.int_value := strtol(source_code.text.ptr, @token_end, 10) | ||||||
| 	  token_length := cast(token_end - source_code.text.ptr: Word); | 	  token_length := cast(token_end - source_code.text.ptr: Word) | ||||||
|  |  | ||||||
| 	  if token_end^ = 'u' then | 	  if token_end^ = 'u' then | ||||||
| 	    current_token^.kind := TOKEN_WORD; | 	    current_token^.kind := TOKEN_WORD | ||||||
|         source_code := advance_source(source_code, token_length + 1u) |         source_code := advance_source(source_code, token_length + 1u) | ||||||
| 	  else | 	  else | ||||||
| 	    current_token^.kind := TOKEN_INTEGER; | 	    current_token^.kind := TOKEN_INTEGER | ||||||
|         source_code := advance_source(source_code, token_length) |         source_code := advance_source(source_code, token_length) | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '(' then | 	elsif first_char = '(' then | ||||||
| 	  source_code := advance_source(source_code, 1u); | 	  source_code := advance_source(source_code, 1u) | ||||||
|  |  | ||||||
| 	  if source_code.text.length = 0u then | 	  if source_code.text.length = 0u then | ||||||
| 	    current_token^.kind := TOKEN_LEFT_PAREN | 	    current_token^.kind := TOKEN_LEFT_PAREN | ||||||
| 	  elsif source_code.text[1u] = '*' then | 	  elsif source_code.text[1u] = '*' then | ||||||
| 	    source_code := advance_source(source_code, 1u); | 	    source_code := advance_source(source_code, 1u) | ||||||
|  |  | ||||||
| 		if lex_comment(@source_code, @token_content) then | 		if lex_comment(@source_code, @token_content) then | ||||||
| 	      current_token^.value.string := string_dup(token_content); | 	      current_token^.value.string := string_dup(token_content) | ||||||
| 		  current_token^.kind := TOKEN_COMMENT | 		  current_token^.kind := TOKEN_COMMENT | ||||||
| 		else | 		else | ||||||
| 	      current_token^.kind := 0 | 	      current_token^.kind := 0 | ||||||
| @@ -698,121 +698,121 @@ begin | |||||||
| 	    current_token^.kind := TOKEN_LEFT_PAREN | 	    current_token^.kind := TOKEN_LEFT_PAREN | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = ')' then | 	elsif first_char = ')' then | ||||||
| 	  current_token^.kind := TOKEN_RIGHT_PAREN; | 	  current_token^.kind := TOKEN_RIGHT_PAREN | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '\'' then | 	elsif first_char = '\'' then | ||||||
| 	  token_end := lex_character(source_code.text.ptr + 1, current_token); | 	  token_end := lex_character(source_code.text.ptr + 1, current_token) | ||||||
| 	  token_length := cast(token_end - source_code.text.ptr: Word); | 	  token_length := cast(token_end - source_code.text.ptr: Word) | ||||||
|  |  | ||||||
| 	  if token_end^ = '\'' then | 	  if token_end^ = '\'' then | ||||||
| 	  	current_token^.kind := TOKEN_CHARACTER; | 	  	current_token^.kind := TOKEN_CHARACTER | ||||||
| 	    source_code := advance_source(source_code, token_length + 1u) | 	    source_code := advance_source(source_code, token_length + 1u) | ||||||
| 	  else | 	  else | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '"' then | 	elsif first_char = '"' then | ||||||
| 	  token_end := lex_string(source_code.text.ptr + 1, current_token); | 	  token_end := lex_string(source_code.text.ptr + 1, current_token) | ||||||
|  |  | ||||||
|       if token_end^ = '"' then |       if token_end^ = '"' then | ||||||
| 		current_token^.kind := TOKEN_STRING; | 		current_token^.kind := TOKEN_STRING | ||||||
| 	    token_length := cast(token_end - source_code.text.ptr: Word); | 	    token_length := cast(token_end - source_code.text.ptr: Word) | ||||||
| 	    source_code := advance_source(source_code, token_length + 1u) | 	    source_code := advance_source(source_code, token_length + 1u) | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '[' then | 	elsif first_char = '[' then | ||||||
| 	  current_token^.kind := TOKEN_LEFT_SQUARE; | 	  current_token^.kind := TOKEN_LEFT_SQUARE | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = ']' then | 	elsif first_char = ']' then | ||||||
| 	  current_token^.kind := TOKEN_RIGHT_SQUARE; | 	  current_token^.kind := TOKEN_RIGHT_SQUARE | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '>' then | 	elsif first_char = '>' then | ||||||
| 	  source_code := advance_source(source_code, 1u); | 	  source_code := advance_source(source_code, 1u) | ||||||
|  |  | ||||||
|       if source_code.text.length = 0u then |       if source_code.text.length = 0u then | ||||||
| 	    current_token^.kind := TOKEN_GREATER_THAN | 	    current_token^.kind := TOKEN_GREATER_THAN | ||||||
| 	  elsif source_code.text[1u] = '=' then | 	  elsif source_code.text[1u] = '=' then | ||||||
| 	    current_token^.kind := TOKEN_GREATER_EQUAL; | 	    current_token^.kind := TOKEN_GREATER_EQUAL | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  elsif source_code.text[1u] = '>' then | 	  elsif source_code.text[1u] = '>' then | ||||||
| 	    current_token^.kind := TOKEN_SHIFT_RIGHT; | 	    current_token^.kind := TOKEN_SHIFT_RIGHT | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  else | 	  else | ||||||
| 	    current_token^.kind := TOKEN_GREATER_THAN | 	    current_token^.kind := TOKEN_GREATER_THAN | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '<' then | 	elsif first_char = '<' then | ||||||
| 	  source_code := advance_source(source_code, 1u); | 	  source_code := advance_source(source_code, 1u) | ||||||
|  |  | ||||||
| 	  if source_code.text.length = 0u then | 	  if source_code.text.length = 0u then | ||||||
| 	    current_token^.kind := TOKEN_LESS_THAN | 	    current_token^.kind := TOKEN_LESS_THAN | ||||||
| 	  elsif source_code.text[1u] = '=' then | 	  elsif source_code.text[1u] = '=' then | ||||||
| 	    current_token^.kind := TOKEN_LESS_EQUAL; | 	    current_token^.kind := TOKEN_LESS_EQUAL | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  elsif source_code.text[1u] = '<' then | 	  elsif source_code.text[1u] = '<' then | ||||||
| 	    current_token^.kind := TOKEN_SHIFT_LEFT; | 	    current_token^.kind := TOKEN_SHIFT_LEFT | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  elsif source_code.text[1u] = '>' then | 	  elsif source_code.text[1u] = '>' then | ||||||
| 	    current_token^.kind := TOKEN_NOT_EQUAL; | 	    current_token^.kind := TOKEN_NOT_EQUAL | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  else | 	  else | ||||||
| 	    current_token^.kind := TOKEN_LESS_THAN | 	    current_token^.kind := TOKEN_LESS_THAN | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '=' then | 	elsif first_char = '=' then | ||||||
| 	  current_token^.kind := TOKEN_EQUAL; | 	  current_token^.kind := TOKEN_EQUAL | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = ';' then | 	elsif first_char = ';' then | ||||||
| 	  current_token^.kind := TOKEN_SEMICOLON; | 	  current_token^.kind := TOKEN_SEMICOLON | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '.' then | 	elsif first_char = '.' then | ||||||
| 	  current_token^.kind := TOKEN_DOT; | 	  current_token^.kind := TOKEN_DOT | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = ',' then | 	elsif first_char = ',' then | ||||||
| 	  current_token^.kind := TOKEN_COMMA; | 	  current_token^.kind := TOKEN_COMMA | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '+' then | 	elsif first_char = '+' then | ||||||
| 	  current_token^.kind := TOKEN_PLUS; | 	  current_token^.kind := TOKEN_PLUS | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '-' then | 	elsif first_char = '-' then | ||||||
| 	  current_token^.kind := TOKEN_MINUS; | 	  current_token^.kind := TOKEN_MINUS | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '*' then | 	elsif first_char = '*' then | ||||||
| 	  current_token^.kind := TOKEN_MULTIPLICATION; | 	  current_token^.kind := TOKEN_MULTIPLICATION | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '/' then | 	elsif first_char = '/' then | ||||||
| 	  current_token^.kind := TOKEN_DIVISION; | 	  current_token^.kind := TOKEN_DIVISION | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '%' then | 	elsif first_char = '%' then | ||||||
| 	  current_token^.kind := TOKEN_REMAINDER; | 	  current_token^.kind := TOKEN_REMAINDER | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = ':' then | 	elsif first_char = ':' then | ||||||
| 	  source_code := advance_source(source_code, 1u); | 	  source_code := advance_source(source_code, 1u) | ||||||
|  |  | ||||||
| 	  if source_code.text.length = 0u then | 	  if source_code.text.length = 0u then | ||||||
| 	    current_token^.kind := TOKEN_COLON | 	    current_token^.kind := TOKEN_COLON | ||||||
| 	  elsif source_code.text[1u] = '=' then | 	  elsif source_code.text[1u] = '=' then | ||||||
| 	    current_token^.kind := TOKEN_ASSIGNMENT; | 	    current_token^.kind := TOKEN_ASSIGNMENT | ||||||
| 	    source_code := advance_source(source_code, 1u) | 	    source_code := advance_source(source_code, 1u) | ||||||
| 	  else | 	  else | ||||||
| 	    current_token^.kind := TOKEN_COLON | 	    current_token^.kind := TOKEN_COLON | ||||||
| 	  end | 	  end | ||||||
| 	elsif first_char = '^' then | 	elsif first_char = '^' then | ||||||
| 	  current_token^.kind := TOKEN_HAT; | 	  current_token^.kind := TOKEN_HAT | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	elsif first_char = '@' then | 	elsif first_char = '@' then | ||||||
| 	  current_token^.kind := TOKEN_AT; | 	  current_token^.kind := TOKEN_AT | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	else | 	else | ||||||
| 	  current_token^.kind := 0; | 	  current_token^.kind := 0 | ||||||
| 	  source_code := advance_source(source_code, 1u) | 	  source_code := advance_source(source_code, 1u) | ||||||
| 	end; | 	end | ||||||
|  |  | ||||||
| 	if current_token^.kind <> 0 then | 	if current_token^.kind <> 0 then | ||||||
|       tokens_size^ := tokens_size^ + 1u; |       tokens_size^ := tokens_size^ + 1u | ||||||
|       source_code := skip_spaces(source_code) |       source_code := skip_spaces(source_code) | ||||||
| 	else | 	else | ||||||
| 	  write_s("Lexical analysis error on \""); | 	  write_s("Lexical analysis error on \"") | ||||||
| 	  write_c(first_char); | 	  write_c(first_char) | ||||||
| 	  write_s("\".\n") | 	  write_s("\".\n") | ||||||
| 	end | 	end | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   return tokens |   return tokens | ||||||
| end | end | ||||||
| @@ -827,21 +827,21 @@ proc parse_constant_definition(tokens: pointer to pointer to Token, | |||||||
| var | var | ||||||
|   result: pointer to ConstantDefinition |   result: pointer to ConstantDefinition | ||||||
| begin | begin | ||||||
|   result := cast(calloc(1u, ConstantDefinition.size): pointer to ConstantDefinition); |   result := cast(calloc(1u, ConstantDefinition.size): pointer to ConstantDefinition) | ||||||
|  |  | ||||||
|   result^.name := cast(malloc(strlen(tokens^^.value.string_value)): pointer to Char); |   result^.name := cast(malloc(strlen(tokens^^.value.string_value)): pointer to Char) | ||||||
|   strcpy(result^.name, tokens^^.value.string_value); |   strcpy(result^.name, tokens^^.value.string_value) | ||||||
|  |  | ||||||
|   tokens^ := tokens^ + 2u; |   tokens^ := tokens^ + 2u | ||||||
|   tokens_size := tokens_size - 2u; |   tokens_size := tokens_size - 2u | ||||||
|  |  | ||||||
|   write_z(result^.name); |   write_z(result^.name) | ||||||
|   write_c('\n'); |   write_c('\n') | ||||||
|  |  | ||||||
|   result^.body := parse_literal(tokens, tokens_size); |   result^.body := parse_literal(tokens, tokens_size) | ||||||
|  |  | ||||||
|   tokens^ := tokens^ + 2u; |   tokens^ := tokens^ + 2u | ||||||
|   tokens_size := tokens_size - 2u; |   tokens_size := tokens_size - 2u | ||||||
|  |  | ||||||
|   return result |   return result | ||||||
| end | end | ||||||
| @@ -851,14 +851,14 @@ var | |||||||
|   result: pointer to Program |   result: pointer to Program | ||||||
|   current_constant: pointer to pointer to ConstantDefinition |   current_constant: pointer to pointer to ConstantDefinition | ||||||
| begin | begin | ||||||
|   result := cast(calloc(1u, Program.size): pointer to Program); |   result := cast(calloc(1u, Program.size): pointer to Program) | ||||||
|  |  | ||||||
|   result^.constants.elements := nil; |   result^.constants.elements := nil | ||||||
|   result^.constants.count := 0u; |   result^.constants.count := 0u | ||||||
|  |  | ||||||
|   if tokens^^.kind = TOKEN_CONST then |   if tokens^^.kind = TOKEN_CONST then | ||||||
|     tokens^ := tokens^ + 1; |     tokens^ := tokens^ + 1 | ||||||
| 	tokens_size^ := tokens_size^ - 1u; | 	tokens_size^ := tokens_size^ - 1u | ||||||
|  |  | ||||||
| 	while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do | 	while tokens_size^ > 0u and tokens^^.kind = TOKEN_IDENTIFIER do | ||||||
| 	  result^.constants.elements := cast( | 	  result^.constants.elements := cast( | ||||||
| @@ -866,12 +866,12 @@ begin | |||||||
| 		  	cast(result^.constants.elements: pointer to Byte), | 		  	cast(result^.constants.elements: pointer to Byte), | ||||||
| 			result^.constants.count + 1u, | 			result^.constants.count + 1u, | ||||||
| 			(pointer to ConstantDefinition).size | 			(pointer to ConstantDefinition).size | ||||||
| 		  ) : pointer to pointer to ConstantDefinition); | 		  ) : pointer to pointer to ConstantDefinition) | ||||||
|       current_constant := result^.constants.elements + result^.constants.count; |       current_constant := result^.constants.elements + result^.constants.count | ||||||
|  |  | ||||||
| 	  result^.constants.count := result^.constants.count + 1u; | 	  result^.constants.count := result^.constants.count + 1u | ||||||
|  |  | ||||||
| 	  current_constant^ := parse_constant_definition(tokens, tokens_size); | 	  current_constant^ := parse_constant_definition(tokens, tokens_size) | ||||||
| 	  if current_constant^ = nil then | 	  if current_constant^ = nil then | ||||||
| 	    return nil | 	    return nil | ||||||
| 	  end | 	  end | ||||||
| @@ -885,14 +885,14 @@ var | |||||||
|   i: Int |   i: Int | ||||||
|   result: pointer to CommandLine |   result: pointer to CommandLine | ||||||
| begin | begin | ||||||
|   i := 1; |   i := 1 | ||||||
|   result := cast(malloc(CommandLine.size): pointer to CommandLine); |   result := cast(malloc(CommandLine.size): pointer to CommandLine) | ||||||
|   result^.tokenize := false; |   result^.tokenize := false | ||||||
|   result^.syntax_tree := false; |   result^.syntax_tree := false | ||||||
|   result^.input := nil; |   result^.input := nil | ||||||
|  |  | ||||||
|   while i < argc do |   while i < argc do | ||||||
|     parameter := argv + i; |     parameter := argv + i | ||||||
|  |  | ||||||
|     if strcmp(parameter^, "--tokenize\0".ptr) = 0 then |     if strcmp(parameter^, "--tokenize\0".ptr) = 0 then | ||||||
|       result^.tokenize := true |       result^.tokenize := true | ||||||
| @@ -901,21 +901,21 @@ begin | |||||||
|     elsif parameter^^ <> '-' then |     elsif parameter^^ <> '-' then | ||||||
|       result^.input := parameter^ |       result^.input := parameter^ | ||||||
|     else |     else | ||||||
|       write_s("Fatal error: Unknown command line options:"); |       write_s("Fatal error: Unknown command line options:") | ||||||
|  |  | ||||||
|       write_c(' '); |       write_c(' ') | ||||||
|       write_z(parameter^); |       write_z(parameter^) | ||||||
|       write_s(".\n"); |       write_s(".\n") | ||||||
|  |  | ||||||
|       return nil |       return nil | ||||||
|     end; |     end | ||||||
|  |  | ||||||
|     i := i + 1 |     i := i + 1 | ||||||
|   end; |   end | ||||||
|   if result^.input = nil then |   if result^.input = nil then | ||||||
|     write_s("Fatal error: no input files.\n"); |     write_s("Fatal error: no input files.\n") | ||||||
| 	return nil | 	return nil | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   return result |   return result | ||||||
| end | end | ||||||
| @@ -927,24 +927,24 @@ var | |||||||
|   source_code: SourceCode |   source_code: SourceCode | ||||||
|   command_line: pointer to CommandLine |   command_line: pointer to CommandLine | ||||||
| begin | begin | ||||||
|   command_line := parse_command_line(argc, argv); |   command_line := parse_command_line(argc, argv) | ||||||
|   if command_line = nil then |   if command_line = nil then | ||||||
|     return 2 |     return 2 | ||||||
|   end; |   end | ||||||
|  |  | ||||||
|   source_code.position := make_position(); |   source_code.position := make_position() | ||||||
|   if not read_source(command_line^.input, @source_code.text) then |   if not read_source(command_line^.input, @source_code.text) then | ||||||
|     perror(command_line^.input); |     perror(command_line^.input) | ||||||
| 	return 3 | 	return 3 | ||||||
|   end; |   end | ||||||
|   tokens := tokenize(source_code, @tokens_size); |   tokens := tokenize(source_code, @tokens_size) | ||||||
|  |  | ||||||
|   if command_line^.tokenize then |   if command_line^.tokenize then | ||||||
|     print_tokens(tokens, tokens_size) |     print_tokens(tokens, tokens_size) | ||||||
|   end; |   end | ||||||
|   if command_line^.syntax_tree then |   if command_line^.syntax_tree then | ||||||
|     parse_program(@tokens, @tokens_size) |     parse_program(@tokens, @tokens_size) | ||||||
|   end; |   end | ||||||
|   return 0 |   return 0 | ||||||
| end | end | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user