diff options
Diffstat (limited to 'source/main.elna')
| -rw-r--r-- | source/main.elna | 209 |
1 files changed, 104 insertions, 105 deletions
diff --git a/source/main.elna b/source/main.elna index dae045b..e60f9ae 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,57 +130,57 @@ 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': @@ -224,12 +223,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 +238,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 +276,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 +298,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 +321,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 +332,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 +401,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 +586,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 +614,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 +776,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 +795,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 +834,7 @@ begin return_code := compile_in_stages(command_line, source_code) end; return return_code -end; +end return process(count, parameters) end. |
