aboutsummaryrefslogtreecommitdiff
path: root/source/main.elna
diff options
context:
space:
mode:
Diffstat (limited to 'source/main.elna')
-rw-r--r--source/main.elna218
1 files changed, 104 insertions, 114 deletions
diff --git a/source/main.elna b/source/main.elna
index dae045b..db5e76f 100644
--- a/source/main.elna
+++ b/source/main.elna
@@ -1,9 +1,8 @@
(* This Source Code Form is subject to the terms of the Mozilla Public License,
v. 2.0. If a copy of the MPL was not distributed with this file, You can
obtain one at https://mozilla.org/MPL/2.0/. *)
-program;
-import cstdio, cctype, common, command_line_interface, lexer;
+import cstdio, cstdlib, cstring, cctype, common, command_line_interface, lexer
type
SourceFile* = record
@@ -11,12 +10,12 @@ type
handle: ^FILE;
size: Word;
index: Word
- end;
+ end
StringBuffer* = record
data: Pointer;
size: Word;
capacity: Word
- end;
+ end
SourceCode = record
position: TextLocation;
@@ -24,7 +23,7 @@ type
empty: proc(Pointer) -> Bool;
advance: proc(Pointer);
head: proc(Pointer) -> Char
- end;
+ end
Token* = record
kind: LexerKind;
value: union
@@ -33,49 +32,49 @@ type
boolean_value: Bool;
char_value: Char
end
- end;
+ end
Tokenizer* = record
length: Word;
data: ^Token
- end;
+ end
(*
Standard procedures.
*)
-proc reallocarray(ptr: Pointer, n: Word, size: Word) -> Pointer;
+proc reallocarray(ptr: Pointer, n: Word, size: Word) -> Pointer
return realloc(ptr, n * size)
-end;
+end
-proc substring(string: String, start: Word, count: Word) -> String;
+proc substring(string: String, start: Word, count: Word) -> String
return String(string.ptr + start, count)
-end;
+end
-proc open_substring(string: String, start: Word) -> String;
+proc open_substring(string: String, start: Word) -> String
return substring(string, start, string.length - start)
-end;
+end
-proc string_dup(origin: String) -> String;
+proc string_dup(origin: String) -> String
var
- copy: ^Char;
+ copy: ^Char
begin
copy := cast(malloc(origin.length): ^Char);
strncpy(copy, origin.ptr, origin.length);
return String(copy, origin.length)
-end;
+end
-proc string_buffer_new() -> StringBuffer;
+proc string_buffer_new() -> StringBuffer
var
- result: StringBuffer;
+ result: StringBuffer
begin
result.capacity := 64u;
result.data := malloc(result.capacity);
result.size := 0u;
return result
-end;
+end
-proc string_buffer_push(buffer: ^StringBuffer, char: Char);
+proc string_buffer_push(buffer: ^StringBuffer, char: Char)
begin
if buffer^.size >= buffer^.capacity then
buffer^.capacity := buffer^.capacity + 1024u;
@@ -83,30 +82,30 @@ begin
end;
cast(buffer^.data + buffer^.size: ^Char)^ := cast(char: Char);
buffer^.size := buffer^.size + 1u
-end;
+end
-proc string_buffer_pop(buffer: ^StringBuffer, count: Word);
+proc string_buffer_pop(buffer: ^StringBuffer, count: Word)
begin
buffer^.size := buffer^.size - count
-end;
+end
-proc string_buffer_clear(buffer: ^StringBuffer) -> String;
+proc string_buffer_clear(buffer: ^StringBuffer) -> String
var
- result: String;
+ result: String
begin
result := String(cast(buffer^.data: ^Char), buffer^.size);
buffer^.size := 0u;
return result
-end;
+end
(*
Source code stream procedures.
*)
-proc read_source(filename: ^Char) -> ^SourceFile;
+proc read_source(filename: ^Char) -> ^SourceFile
var
- result: ^SourceFile;
- file_handle: ^FILE;
+ result: ^SourceFile
+ file_handle: ^FILE
begin
file_handle := fopen(filename, "rb\0".ptr);
@@ -117,11 +116,11 @@ begin
result^.index := 1u
end;
return result
-end;
+end
-proc source_file_empty(source_input: Pointer) -> Bool;
+proc source_file_empty(source_input: Pointer) -> Bool
var
- source_file: ^SourceFile;
+ source_file: ^SourceFile
begin
source_file := cast(source_input: ^SourceFile);
@@ -131,68 +130,62 @@ begin
end;
return source_file^.size = 0u
-end;
+end
-proc source_file_head(source_input: Pointer) -> Char;
+proc source_file_head(source_input: Pointer) -> Char
var
- source_file: ^SourceFile;
+ source_file: ^SourceFile
begin
source_file := cast(source_input: ^SourceFile);
return source_file^.buffer[source_file^.index]
-end;
+end
-proc source_file_advance(source_input: Pointer);
+proc source_file_advance(source_input: Pointer)
var
- source_file: ^SourceFile;
+ source_file: ^SourceFile
begin
source_file := cast(source_input: ^SourceFile);
source_file^.index := source_file^.index + 1u
-end;
+end
-proc source_code_empty(source_code: ^SourceCode) -> Bool;
+proc source_code_empty(source_code: ^SourceCode) -> Bool
return source_code^.empty(source_code^.input)
-end;
+end
-proc source_code_head(source_code: SourceCode) -> Char;
+proc source_code_head(source_code: SourceCode) -> Char
return source_code.head(source_code.input)
-end;
+end
-proc source_code_advance(source_code: ^SourceCode);
+proc source_code_advance(source_code: ^SourceCode)
begin
source_code^.advance(source_code^.input);
source_code^.position.column := source_code^.position.column
-end;
+end
-proc source_code_break(source_code: ^SourceCode);
+proc source_code_break(source_code: ^SourceCode)
begin
source_code^.position.line := source_code^.position.line + 1u;
source_code^.position.column := 0u
-end;
+end
-proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool;
+proc source_code_expect(source_code: ^SourceCode, expected: Char) -> Bool
return ~source_code_empty(source_code) & source_code_head(source_code^) = expected
-end;
+end
(*
Token procedures.
*)
-proc lexer_escape(escape: Char, result: ^Char) -> Bool;
+proc lexer_escape(escape: Char, result: ^Char) -> Bool
var
- successful: Bool;
+ successful: Bool
begin
case escape of
'n':
result^ := '\n';
successful := true
- | 'a':
- result^ := '\a';
- successful := true
- | 'b':
- result^ := '\b';
- successful := true
| 't':
result^ := '\t';
successful := true
@@ -214,9 +207,6 @@ begin
| '"':
result^ := '"';
successful := true
- | '?':
- result^ := '\?';
- successful := true
| '0':
result^ := '\0';
successful := true
@@ -224,12 +214,12 @@ begin
successful := false
end;
return successful
-end;
+end
(* Skip spaces. *)
-proc lexer_spaces(source_code: ^SourceCode);
+proc lexer_spaces(source_code: ^SourceCode)
var
- current: Char;
+ current: Char
begin
while ~source_code_empty(source_code) & isspace(cast(source_code_head(source_code^): Int)) <> 0 do
current := source_code_head(source_code^);
@@ -239,26 +229,26 @@ begin
end;
source_code_advance(source_code)
end
-end;
+end
(* Checker whether the character is allowed in an identificator. *)
-proc lexer_is_ident(char: Char) -> Bool;
+proc lexer_is_ident(char: Char) -> Bool
return isalnum(cast(char: Int)) <> 0 or char = '_'
-end;
+end
-proc lexer_identifier(source_code: ^SourceCode, token_content: ^StringBuffer);
+proc lexer_identifier(source_code: ^SourceCode, token_content: ^StringBuffer)
var
- content_length: Word;
+ content_length: Word
begin
while ~source_code_empty(source_code) & lexer_is_ident(source_code_head(source_code^)) do
string_buffer_push(token_content, source_code_head(source_code^));
source_code_advance(source_code)
end
-end;
+end
-proc lexer_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
+proc lexer_comment(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool
var
- trailing: Word;
+ trailing: Word
begin
trailing := 0u;
@@ -277,11 +267,11 @@ begin
end;
return trailing = 2u
-end;
+end
-proc lexer_character(source_code: ^SourceCode, token_content: ^Char) -> Bool;
+proc lexer_character(source_code: ^SourceCode, token_content: ^Char) -> Bool
var
- successful: Bool;
+ successful: Bool
begin
successful := ~source_code_empty(source_code);
@@ -299,14 +289,14 @@ begin
source_code_advance(source_code)
end;
return successful
-end;
+end
-proc lexer_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool;
+proc lexer_string(source_code: ^SourceCode, token_content: ^StringBuffer) -> Bool
var
- token_end, constructed_string: ^Char;
- token_length: Word;
- is_valid: Bool := true;
- next_char: Char;
+ token_end, constructed_string: ^Char
+ token_length: Word
+ is_valid: Bool := true
+ next_char: Char
begin
while is_valid & ~source_code_empty(source_code) & source_code_head(source_code^) <> '"' do
is_valid := lexer_character(source_code, @next_char);
@@ -322,9 +312,9 @@ begin
is_valid := false
end;
return is_valid
-end;
+end
-proc lexer_number(source_code: ^SourceCode, token_content: ^Int);
+proc lexer_number(source_code: ^SourceCode, token_content: ^Int)
begin
token_content^ := 0;
@@ -333,12 +323,12 @@ begin
source_code_advance(source_code)
end
-end;
+end
(* Categorize an identifier. *)
-proc lexer_categorize(token_content: String) -> Token;
+proc lexer_categorize(token_content: String) -> Token
var
- current_token: Token;
+ current_token: Token
begin
if token_content = "if" then
current_token.kind := LexerKind._if
@@ -402,23 +392,23 @@ begin
end;
return current_token
-end;
+end
-proc lexer_add_token(lexer: ^Tokenizer, token: Token);
+proc lexer_add_token(lexer: ^Tokenizer, token: Token)
var
- new_length: Word;
+ new_length: Word
begin
new_length := lexer^.length + 1u;
lexer^.data := cast(reallocarray(cast(lexer^.data: Pointer), new_length, #size(Token)): ^Token);
(lexer^.data + lexer^.length)^ := token;
lexer^.length := new_length
-end;
+end
(* Read the next token from the input. *)
-proc lexer_next(source_code: SourceCode, token_buffer: ^StringBuffer) -> Token;
+proc lexer_next(source_code: SourceCode, token_buffer: ^StringBuffer) -> Token
var
- current_token: Token;
- first_char: Char;
+ current_token: Token
+ first_char: Char
begin
current_token.kind := LexerKind.unknown;
@@ -587,14 +577,14 @@ begin
end;
return current_token
-end;
+end
(* Split the source text into tokens. *)
-proc lexer_text(source_code: SourceCode) -> Tokenizer;
+proc lexer_text(source_code: SourceCode) -> Tokenizer
var
- current_token: Token;
- token_buffer: StringBuffer;
- lexer: Tokenizer;
+ current_token: Token
+ token_buffer: StringBuffer
+ lexer: Tokenizer
begin
lexer := Tokenizer(0u, nil);
token_buffer := string_buffer_new();
@@ -615,16 +605,16 @@ begin
end;
return lexer
-end;
+end
(*
Parser.
*)
-proc parse(tokens: ^Token, tokens_size: Word);
+proc parse(tokens: ^Token, tokens_size: Word)
var
- current_token: ^Token;
- i: Word := 0u;
+ current_token: ^Token
+ i: Word := 0u
begin
while i < tokens_size do
current_token := tokens + i;
@@ -777,16 +767,16 @@ begin
i := i + 1u
end;
write_c('\n')
-end;
+end
(*
Compilation entry.
*)
-proc compile_in_stages(command_line: ^CommandLine, source_code: SourceCode) -> Int;
+proc compile_in_stages(command_line: ^CommandLine, source_code: SourceCode) -> Int
var
- return_code: Int := 0;
- lexer: Tokenizer;
+ return_code: Int := 0
+ lexer: Tokenizer
begin
if command_line^.lex or command_line^.parse then
lexer := lexer_text(source_code)
@@ -796,16 +786,16 @@ begin
end;
return return_code
-end;
+end
-proc process(argc: Int, argv: ^^Char) -> Int;
+proc process(argc: Int, argv: ^^Char) -> Int
var
- tokens: ^Token;
- tokens_size: Word;
- source_code: SourceCode;
- command_line: ^CommandLine;
- return_code: Int := 0;
- source_file: ^SourceFile;
+ tokens: ^Token
+ tokens_size: Word
+ source_code: SourceCode
+ command_line: ^CommandLine
+ return_code: Int := 0
+ source_file: ^SourceFile
begin
command_line := parse_command_line(argc, argv);
if command_line = nil then
@@ -835,7 +825,7 @@ begin
return_code := compile_in_stages(command_line, source_code)
end;
return return_code
-end;
+end
return process(count, parameters)
end.