diff options
| author | Eugen Wissner <belka@caraus.de> | 2026-07-13 02:49:24 +0200 |
|---|---|---|
| committer | Eugen Wissner <belka@caraus.de> | 2026-07-13 02:49:24 +0200 |
| commit | 97741a01323021ccec8b0b60c6f8318c88ac373a (patch) | |
| tree | 51cd1722073498a749f158b9a6dc998fb4846055 /source | |
| parent | b2f8be605d2b79d1d4b1995646e7058bec299a22 (diff) | |
| download | elna-97741a01323021ccec8b0b60c6f8318c88ac373a.tar.gz | |
Fix ICE substracting pointers
Diffstat (limited to 'source')
| -rw-r--r-- | source/common.elna | 13 | ||||
| -rw-r--r-- | source/lexer.elna | 684 | ||||
| -rw-r--r-- | source/main.elna | 4 |
3 files changed, 584 insertions, 117 deletions
diff --git a/source/common.elna b/source/common.elna index 8bba90f..9e6a314 100644 --- a/source/common.elna +++ b/source/common.elna @@ -78,4 +78,17 @@ begin return nil end +(* Returns true or false depending whether two strings are equal. *) +proc string_compare*(lhs_pointer: ^Char; lhs_length: Word; rhs_pointer: String): Bool +var + result: Bool +begin + if lhs_length = rhs_pointer.length then + result := memcmp(lhs_pointer, rhs_pointer.ptr, lhs_length) = 0 + else + result := false + end; + return result +end + end. diff --git a/source/lexer.elna b/source/lexer.elna index 318d740..5029ec5 100644 --- a/source/lexer.elna +++ b/source/lexer.elna @@ -2,37 +2,37 @@ 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/. *) -import cstdio, common +import cstdio, common, cstdlib const CHUNK_SIZE := 85536u type - ElnaLexerState = ( - start, - colon, - identifier, - decimal, - leading_zero, - greater, - minus, - left_paren, - less, - dot, - comment, - closing_comment, - character, - character_escape, - string, - string_escape, - number_sign, - trait, - finish - ) + ElnaLexerState = ( + start, + colon, + identifier, + decimal, + leading_zero, + greater, + minus, + left_paren, + less, + dot, + comment, + closing_comment, + character, + character_escape, + string, + string_escape, + number_sign, + trait, + finish + ) ElnaLexerToken* = record kind: ElnaLexerKind; - start: String; (* DEPRECATED *) - position: ElnaPosition + start: String; (* DEPRECATED *) + position: ElnaPosition end ElnaLexerBooleanToken* = record(ElnaLexerToken) value: Bool @@ -49,20 +49,20 @@ type TransitionAction = proc(lexer: ^Lexer; token: ^ElnaLexerToken) (* DEPRECATED should be replaced with TransitionAction (but keeping the type name). *) - ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited) + ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited) ElnaLexerTransition = record action: ElnaLexerAction; next_state: ElnaLexerState end - ElnaLexerCursor = record - state: ElnaLexerState; - start: ^Char; - finish: ^Char; - token: ^ElnaLexerToken; - position: ElnaPosition - end + ElnaLexerCursor = record + state: ElnaLexerState; + start: ^Char; + finish: ^Char; + token: ^ElnaLexerToken; + position: ElnaPosition + end BufferPosition* = record iterator: ^Char; @@ -76,58 +76,58 @@ type start: BufferPosition; current: BufferPosition end - ElnaLexerKind* = ( - identifier, - _const, - _var, - _proc, - _type, - _begin, - _end, - _if, - _then, - _else, - _elsif, - _extern, - _record, - boolean, - null, - and, - _or, - _xor, - not, - _return, - _cast, - trait, - left_paren, - right_paren, - left_square, - right_square, - greater_equal, - less_equal, - greater_than, - less_than, - not_equal, - equals, - semicolon, - dot, - comma, - plus, - _import, - minus, - multiplication, - division, - remainder, - assignment, - colon, - hat, - at, - comment, - string, - character, - integer, - word, - _while, + ElnaLexerKind* = ( + identifier, + _const, + _var, + _proc, + _type, + _begin, + _end, + _if, + _then, + _else, + _elsif, + _extern, + _record, + boolean, + null, + and, + _or, + _xor, + not, + _return, + _cast, + trait, + left_paren, + right_paren, + left_square, + right_square, + greater_equal, + less_equal, + greater_than, + less_than, + not_equal, + equals, + semicolon, + dot, + comma, + plus, + _import, + minus, + multiplication, + division, + remainder, + assignment, + colon, + hat, + at, + comment, + string, + character, + integer, + word, + _while, _defer, exclamation, shift_right, @@ -136,36 +136,490 @@ type _case, _do, _of, - eof - ) - (** - * Classification table assigns each possible character to a group (class). All - * characters of the same group a handled equivalently. - *) - ElnaLexerClass = ( - invalid, - digit, - alpha, - space, - colon, - equals, - left_paren, - right_paren, - asterisk, - backslash, - single, - hex, - zero, - x, - eof, - dot, - minus, - single_quote, - double_quote, - greater, - less, - other, - number_sign - ) + eof + ) + (** + * Classification table assigns each possible character to a group (class). All + * characters of the same group a handled equivalently. + *) + ElnaLexerClass = ( + invalid, + digit, + alpha, + space, + colon, + equals, + left_paren, + right_paren, + asterisk, + backslash, + single, + hex, + zero, + x, + eof, + dot, + minus, + single_quote, + double_quote, + greater, + less, + other, + number_sign + ) + +var + classification: [256]ElnaLexerClass + transition_table: [19][23]ElnaLexerTransition + +proc elna_lexer_classifications1() +begin + classification[1] := ElnaLexerClass.eof; + classification[10] := ElnaLexerClass.space; + classification[11] := ElnaLexerClass.space; + classification[14] := ElnaLexerClass.space; + classification[33] := ElnaLexerClass.space; + classification[34] := ElnaLexerClass.single +end + +proc elna_lexer_classifications2() +begin + classification[35] := ElnaLexerClass.double_quote; + classification[36] := ElnaLexerClass.number_sign; + classification[37] := ElnaLexerClass.other; + classification[38] := ElnaLexerClass.single; + classification[39] := ElnaLexerClass.single; + classification[40] := ElnaLexerClass.single_quote; + classification[41] := ElnaLexerClass.left_paren; + classification[42] := ElnaLexerClass.right_paren; + classification[43] := ElnaLexerClass.asterisk; + classification[44] := ElnaLexerClass.single; + classification[45] := ElnaLexerClass.single; + classification[46] := ElnaLexerClass.minus; + classification[47] := ElnaLexerClass.dot; + classification[48] := ElnaLexerClass.single; + classification[49] := ElnaLexerClass.zero; + classification[50] := ElnaLexerClass.digit; + classification[51] := ElnaLexerClass.digit; + classification[52] := ElnaLexerClass.digit; + classification[53] := ElnaLexerClass.digit; + classification[54] := ElnaLexerClass.digit; + classification[55] := ElnaLexerClass.digit; + classification[56] := ElnaLexerClass.digit; + classification[57] := ElnaLexerClass.digit; + classification[58] := ElnaLexerClass.digit; + classification[59] := ElnaLexerClass.colon; + classification[60] := ElnaLexerClass.single; + classification[61] := ElnaLexerClass.less; + classification[62] := ElnaLexerClass.equals; + classification[63] := ElnaLexerClass.greater; + classification[64] := ElnaLexerClass.other +end + +proc elna_lexer_classifications3() +begin + classification[65] := ElnaLexerClass.single; + classification[66] := ElnaLexerClass.alpha; + classification[67] := ElnaLexerClass.alpha; + classification[68] := ElnaLexerClass.alpha; + classification[69] := ElnaLexerClass.alpha; + classification[70] := ElnaLexerClass.alpha; + classification[71] := ElnaLexerClass.alpha; + classification[72] := ElnaLexerClass.alpha; + classification[73] := ElnaLexerClass.alpha; + classification[74] := ElnaLexerClass.alpha; + classification[75] := ElnaLexerClass.alpha; + classification[76] := ElnaLexerClass.alpha; + classification[77] := ElnaLexerClass.alpha; + classification[78] := ElnaLexerClass.alpha; + classification[79] := ElnaLexerClass.alpha; + classification[80] := ElnaLexerClass.alpha; + classification[81] := ElnaLexerClass.alpha; + classification[82] := ElnaLexerClass.alpha; + classification[83] := ElnaLexerClass.alpha; + classification[84] := ElnaLexerClass.alpha; + classification[85] := ElnaLexerClass.alpha; + classification[86] := ElnaLexerClass.alpha; + classification[87] := ElnaLexerClass.alpha; + classification[88] := ElnaLexerClass.alpha; + classification[89] := ElnaLexerClass.alpha; + classification[90] := ElnaLexerClass.alpha; + classification[91] := ElnaLexerClass.alpha; + classification[92] := ElnaLexerClass.single; + classification[93] := ElnaLexerClass.backslash; + classification[94] := ElnaLexerClass.single; + classification[95] := ElnaLexerClass.single; + classification[96] := ElnaLexerClass.alpha; + classification[97] := ElnaLexerClass.other; + classification[98] := ElnaLexerClass.hex +end + +proc elna_lexer_classifications4() +begin + classification[99] := ElnaLexerClass.hex; + classification[100] := ElnaLexerClass.hex; + classification[101] := ElnaLexerClass.hex; + classification[102] := ElnaLexerClass.hex; + classification[103] := ElnaLexerClass.hex; + classification[104] := ElnaLexerClass.alpha; + classification[105] := ElnaLexerClass.alpha; + classification[106] := ElnaLexerClass.alpha; + classification[107] := ElnaLexerClass.alpha; + classification[108] := ElnaLexerClass.alpha; + classification[109] := ElnaLexerClass.alpha; + classification[110] := ElnaLexerClass.alpha; + classification[111] := ElnaLexerClass.alpha; + classification[112] := ElnaLexerClass.alpha; + classification[113] := ElnaLexerClass.alpha; + classification[114] := ElnaLexerClass.alpha; + classification[115] := ElnaLexerClass.alpha; + classification[116] := ElnaLexerClass.alpha; + classification[117] := ElnaLexerClass.alpha; + classification[118] := ElnaLexerClass.alpha; + classification[119] := ElnaLexerClass.alpha; + classification[120] := ElnaLexerClass.alpha; + classification[121] := ElnaLexerClass.x; + classification[122] := ElnaLexerClass.alpha; + classification[123] := ElnaLexerClass.alpha; + classification[124] := ElnaLexerClass.other; + classification[125] := ElnaLexerClass.single; + classification[126] := ElnaLexerClass.other; + classification[127] := ElnaLexerClass.single +end + +(** + * Initializes the array with character classes. + *) +proc elna_lexer_classifications() +var + code: Word +begin + code := 1u; + + (* Set everything by default to invalid. *) + while code < 129u do + classification[code] := ElnaLexerClass.invalid; + code := code + 1u + end; + + elna_lexer_classifications1(); + elna_lexer_classifications2(); + elna_lexer_classifications3(); + elna_lexer_classifications4(); + + (* Set the remaining 129 - 256 bytes to transitionClassOther. *) + while code < 257u do + classification[code] := ElnaLexerClass.other; + code := code + 1u + end +end + +proc elna_lexer_get_transition(current_state: ElnaLexerState; character_class: ElnaLexerClass): ^ElnaLexerTransition + (* Each state is 8 bytes long (2 words: action and next state). + There are 23 character classes, so a transition row 8 * 23 = 184 bytes long. *) + + return @transition_table[cast(current_state: Word)][cast(character_class: Word)] +end + +(** + * Parameters: + * current_state - First index into transitions table. + * character_class - Second index into transitions table. + * action - Action to assign. + * next_state - Next state to assign. + *) +proc elna_lexer_set_transition(current_state: ElnaLexerState; character_class: ElnaLexerClass; + action: ElnaLexerAction; next_state: ElnaLexerState) +var + transition: ^ElnaLexerTransition +begin + transition := elna_lexer_get_transition(current_state, character_class); + + transition^.action := action; + transition^.next_state := next_state +end + +(** + * Sets same action and state transition for all character classes in one transition row. + * + * Parameters: + * current_state - Current state (Transition state enumeration). + * default_action - Default action (Callback). + * next_state - Next state (Transition state enumeration). + *) +proc elna_lexer_default_transition(current_state: ElnaLexerState; default_action: ElnaLexerAction; + next_state: ElnaLexerState) +begin + elna_lexer_set_transition(current_state, ElnaLexerClass.invalid, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.digit, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.alpha, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.space, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.colon, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.equals, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.left_paren, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.right_paren, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.asterisk, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.backslash, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.single, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.hex, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.zero, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.x, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.eof, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.dot, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.minus, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.single_quote, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.double_quote, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.greater, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.less, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.other, default_action, next_state); + elna_lexer_set_transition(current_state, ElnaLexerClass.number_sign, default_action, next_state) +end + +(** + * The transition table describes transitions from one state to another, given + * a symbol (character class). + * + * The table has m rows and n columns, where m is the amount of states and n is + * the amount of classes. So given the current state and a classified character + * the table can be used to look up the next state. + *) +proc elna_lexer_transitions() +begin + (* Start state. *) + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.decimal); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.space, ElnaLexerAction.skip, ElnaLexerState.start); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.colon, ElnaLexerAction.accumulate, ElnaLexerState.colon); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.equals, ElnaLexerAction.single, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.left_paren, ElnaLexerAction.accumulate, ElnaLexerState.left_paren); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.right_paren, ElnaLexerAction.single, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.asterisk, ElnaLexerAction.single, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.backslash, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.single, ElnaLexerAction.single, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.leading_zero); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.eof, ElnaLexerAction.eof, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.dot, ElnaLexerAction.single, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.minus, ElnaLexerAction.accumulate, ElnaLexerState.minus); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.single_quote, ElnaLexerAction.accumulate, ElnaLexerState.character); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.double_quote, ElnaLexerAction.accumulate, ElnaLexerState.string); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.greater, ElnaLexerAction.accumulate, ElnaLexerState.greater); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.less, ElnaLexerAction.accumulate, ElnaLexerState.less); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.other, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.start, ElnaLexerClass.number_sign, ElnaLexerAction.accumulate, ElnaLexerState.number_sign); + + (* Colon state. *) + elna_lexer_default_transition(ElnaLexerState.colon, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.colon, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish); + + (* Identifier state. *) + elna_lexer_default_transition(ElnaLexerState.identifier, ElnaLexerAction.key_id, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + elna_lexer_set_transition(ElnaLexerState.identifier, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.identifier); + + (* Decimal state. *) + elna_lexer_default_transition(ElnaLexerState.decimal, ElnaLexerAction.integer, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.decimal); + elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.alpha, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.hex, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.decimal); + elna_lexer_set_transition(ElnaLexerState.decimal, ElnaLexerClass.x, ElnaLexerAction.none, ElnaLexerState.finish); + + (* Leading zero. *) + elna_lexer_default_transition(ElnaLexerState.leading_zero, ElnaLexerAction.integer, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.digit, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.alpha, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.hex, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.zero, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.leading_zero, ElnaLexerClass.x, ElnaLexerAction.none, ElnaLexerState.dot); + + (* Greater state. *) + elna_lexer_default_transition(ElnaLexerState.greater, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.greater, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish); + + (* Minus state. *) + elna_lexer_default_transition(ElnaLexerState.minus, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.minus, ElnaLexerClass.greater, ElnaLexerAction.composite, ElnaLexerState.finish); + + (* Left paren state. *) + elna_lexer_default_transition(ElnaLexerState.left_paren, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.left_paren, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.comment); + + (* Less state. *) + elna_lexer_default_transition(ElnaLexerState.less, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.less, ElnaLexerClass.equals, ElnaLexerAction.composite, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.less, ElnaLexerClass.greater, ElnaLexerAction.composite, ElnaLexerState.finish); + + (* Hexadecimal after 0x. *) + elna_lexer_default_transition(ElnaLexerState.dot, ElnaLexerAction.finalize, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.dot, ElnaLexerClass.dot, ElnaLexerAction.composite, ElnaLexerState.finish); + + (* Comment. *) + elna_lexer_default_transition(ElnaLexerState.comment, ElnaLexerAction.accumulate, ElnaLexerState.comment); + elna_lexer_set_transition(ElnaLexerState.comment, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.closing_comment); + elna_lexer_set_transition(ElnaLexerState.comment, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + + (* Closing comment. *) + elna_lexer_default_transition(ElnaLexerState.closing_comment, ElnaLexerAction.accumulate, ElnaLexerState.comment); + elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.right_paren, ElnaLexerAction.delimited, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.asterisk, ElnaLexerAction.accumulate, ElnaLexerState.closing_comment); + elna_lexer_set_transition(ElnaLexerState.closing_comment, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + + (* Character. *) + elna_lexer_default_transition(ElnaLexerState.character, ElnaLexerAction.accumulate, ElnaLexerState.character); + elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.single_quote, ElnaLexerAction.delimited, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.character, ElnaLexerClass.backslash, ElnaLexerAction.accumulate, ElnaLexerState.character_escape); + + (* Escape sequence in a character. *) + elna_lexer_default_transition(ElnaLexerState.character_escape, ElnaLexerAction.accumulate, ElnaLexerState.character); + elna_lexer_set_transition(ElnaLexerState.character_escape, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.character_escape, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + + (* String. *) + elna_lexer_default_transition(ElnaLexerState.string, ElnaLexerAction.accumulate, ElnaLexerState.string); + elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.double_quote, ElnaLexerAction.delimited, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.string, ElnaLexerClass.backslash, ElnaLexerAction.accumulate, ElnaLexerState.string_escape); + + (* Escape sequence in a string. *) + elna_lexer_default_transition(ElnaLexerState.string_escape, ElnaLexerAction.accumulate, ElnaLexerState.string); + elna_lexer_set_transition(ElnaLexerState.string_escape, ElnaLexerClass.invalid, ElnaLexerAction.none, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.string_escape, ElnaLexerClass.eof, ElnaLexerAction.none, ElnaLexerState.finish); + + (* Number sign state. *) + elna_lexer_default_transition(ElnaLexerState.number_sign, ElnaLexerAction.key_id, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.number_sign, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.trait); + + (* Trait state. *) + elna_lexer_default_transition(ElnaLexerState.trait, ElnaLexerAction.key_id, ElnaLexerState.finish); + elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.digit, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.alpha, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.hex, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.zero, ElnaLexerAction.accumulate, ElnaLexerState.trait); + elna_lexer_set_transition(ElnaLexerState.trait, ElnaLexerClass.x, ElnaLexerAction.accumulate, ElnaLexerState.trait) +end + +proc elna_lexer_advance(cursor: ^ElnaLexerCursor) +begin + cursor^.finish := cursor^.finish + 1; + cursor^.position.end_location.column := cursor^.position.end_location.column + 1u +end + +proc elna_lexer_classify_space(start_position: ^Char; location: ^ElnaLocation) +begin + if start_position^ = '\n' then + location^.line := location^.line + 1u; + location^.column := 1u + else + location^.column := location^.column + 1u + end +end + +proc elna_lexer_token_create(kind: ElnaLexerKind; position: ^ElnaPosition): ^ElnaLexerToken +var + result: ^ElnaLexerToken +begin + result := malloc(#size(ElnaLexerToken)); + result^.kind := kind; + result^.position := position^; + + return result +end + +proc elna_lexer_classify_keyword(position_start, position_end: ^Char; position: ^ElnaPosition): ^ElnaLexerToken +var + result: ^ElnaLexerToken + result_length: Word +begin + result_length := cast(position_end - position_start: Word); + + result := elna_lexer_token_create(ElnaLexerKind.identifier, position); + result^.start := String(position_start, result_length); + + if position_start^ = '#' then + result^.kind := ElnaLexerKind.trait + elsif string_compare(position_start, result_length, "const") then + result^.kind := ElnaLexerKind._const + elsif string_compare(position_start, result_length, "var") then + result^.kind := ElnaLexerKind._var + elsif string_compare(position_start, result_length, "proc") then + result^.kind := ElnaLexerKind._proc + elsif string_compare(position_start, result_length, "type") then + result^.kind := ElnaLexerKind._type + elsif string_compare(position_start, result_length, "begin") then + result^.kind := ElnaLexerKind._begin + elsif string_compare(position_start, result_length, "end") then + result^.kind := ElnaLexerKind._end + elsif string_compare(position_start, result_length, "return") then + result^.kind := ElnaLexerKind._return + elsif string_compare(position_start, result_length, "defer") then + result^.kind := ElnaLexerKind._defer + elsif string_compare(position_start, result_length, "if") then + result^.kind := ElnaLexerKind._if + elsif string_compare(position_start, result_length, "extern") then + result^.kind := ElnaLexerKind._extern + elsif string_compare(position_start, result_length, "then") then + result^.kind := ElnaLexerKind._then + elsif string_compare(position_start, result_length, "else") then + result^.kind := ElnaLexerKind._else + elsif string_compare(position_start, result_length, "elsif") then + result^.kind := ElnaLexerKind._elsif + elsif string_compare(position_start, result_length, "record") then + result^.kind := ElnaLexerKind._record + elsif string_compare(position_start, result_length, "or") then + result^.kind := ElnaLexerKind._or + elsif string_compare(position_start, result_length, "xor") then + result^.kind := ElnaLexerKind._xor + elsif string_compare(position_start, result_length, "nil") then + result^.kind := ElnaLexerKind.null + elsif string_compare(position_start, result_length, "true") then + result^.kind := ElnaLexerKind.boolean + elsif string_compare(position_start, result_length, "false") then + result^.kind := ElnaLexerKind.boolean + elsif string_compare(position_start, result_length, "cast") then + result^.kind := ElnaLexerKind._cast + end; + return result +end + +proc elna_lexer_classify_delimited(start_position, end_position: ^Char; position: ^ElnaPosition): ^ElnaLexerToken +var + delimiter: Char + result: ^ElnaLexerToken +begin + delimiter := start_position^; + + if delimiter = '(' then + result := elna_lexer_token_create(ElnaLexerKind.comment, position) + elsif delimiter = '\'' then + result := elna_lexer_token_create(ElnaLexerKind.character, position) + elsif delimiter = '"' then + result := elna_lexer_token_create(ElnaLexerKind.string, position) + end; + result^.start := String(start_position, cast(end_position - start_position: Word)); + + return result +end + +proc elna_lexer_classify_integer(start_position, end_position: ^Char; position: ^ElnaPosition): ^ElnaLexerToken +var + result: ^ElnaLexerToken +begin + result := elna_lexer_token_create(ElnaLexerKind.integer, position); + result^.start := String(start_position, cast(end_position - start_position: Word)); + + return result +end end. diff --git a/source/main.elna b/source/main.elna index 9a43fb8..37d0f07 100644 --- a/source/main.elna +++ b/source/main.elna @@ -30,8 +30,8 @@ type end var - stdout: ^FILE - stderr: ^FILE + stdout: ^FILE + stderr: ^FILE stdin: ^FILE (* |
