diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-12 13:23:54 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-12 13:23:54 +0200 |
| commit | 768537d6e4b82a19e77b7e44234309ecaf4d65d2 (patch) | |
| tree | ab22613a16c3a914b16d00a5f988f51d1eadac0d /source/main.elna | |
| parent | 14d4977e2ab2409bb7344395ca01d19e49f130f1 (diff) | |
| download | elna-768537d6e4b82a19e77b7e44234309ecaf4d65d2.tar.gz | |
Remove unions
Diffstat (limited to 'source/main.elna')
| -rw-r--r-- | source/main.elna | 400 |
1 files changed, 205 insertions, 195 deletions
diff --git a/source/main.elna b/source/main.elna index aeaba2f..781d681 100644 --- a/source/main.elna +++ b/source/main.elna @@ -24,18 +24,9 @@ type advance: proc(stream: Pointer); head: proc(stream: Pointer): Char end - Token* = record - kind: LexerKind; - value: union - int_value: Int; - string: String; - boolean_value: Bool; - char_value: Char - end - end Tokenizer* = record length: Word; - data: ^Token + data: ^^ElnaLexerToken end (* @@ -57,7 +48,7 @@ proc string_dup(origin: String): String var copy: ^Char begin - copy := cast(malloc(origin.length): ^Char); + copy := malloc(origin.length); strncpy(copy, origin.ptr, origin.length); return String(copy, origin.length) @@ -326,92 +317,109 @@ begin end (* Categorize an identifier. *) -proc lexer_categorize(token_content: String): Token +proc lexer_categorize(token_content: String): ^ElnaLexerToken var - current_token: Token + current_token: ^ElnaLexerToken begin if token_content = "if" then - current_token.kind := LexerKind._if + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._if elsif token_content = "then" then - current_token.kind := LexerKind._then + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._then elsif token_content = "else" then - current_token.kind := LexerKind._else + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._else elsif token_content = "elsif" then - current_token.kind := LexerKind._elsif + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._elsif elsif token_content = "while" then - current_token.kind := LexerKind._while + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._while elsif token_content = "do" then - current_token.kind := LexerKind._do + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._do elsif token_content = "proc" then - current_token.kind := LexerKind._proc + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._proc elsif token_content = "begin" then - current_token.kind := LexerKind._begin + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._begin elsif token_content = "end" then - current_token.kind := LexerKind._end + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._end elsif token_content = "extern" then - current_token.kind := LexerKind._extern + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._extern elsif token_content = "const" then - current_token.kind := LexerKind._const + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._const elsif token_content = "var" then - current_token.kind := LexerKind._var + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._var elsif token_content = "case" then - current_token.kind := LexerKind._case + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._case elsif token_content = "of" then - current_token.kind := LexerKind._of + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._of elsif token_content = "type" then - current_token.kind := LexerKind._type + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._type elsif token_content = "record" then - current_token.kind := LexerKind._record - elsif token_content = "union" then - current_token.kind := LexerKind._union + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._record elsif token_content = "true" then - current_token.kind := LexerKind.boolean; - current_token.value.boolean_value := true + current_token := malloc(#size(ElnaLexerBooleanToken)); + current_token^.kind := ElnaLexerKind.boolean; + cast(current_token: ^ElnaLexerBooleanToken)^.value := true elsif token_content = "false" then - current_token.kind := LexerKind.boolean; - current_token.value.boolean_value := false + current_token := malloc(#size(ElnaLexerBooleanToken)); + current_token^.kind := ElnaLexerKind.boolean; + cast(current_token: ^ElnaLexerBooleanToken)^.value := false elsif token_content = "nil" then - current_token.kind := LexerKind.null + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.null elsif token_content = "or" then - current_token.kind := LexerKind._or + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._or elsif token_content = "return" then - current_token.kind := LexerKind._return + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._return elsif token_content = "cast" then - current_token.kind := LexerKind._cast + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._cast elsif token_content = "defer" then - current_token.kind := LexerKind._defer - elsif token_content = "program" then - current_token.kind := LexerKind._program - elsif token_content = "module" then - current_token.kind := LexerKind._module + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._defer elsif token_content = "import" then - current_token.kind := LexerKind._import + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind._import else - current_token.kind := LexerKind.identifier; - current_token.value.string := string_dup(token_content) + current_token := malloc(#size(ElnaLexerStringToken)); + current_token^.kind := ElnaLexerKind.identifier; + cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(token_content) end; return current_token end -proc lexer_add_token(lexer: ^Tokenizer; token: Token) +proc lexer_add_token(lexer: ^Tokenizer; token: ^ElnaLexerToken) var new_length: Word begin new_length := lexer^.length + 1u; - lexer^.data := cast(reallocarray(cast(lexer^.data: Pointer), new_length, #size(Token)): ^Token); + lexer^.data := cast(reallocarray(cast(lexer^.data: Pointer), new_length, #size(Pointer)): ^^ElnaLexerToken); (lexer^.data + lexer^.length)^ := token; lexer^.length := new_length 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): ^ElnaLexerToken var - current_token: Token + current_token: ^ElnaLexerToken := nil first_char: Char begin - current_token.kind := LexerKind.unknown; - first_char := source_code_head(source_code); if isalpha(cast(first_char: Int)) <> 0 or first_char = '_' then @@ -421,158 +429,170 @@ begin source_code_advance(@source_code); lexer_identifier(@source_code, token_buffer); - current_token.kind := LexerKind.trait; - current_token.value.string := string_dup(string_buffer_clear(token_buffer)) + current_token := malloc(#size(ElnaLexerStringToken)); + current_token^.kind := ElnaLexerKind.trait; + cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer)) elsif isdigit(cast(first_char: Int)) <> 0 then - lexer_number(@source_code, @current_token.value.int_value); + current_token := malloc(#size(ElnaLexerIntegerToken)); + lexer_number(@source_code, @cast(current_token: ^ElnaLexerIntegerToken)^.value); if source_code_expect(@source_code, 'u') then - current_token.kind := LexerKind.word; - source_code_advance(@source_code) + current_token^.kind := ElnaLexerKind.word; + source_code_advance(@source_code) else - current_token.kind := LexerKind.integer + current_token^.kind := ElnaLexerKind.integer end elsif first_char = '(' then source_code_advance(@source_code); if source_code_empty(@source_code) then - current_token.kind := LexerKind.left_paren + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.left_paren elsif source_code_head(source_code) = '*' then source_code_advance(@source_code); if lexer_comment(@source_code, token_buffer) then - current_token.value.string := string_dup(string_buffer_clear(token_buffer)); - current_token.kind := LexerKind.comment - else - current_token.kind := LexerKind.unknown + current_token := malloc(#size(ElnaLexerStringToken)); + cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer)); + current_token^.kind := ElnaLexerKind.comment end else - current_token.kind := LexerKind.left_paren + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.left_paren end elsif first_char = ')' then - current_token.kind := LexerKind.right_paren; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.right_paren; source_code_advance(@source_code) elsif first_char = '\'' then source_code_advance(@source_code); - if lexer_character(@source_code, @current_token.value.char_value) & source_code_expect(@source_code, '\'') then - current_token.kind := LexerKind.character; + if lexer_character(@source_code, @first_char) & source_code_expect(@source_code, '\'') then + current_token := malloc(#size(ElnaLexerCharacterToken)); + current_token^.kind := ElnaLexerKind.character; + cast(current_token: ^ElnaLexerCharacterToken)^.value := first_char; source_code_advance(@source_code) - else - current_token.kind := LexerKind.unknown end elsif first_char = '"' then source_code_advance(@source_code); if lexer_string(@source_code, token_buffer) then - current_token.kind := LexerKind.string; - current_token.value.string := string_dup(string_buffer_clear(token_buffer)) - else - current_token.kind := LexerKind.unknown + current_token := malloc(#size(ElnaLexerStringToken)); + current_token^.kind := ElnaLexerKind.string; + cast(current_token: ^ElnaLexerStringToken)^.value := string_dup(string_buffer_clear(token_buffer)) end elsif first_char = '[' then - current_token.kind := LexerKind.left_square; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.left_square; source_code_advance(@source_code) elsif first_char = ']' then - current_token.kind := LexerKind.right_square; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.right_square; source_code_advance(@source_code) elsif first_char = '>' then source_code_advance(@source_code); + current_token := malloc(#size(ElnaLexerToken)); if source_code_empty(@source_code) then - current_token.kind := LexerKind.greater_than + current_token^.kind := ElnaLexerKind.greater_than elsif source_code_head(source_code) = '=' then - current_token.kind := LexerKind.greater_equal; + current_token^.kind := ElnaLexerKind.greater_equal; source_code_advance(@source_code) elsif source_code_head(source_code) = '>' then - current_token.kind := LexerKind.shift_right; + current_token^.kind := ElnaLexerKind.shift_right; source_code_advance(@source_code) else - current_token.kind := LexerKind.greater_than + current_token^.kind := ElnaLexerKind.greater_than end elsif first_char = '<' then source_code_advance(@source_code); + current_token := malloc(#size(ElnaLexerToken)); if source_code_empty(@source_code) then - current_token.kind := LexerKind.less_than + current_token^.kind := ElnaLexerKind.less_than elsif source_code_head(source_code) = '=' then - current_token.kind := LexerKind.less_equal; + current_token^.kind := ElnaLexerKind.less_equal; source_code_advance(@source_code) elsif source_code_head(source_code) = '<' then - current_token.kind := LexerKind.shift_left; + current_token^.kind := ElnaLexerKind.shift_left; source_code_advance(@source_code) elsif source_code_head(source_code) = '>' then - current_token.kind := LexerKind.not_equal; + current_token^.kind := ElnaLexerKind.not_equal; source_code_advance(@source_code) else - current_token.kind := LexerKind.less_than + current_token^.kind := ElnaLexerKind.less_than end elsif first_char = '=' then - current_token.kind := LexerKind.equal; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.equals; source_code_advance(@source_code) elsif first_char = ';' then - current_token.kind := LexerKind.semicolon; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.semicolon; source_code_advance(@source_code) elsif first_char = '.' then - current_token.kind := LexerKind.dot; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.dot; source_code_advance(@source_code) elsif first_char = ',' then - current_token.kind := LexerKind.comma; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.comma; source_code_advance(@source_code) elsif first_char = '+' then - current_token.kind := LexerKind.plus; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.plus; source_code_advance(@source_code) elsif first_char = '-' then source_code_advance(@source_code); - - if source_code_empty(@source_code) then - current_token.kind := LexerKind.minus - elsif source_code_head(source_code) = '>' then - current_token.kind := LexerKind.arrow; - source_code_advance(@source_code) - else - current_token.kind := LexerKind.minus - end + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.minus elsif first_char = '*' then - current_token.kind := LexerKind.multiplication; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.multiplication; source_code_advance(@source_code) elsif first_char = '/' then - current_token.kind := LexerKind.division; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.division; source_code_advance(@source_code) elsif first_char = '%' then - current_token.kind := LexerKind.remainder; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.remainder; source_code_advance(@source_code) elsif first_char = ':' then source_code_advance(@source_code); + current_token := malloc(#size(ElnaLexerToken)); if source_code_empty(@source_code) then - current_token.kind := LexerKind.colon + current_token^.kind := ElnaLexerKind.colon elsif source_code_head(source_code) = '=' then - current_token.kind := LexerKind.assignment; + current_token^.kind := ElnaLexerKind.assignment; source_code_advance(@source_code) else - current_token.kind := LexerKind.colon + current_token^.kind := ElnaLexerKind.colon end elsif first_char = '^' then - current_token.kind := LexerKind.hat; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.hat; source_code_advance(@source_code) elsif first_char = '@' then - current_token.kind := LexerKind.at; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.at; source_code_advance(@source_code) elsif first_char = '!' then - current_token.kind := LexerKind.exclamation; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.exclamation; source_code_advance(@source_code) elsif first_char = '&' then - current_token.kind := LexerKind.and; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.and; source_code_advance(@source_code) elsif first_char = '~' then - current_token.kind := LexerKind.not; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.not; source_code_advance(@source_code) elsif first_char = '|' then - current_token.kind := LexerKind.pipe; - source_code_advance(@source_code) - else - current_token.kind := LexerKind.unknown; + current_token := malloc(#size(ElnaLexerToken)); + current_token^.kind := ElnaLexerKind.pipe; source_code_advance(@source_code) end; @@ -582,7 +602,7 @@ end (* Split the source text into tokens. *) proc lexer_text(source_code: SourceCode): Tokenizer var - current_token: Token + current_token: ^ElnaLexerToken token_buffer: StringBuffer lexer: Tokenizer begin @@ -594,7 +614,7 @@ begin while ~source_code_empty(@source_code) do current_token := lexer_next(source_code, @token_buffer); - if current_token.kind <> LexerKind.unknown then + if current_token <> nil then lexer_add_token(@lexer, current_token); lexer_spaces(@source_code) else @@ -611,151 +631,141 @@ end Parser. *) -proc parse(tokens: ^Token; tokens_size: Word) +proc parse(tokens: ^^ElnaLexerToken; tokens_size: Word) var - current_token: ^Token + current_token: ^ElnaLexerToken i: Word := 0u begin while i < tokens_size do - current_token := tokens + i; + current_token := (tokens + i)^; case current_token^.kind of - LexerKind._if: + ElnaLexerKind._if: write_s("IF") - | LexerKind._then: + | ElnaLexerKind._then: write_s("THEN") - | LexerKind._else: + | ElnaLexerKind._else: write_s("ELSE") - | LexerKind._elsif: + | ElnaLexerKind._elsif: write_s("ELSIF") - | LexerKind._while: + | ElnaLexerKind._while: write_s("WHILE") - | LexerKind._do: + | ElnaLexerKind._do: write_s("DO") - | LexerKind._proc: + | ElnaLexerKind._proc: write_s("PROC") - | LexerKind._begin: + | ElnaLexerKind._begin: write_s("BEGIN") - | LexerKind._end: + | ElnaLexerKind._end: write_s("END") - | LexerKind._extern: + | ElnaLexerKind._extern: write_s("EXTERN") - | LexerKind._const: + | ElnaLexerKind._const: write_s("CONST") - | LexerKind._var: + | ElnaLexerKind._var: write_s("VAR") - | LexerKind._case: + | ElnaLexerKind._case: write_s("CASE") - | LexerKind._of: + | ElnaLexerKind._of: write_s("OF") - | LexerKind._type: + | ElnaLexerKind._type: write_s("TYPE") - | LexerKind._record: + | ElnaLexerKind._record: write_s("RECORD") - | LexerKind._union: - write_s("UNION") - | LexerKind.pipe: + | ElnaLexerKind.pipe: write_s("|") - | LexerKind.to: - write_s("TO") - | LexerKind.boolean: + | ElnaLexerKind.boolean: write_s("BOOLEAN<"); - write_b(current_token^.value.boolean_value); + write_b(cast(current_token: ^ElnaLexerBooleanToken)^.value); write_c('>') - | LexerKind.null: + | ElnaLexerKind.null: write_s("NIL") - | LexerKind.and: + | ElnaLexerKind.and: write_s("&") - | LexerKind._or: + | ElnaLexerKind._or: write_s("OR") - | LexerKind.not: + | ElnaLexerKind.not: write_s("~") - | LexerKind._return: + | ElnaLexerKind._return: write_s("RETURN") - | LexerKind._cast: + | ElnaLexerKind._cast: write_s("CAST") - | LexerKind.shift_left: + | ElnaLexerKind.shift_left: write_s("<<") - | LexerKind.shift_right: + | ElnaLexerKind.shift_right: write_s(">>") - | LexerKind.identifier: + | ElnaLexerKind.identifier: write_c('<'); - write_s(current_token^.value.string); + write_s(cast(current_token: ^ElnaLexerStringToken)^.value); write_c('>') - | LexerKind.trait: + | ElnaLexerKind.trait: write_c('#'); - write_s(current_token^.value.string) - | LexerKind.left_paren: + write_s(cast(current_token: ^ElnaLexerStringToken)^.value) + | ElnaLexerKind.left_paren: write_s("(") - | LexerKind.right_paren: + | ElnaLexerKind.right_paren: write_s(")") - | LexerKind.left_square: + | ElnaLexerKind.left_square: write_s("[") - | LexerKind.right_square: + | ElnaLexerKind.right_square: write_s("]") - | LexerKind.greater_equal: + | ElnaLexerKind.greater_equal: write_s(">=") - | LexerKind.less_equal: + | ElnaLexerKind.less_equal: write_s("<=") - | LexerKind.greater_than: + | ElnaLexerKind.greater_than: write_s(">") - | LexerKind.less_than: + | ElnaLexerKind.less_than: write_s("<") - | LexerKind.equal: + | ElnaLexerKind.equals: write_s("=") - | LexerKind.not_equal: + | ElnaLexerKind.not_equal: write_s("<>") - | LexerKind.semicolon: + | ElnaLexerKind.semicolon: write_c(';') - | LexerKind.dot: + | ElnaLexerKind.dot: write_c('.') - | LexerKind.comma: + | ElnaLexerKind.comma: write_c(',') - | LexerKind.plus: + | ElnaLexerKind.plus: write_c('+') - | LexerKind.minus: + | ElnaLexerKind.minus: write_c('-') - | LexerKind.multiplication: + | ElnaLexerKind.multiplication: write_c('*') - | LexerKind.division: + | ElnaLexerKind.division: write_c('/') - | LexerKind.remainder: + | ElnaLexerKind.remainder: write_c('%') - | LexerKind.assignment: + | ElnaLexerKind.assignment: write_s(":=") - | LexerKind.colon: + | ElnaLexerKind.colon: write_c(':') - | LexerKind.hat: + | ElnaLexerKind.hat: write_c('^') - | LexerKind.at: + | ElnaLexerKind.at: write_c('@') - | LexerKind.comment: + | ElnaLexerKind.comment: write_s("(* COMMENT *)") - | LexerKind.integer: + | ElnaLexerKind.integer: write_c('<'); - write_i(current_token^.value.int_value); + write_i(cast(current_token: ^ElnaLexerIntegerToken)^.value); write_c('>') - | LexerKind.word: + | ElnaLexerKind.word: write_c('<'); - write_i(current_token^.value.int_value); + write_i(cast(current_token: ^ElnaLexerIntegerToken)^.value); write_s("u>") - | LexerKind.character: + | ElnaLexerKind.character: write_c('<'); - write_i(cast(current_token^.value.char_value: Int)); + write_i(cast(cast(current_token: ^ElnaLexerCharacterToken)^.value: Int)); write_s("c>") - | LexerKind.string: + | ElnaLexerKind.string: write_s("\"...\"") - | LexerKind._defer: + | ElnaLexerKind._defer: write_s("DEFER") - | LexerKind.exclamation: + | ElnaLexerKind.exclamation: write_c('!') - | LexerKind.arrow: - write_s("->") - | LexerKind._program: - write_s("PROGRAM") - | LexerKind._module: - write_s("MODULE") - | LexerKind._import: + | ElnaLexerKind._import: write_s("IMPORT") else write_s("UNKNOWN<"); @@ -790,7 +800,7 @@ end proc process(argc: Int; argv: ^^Char): Int var - tokens: ^Token + tokens: ^ElnaLexerToken tokens_size: Word source_code: SourceCode command_line: ^CommandLine @@ -817,7 +827,7 @@ begin end; source_code.position := TextLocation(1u, 1u); - source_code.input := cast(source_file: Pointer); + source_code.input := source_file; source_code.empty := source_file_empty; source_code.head := source_file_head; source_code.advance := source_file_advance; |
