From 1c2a8e6da852016bedcc70e45cd328836a20f18a Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Tue, 2 Dec 2025 22:28:40 +0100 Subject: [PATCH] Add boolean literals and type --- boot/stage17/cl.elna | 350 +++++++++++++++++++++++++------------------ 1 file changed, 207 insertions(+), 143 deletions(-) diff --git a/boot/stage17/cl.elna b/boot/stage17/cl.elna index 7a33f6e..e10be76 100644 --- a/boot/stage17/cl.elna +++ b/boot/stage17/cl.elna @@ -7,6 +7,8 @@ program; (* Stage 17 compiler. *) +(* - true and false boolean literals. *) + type (** * List of intermediate representation items. @@ -14,6 +16,10 @@ type ElnaInstructionList = record next: Word end; + ElnaInstructionModule = record + data: Word; + code: Word + end; ElnaInstructionDeclaration = record next: Word; name: Word; @@ -44,6 +50,11 @@ type kind: Word; type_decoration: Word end; + ElnaTreeBooleanLiteral = record + kind: Word; + type_decoration: Word; + value: Word + end; ElnaTreeVariableExpression = record kind: Word; type_decoration: Word; @@ -74,28 +85,39 @@ type operand: Word; operator: Word end; - _if_statement = record - kind: Word; - next: Word; - conditionals: Word; - _else: Word - end; (** * All statements are chained into a list. Next contains a pointer to the next * statement in the statement list. *) - _statement = record + ElnaTreeStatement = record kind: Word; next: Word end; - _goto_statement = record + ElnaTreeIfStatement = record + kind: Word; + next: Word; + conditionals: Word; + _else: Word + end; + ElnaTreeGotoStatement = record kind: Word; next: Word; label: Word; length: Word end; - _label_declaration = record + ElnaTreeAssignStatement = record + kind: Word; + next: Word; + assignee: Word; + assignment: Word + end; + ElnaTreeReturnStatement = record + kind: Word; + next: Word; + returned: Word + end; + ElnaTreeLabelDeclaration = record kind: Word; next: Word; label: Word; @@ -113,27 +135,6 @@ type members: Word; length: Word end; - ElnaInstructionModule = record - data: Word; - code: Word - end; - _module_declaration = record - kind: Word; - types: Word; - globals: Word; - procedures: Word - end; - _assign_statement = record - kind: Word; - next: Word; - assignee: Word; - assignment: Word - end; - _return_statement = record - kind: Word; - next: Word; - returned: Word - end; ElnaTreeRecordTypeExpression = record kind: Word; members: Word; @@ -153,6 +154,51 @@ type base: Word; length: Word end; + (** + * Conditional statements is a list of pairs: condition and statements. + * Used for example to represent if and elsif blocks with beloning statements. + *) + ElnaTreeConditionalStatements = record + condition: Word; + statements: Word; + next: Word + end; + ElnaTreeDeclaration = record + kind: Word; + next: Word; + name: Word; + length: Word + end; + ElnaTreeModuleDeclaration = record + kind: Word; + types: Word; + globals: Word; + procedures: Word + end; + ElnaTreeProcedureDeclaration = record + kind: Word; + next: Word; + name: Word; + length: Word; + body: Word; + temporaries: Word; + parameters: Word + end; + ElnaTreeTypeDeclaration = record + kind: Word; + next: Word; + name: Word; + length: Word; + _type: Word + end; + ElnaTreeVariableDeclaration = record + kind: Word; + next: Word; + name: Word; + length: Word; + _type: Word + end; + ElnaType = record kind: Word; size: Word @@ -207,46 +253,6 @@ type symbol_table: Word end; - (** - * Conditional statements is a list of pairs: condition and statements. - * Used for example to represent if and elsif blocks with beloning statements. - *) - _conditional_statements = record - condition: Word; - statements: Word; - next: Word - end; - - _declaration = record - kind: Word; - next: Word; - name: Word; - length: Word - end; - _procedure_declaration = record - kind: Word; - next: Word; - name: Word; - length: Word; - body: Word; - temporaries: Word; - parameters: Word - end; - _type_declaration = record - kind: Word; - next: Word; - name: Word; - length: Word; - _type: Word - end; - _variable_declaration = record - kind: Word; - next: Word; - name: Word; - length: Word; - _type: Word - end; - ElnaLexerAction = (none, accumulate, skip, single, eof, finalize, composite, key_id, integer, delimited); (** @@ -317,8 +323,7 @@ type _do, _extern, _record, - _true, - _false, + boolean, null, and, _or, @@ -371,6 +376,7 @@ type integer_literal, string_literal, character_literal, + boolean_literal, variable_expression, field_access_expression, dereference_expression, @@ -1579,6 +1585,23 @@ begin return result end; +proc elna_parser_boolean_literal(); +var + boolean_token: Word; + result: ^ElnaTreeBooleanLiteral; +begin + result := malloc(ElnaTreeBooleanLiteral_size()); + + boolean_token := _elna_lexer_global_get_start(); + _elna_lexer_skip_token(); + + result^.kind := ElnaTreeKind.boolean_literal; + result^.value := string_compare(boolean_token, 4, "true", 4); + result^.type_decoration := nil; + + return result +end; + proc elna_parser_nil_literal(); var result: ^ElnaTreeNilLiteral; @@ -1601,6 +1624,15 @@ begin return nil end; +proc _elna_tac_boolean_literal(boolean_literal_node: ^ElnaTreeBooleanLiteral, operand_type: Word, operand_value: Word, operand_length: Word); +begin + operand_type^ := ElnaTacOperand.immediate; + operand_value^ := boolean_literal_node^.value; + operand_length^ := 0; + + return nil +end; + proc _elna_tac_nil_literal(nil_node: Word, operand_type: Word, operand_value: Word, operand_length: Word); begin operand_type^ := ElnaTacOperand.immediate; @@ -1737,6 +1769,8 @@ begin parser_node := elna_parser_integer_literal() elsif token_kind = ElnaLexerKind.string then parser_node := elna_parser_string_literal() + elsif token_kind = ElnaLexerKind.boolean then + parser_node := elna_parser_boolean_literal() elsif token_kind = ElnaLexerKind.null then parser_node := elna_parser_nil_literal() elsif token_kind = ElnaLexerKind.identifier then @@ -1792,6 +1826,8 @@ begin instruction := _elna_tac_string_literal(parser_node, operand_type, operand_value, operand_length) elsif parser_node^.kind = ElnaTreeKind.integer_literal then instruction := _elna_tac_integer_literal(parser_node, operand_type, operand_value, operand_length) + elsif parser_node^.kind = ElnaTreeKind.boolean_literal then + instruction := _elna_tac_boolean_literal(parser_node, operand_type, operand_value, operand_length) elsif parser_node^.kind = ElnaTreeKind.null then instruction := _elna_tac_nil_literal(parser_node, operand_type, operand_value, operand_length) else @@ -2105,7 +2141,7 @@ end; proc elna_parser_call(callee: Word); var parsed_expression: Word; - result: ^_statement; + result: ^ElnaTreeStatement; argument_number: Word; token_kind: Word; begin @@ -2230,7 +2266,7 @@ var token_kind: Word; label_name: Word; label_length: Word; - result: ^_goto_statement; + result: ^ElnaTreeGotoStatement; begin _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); @@ -2239,7 +2275,7 @@ begin label_length := _elna_lexer_global_get_end() - label_name; _elna_lexer_skip_token(); - result := malloc(_goto_statement_size()); + result := malloc(ElnaTreeGotoStatement_size()); result^.kind := ElnaTreeKind.goto_statement; result^.next := nil; @@ -2249,7 +2285,7 @@ begin return result end; -proc _elna_tac_goto_statement(parser_node: ^_goto_statement); +proc _elna_tac_goto_statement(parser_node: ^ElnaTreeGotoStatement); var label_length: Word; label_with_dot: Word; @@ -2271,7 +2307,7 @@ var token_kind: Word; label_name: Word; label_length: Word; - result: ^_goto_statement; + result: ^ElnaTreeGotoStatement; begin _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); @@ -2280,7 +2316,7 @@ begin label_length := _elna_lexer_global_get_end() - label_name; _elna_lexer_skip_token(); - result := malloc(_label_declaration_size()); + result := malloc(ElnaTreeLabelDeclaration_size()); result^.kind := ElnaTreeKind.label_declaration; result^.next := nil; @@ -2290,7 +2326,7 @@ begin return result end; -proc _elna_tac_label_declaration(parser_node: ^_label_declaration); +proc _elna_tac_label_declaration(parser_node: ^ElnaTreeLabelDeclaration); return _elna_tac_label(parser_node^.label, parser_node^.length) end; @@ -2447,10 +2483,10 @@ end; proc elna_parser_assign_statement(assignee: Word); var - result: ^_assign_statement; + result: ^ElnaTreeAssignStatement; token_kind: Word; begin - result := malloc(_assign_statement_size()); + result := malloc(ElnaTreeAssignStatement_size()); result^.kind := ElnaTreeKind.assign_statement; result^.next := nil; @@ -2465,7 +2501,7 @@ begin return result end; -proc _elna_tac_assign_statement(parser_tree: ^_assign_statement, symbol_table: Word); +proc _elna_tac_assign_statement(parser_tree: ^ElnaTreeAssignStatement, symbol_table: Word); var is_address: Word; first_instruction: Word; @@ -2523,14 +2559,14 @@ var token_kind: Word; returned: Word; label_length: Word; - result: ^_return_statement; + result: ^ElnaTreeReturnStatement; begin (* Skip "return" keyword and whitespace after it. *) _elna_lexer_skip_token(); _elna_lexer_read_token(@token_kind); returned := elna_parser_binary_expression(); - result := malloc(_return_statement_size()); + result := malloc(ElnaTreeReturnStatement_size()); result^.kind := ElnaTreeKind.return_statement; result^.next := nil; @@ -2539,7 +2575,7 @@ begin return result end; -proc _elna_tac_return_statement(parser_node: ^_return_statement, symbol_table: Word); +proc _elna_tac_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word); var first_instruction: Word; instruction: Word; @@ -2583,9 +2619,9 @@ end; proc elna_parser_conditional_statements(); var token_kind: Word; - result: ^_conditional_statements; + result: ^ElnaTreeConditionalStatements; begin - result := malloc(_conditional_statements_size()); + result := malloc(ElnaTreeConditionalStatements_size()); (* Skip "if", "while" or "elsif". *) _elna_lexer_skip_token(); @@ -2601,7 +2637,7 @@ begin return result end; -proc _elna_tac_conditional_statements(parser_node: ^_conditional_statements, after_end_label: Word, symbol_table: Word); +proc _elna_tac_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, after_end_label: Word, symbol_table: Word); var condition_label: Word; instruction: Word; @@ -2645,12 +2681,12 @@ end; proc elna_parser_if_statement(); var - result: ^_if_statement; + result: ^ElnaTreeIfStatement; token_kind: Word; - previous_conditional: ^_conditional_statements; - next_conditional: ^_conditional_statements; + previous_conditional: ^ElnaTreeConditionalStatements; + next_conditional: ^ElnaTreeConditionalStatements; begin - result := malloc(_if_statement_size()); + result := malloc(ElnaTreeIfStatement_size()); result^.kind := ElnaTreeKind.if_statement; result^.next := nil; @@ -2707,9 +2743,9 @@ end; proc elna_parser_statements(); var token_kind: Word; - previous_statement: ^_statement; - next_statement: ^_statement; - first_statement: ^_statement; + previous_statement: ^ElnaTreeStatement; + next_statement: ^ElnaTreeStatement; + first_statement: ^ElnaTreeStatement; begin _skip_empty_lines(); @@ -2741,7 +2777,7 @@ end; proc _elna_tac_statements(parser_node: Word, symbol_table: Word); var - current_statement: ^_statement; + current_statement: ^ElnaTreeStatement; instruction: Word; first_instruction: Word; current_instruction: Word; @@ -2767,9 +2803,9 @@ begin return first_instruction end; -proc _elna_tac_if_statement(parser_node: ^_if_statement, symbol_table: Word); +proc _elna_tac_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word); var - current_node: ^_conditional_statements; + current_node: ^ElnaTreeConditionalStatements; after_end_label: Word; condition_label: Word; first_instruction: Word; @@ -3269,7 +3305,7 @@ end; * Parameters: * parameter_index - Parameter index. *) -proc elna_name_procedure_parameter(parser_node: ^_variable_declaration, parameter_index: Word, symbol_table: Word); +proc elna_name_procedure_parameter(parser_node: ^ElnaTreeVariableDeclaration, parameter_index: Word, symbol_table: Word); var info: Word; variable_type: Word; @@ -3284,7 +3320,7 @@ end; * Parameters: * variable_index - Variable index. *) -proc elna_name_procedure_temporary(parser_node: ^_variable_declaration, variable_index: Word, symbol_table: Word); +proc elna_name_procedure_temporary(parser_node: ^ElnaTreeVariableDeclaration, variable_index: Word, symbol_table: Word); var info: Word; variable_type: Word; @@ -3295,7 +3331,7 @@ begin _symbol_table_enter(symbol_table, parser_node^.name, parser_node^.length, info) end; -proc elna_name_procedure_temporaries(parser_node: ^_variable_declaration, symbol_table: Word); +proc elna_name_procedure_temporaries(parser_node: ^ElnaTreeVariableDeclaration, symbol_table: Word); var temporary_counter: Word; begin @@ -3313,13 +3349,13 @@ end; proc elna_parser_procedure_declaration(); var - next_declaration: ^_declaration; - current_declaration: ^_declaration; + next_declaration: ^ElnaTreeDeclaration; + current_declaration: ^ElnaTreeDeclaration; token_kind: Word; - result: ^_procedure_declaration; - parameter_head: ^_declaration; + result: ^ElnaTreeProcedureDeclaration; + parameter_head: ^ElnaTreeDeclaration; begin - result := malloc(_procedure_declaration_size()); + result := malloc(ElnaTreeProcedureDeclaration_size()); result^.kind := ElnaTreeKind.procedure_declaration; result^.next := nil; @@ -3386,7 +3422,7 @@ begin return result end; -proc _elna_tac_parameters(current_parameter: ^_declaration, new_symbol_table: Word); +proc _elna_tac_parameters(current_parameter: ^ElnaTreeDeclaration, new_symbol_table: Word); var name_pointer: Word; name_length: Word; @@ -3460,7 +3496,7 @@ begin return result end; -proc _elna_tac_procedure_declaration(parser_node: _procedure_declaration); +proc _elna_tac_procedure_declaration(parser_node: ElnaTreeProcedureDeclaration); var current_parameter: Word; new_symbol_table: Word; @@ -3494,9 +3530,9 @@ end; proc elna_parser_procedures(); var - parser_node: ^_declaration; - result: ^_declaration; - current_declaration: ^_declaration; + parser_node: ^ElnaTreeDeclaration; + result: ^ElnaTreeDeclaration; + current_declaration: ^ElnaTreeDeclaration; token_kind: Word; begin result := nil; @@ -3579,7 +3615,7 @@ begin return first_copy end; -proc _elna_tac_procedures(parser_node: ^_declaration); +proc _elna_tac_procedures(parser_node: ^ElnaTreeDeclaration); var result: Word; current_procedure: ^ElnaInstructionList; @@ -3628,7 +3664,7 @@ var token_kind: Word; type_name: Word; name_length: Word; - result: ^_type_declaration; + result: ^ElnaTreeTypeDeclaration; begin _elna_lexer_read_token(@token_kind); type_name := _elna_lexer_global_get_start(); @@ -3638,7 +3674,7 @@ begin _elna_lexer_read_token(@token_kind); _elna_lexer_skip_token(); - result := malloc(_type_declaration_size()); + result := malloc(ElnaTreeTypeDeclaration_size()); result^.kind := ElnaTreeKind.type_declaration; result^.next := nil; @@ -3652,7 +3688,7 @@ begin return result end; -proc elna_name_type_declaration(parser_node: ^_type_declaration); +proc elna_name_type_declaration(parser_node: ^ElnaTreeTypeDeclaration); var type_name: Word; name_length: Word; @@ -3675,9 +3711,9 @@ end; proc elna_parser_type_part(); var token_kind: Word; - parser_node: ^_declaration; - result: ^_declaration; - current_declaration: ^_declaration; + parser_node: ^ElnaTreeDeclaration; + result: ^ElnaTreeDeclaration; + current_declaration: ^ElnaTreeDeclaration; begin result := nil; _skip_empty_lines(); @@ -3714,7 +3750,7 @@ var name: Word; name_length: Word; variable_type: Word; - result: ^_variable_declaration; + result: ^ElnaTreeVariableDeclaration; begin _elna_lexer_read_token(@token_kind); @@ -3727,7 +3763,7 @@ begin _elna_lexer_skip_token(); variable_type := elna_parser_type_expression(); - result := malloc(_variable_declaration_size()); + result := malloc(ElnaTreeVariableDeclaration_size()); result^.kind := ElnaTreeKind.variable_declaration; result^.next := nil; @@ -3738,7 +3774,7 @@ begin return result end; -proc _elna_tac_variable_declaration(parser_tree: ^_variable_declaration); +proc _elna_tac_variable_declaration(parser_tree: ^ElnaTreeVariableDeclaration); var name: Word; name_length: Word; @@ -3798,7 +3834,7 @@ begin return result end; -proc _elna_tac_type_part(parser_node: ^_declaration); +proc _elna_tac_type_part(parser_node: ^ElnaTreeDeclaration); var result: Word; first_result: Word; @@ -3844,7 +3880,7 @@ var result: Word; token_kind: Word; variable_node: Word; - current_declaration: ^_declaration; + current_declaration: ^ElnaTreeDeclaration; begin result := 0; _elna_lexer_read_token(@token_kind); @@ -3879,7 +3915,7 @@ begin return result end; -proc _elna_tac_var_part(parser_node: ^_declaration); +proc _elna_tac_var_part(parser_node: ^ElnaTreeDeclaration); var node: Word; current_variable: ^ElnaInstructionList; @@ -3911,10 +3947,10 @@ end; proc elna_parser_module_declaration(); var parser_node: Word; - result: ^_module_declaration; + result: ^ElnaTreeModuleDeclaration; token_kind: Word; begin - result := malloc(_module_declaration_size()); + result := malloc(ElnaTreeModuleDeclaration_size()); result^.kind := ElnaTreeKind.module_declaration; (* Skip "program;". *) @@ -3934,7 +3970,7 @@ end; (** * Process the source code and print the generated code. *) -proc _elna_tac_module_declaration(parser_node: ^_module_declaration); +proc _elna_tac_module_declaration(parser_node: ^ElnaTreeModuleDeclaration); var data_part: Word; code_part: Word; @@ -3960,12 +3996,12 @@ begin return elna_instruction_module_create(data_part, code_part) end; -proc elna_name_procedure_declaration(parser_node: ^_procedure_declaration); +proc elna_name_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration); var new_symbol_table: Word; parameter_counter: Word; symbol_info: Word; - current_parameter: ^_declaration; + current_parameter: ^ElnaTreeDeclaration; begin new_symbol_table := _symbol_table_create(); symbol_info := _procedure_info_create(new_symbol_table); @@ -3985,7 +4021,7 @@ begin _symbol_table_enter(@symbol_table_global, parser_node^.name, parser_node^.length, symbol_info) end; -proc elna_type_conditional_statements(parser_node: ^_conditional_statements, symbol_table: Word); +proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: Word); begin .elna_type_conditional_statements_loop; elna_type_binary_expression(parser_node^.condition, symbol_table); @@ -3997,9 +4033,9 @@ begin end end; -proc elna_type_if_statement(parser_node: ^_if_statement, symbol_table: Word); +proc elna_type_if_statement(parser_node: ^ElnaTreeIfStatement, symbol_table: Word); var - block: ^_conditional_statements; + block: ^ElnaTreeConditionalStatements; begin block := parser_node^.conditionals; @@ -4016,7 +4052,7 @@ begin end end; -proc elna_type_return_statement(parser_node: ^_return_statement, symbol_table: Word); +proc elna_type_return_statement(parser_node: ^ElnaTreeReturnStatement, symbol_table: Word); begin elna_type_binary_expression(parser_node^.returned, symbol_table) end; @@ -4039,7 +4075,7 @@ begin end end; -proc elna_type_assign_statement(parser_node: ^_assign_statement, symbol_table: Word); +proc elna_type_assign_statement(parser_node: ^ElnaTreeAssignStatement, symbol_table: Word); begin elna_type_designator(parser_node^.assignee, symbol_table); elna_type_binary_expression(parser_node^.assignment, symbol_table) @@ -4059,7 +4095,7 @@ begin end end; -proc elna_type_statements(parser_node: ^_statement, symbol_table: Word); +proc elna_type_statements(parser_node: ^ElnaTreeStatement, symbol_table: Word); begin .elna_type_statements_loop; if parser_node <> nil then @@ -4094,11 +4130,19 @@ begin parser_node^.type_decoration := symbol_info^._type end; +proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral); +var + symbol_info: ^_type_info; +begin + symbol_info := _symbol_table_lookup(@symbol_table_global, "Bool", 4); + parser_node^.type_decoration := symbol_info^._type +end; + proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral); var symbol_info: ^_type_info; begin - symbol_info := _symbol_table_lookup(@symbol_table_global, "Word", 4); + symbol_info := _symbol_table_lookup(@symbol_table_global, "Pointer", 7); parser_node^.type_decoration := symbol_info^._type end; @@ -4131,6 +4175,8 @@ begin elna_type_character_literal(parser_node) elsif parser_node^.kind = ElnaTreeKind.string_literal then elna_type_string_literal(parser_node) + elsif parser_node^.kind = ElnaTreeKind.boolean_literal then + elna_type_boolean_literal(parser_node) elsif parser_node^.kind = ElnaTreeKind.null then elna_type_nil_literal(parser_node) elsif parser_node^.kind = ElnaTreeKind.variable_expression then @@ -4250,7 +4296,7 @@ begin end end; -proc elna_type_procedure_declaration(parser_node: ^_procedure_declaration); +proc elna_type_procedure_declaration(parser_node: ^ElnaTreeProcedureDeclaration); var procedure_info: ^_procedure_info; symbol_table: Word; @@ -4261,9 +4307,9 @@ begin elna_type_statements(parser_node^.body, symbol_table) end; -proc elna_name_module_declaration(parser_node: ^_module_declaration); +proc elna_name_module_declaration(parser_node: ^ElnaTreeModuleDeclaration); var - current_part: ^_declaration; + current_part: ^ElnaTreeDeclaration; begin current_part := parser_node^.types; .elna_name_module_declaration_type; @@ -4291,9 +4337,9 @@ begin end end; -proc elna_type_module_declaration(parser_node: ^_module_declaration); +proc elna_type_module_declaration(parser_node: ^ElnaTreeModuleDeclaration); var - current_part: ^_declaration; + current_part: ^ElnaTreeDeclaration; begin current_part := parser_node^.types; .elna_type_module_declaration_type; @@ -4462,14 +4508,28 @@ begin (* Set the table length to 0. *) symbol_table_global := 0; + (* Enter built-in symbols. *) current_type := malloc(ElnaType_size()); current_type^.kind := ElnaTypeKind.primitive; current_type^.size := 4; - - (* Enter built-in symbols. *) current_info := _type_info_create(current_type); _symbol_table_enter(@symbol_table_global, "Word", 4, current_info); + current_type := malloc(ElnaType_size()); + current_type^.kind := ElnaTypeKind.primitive; + current_type^.size := 4; + current_info := _type_info_create(current_type); + _symbol_table_enter(@symbol_table_global, "Pointer", 7, current_info); + + current_type := malloc(ElnaType_size()); + current_type^.kind := ElnaTypeKind.primitive; + current_type^.size := 1; + current_info := _type_info_create(current_type); + _symbol_table_enter(@symbol_table_global, "Bool", 4, current_info); + + current_type := malloc(ElnaType_size()); + current_type^.kind := ElnaTypeKind.primitive; + current_type^.size := 4096; current_info := _type_info_create(current_type); _symbol_table_enter(@symbol_table_global, "Array", 5, current_info) end; @@ -5034,6 +5094,10 @@ begin result := ElnaLexerKind._module elsif string_compare(position_start, token_length, "nil", 3) then result := ElnaLexerKind.null + elsif string_compare(position_start, token_length, "true", 4) then + result := ElnaLexerKind.boolean + elsif string_compare(position_start, token_length, "false", 5) then + result := ElnaLexerKind.boolean end; return result end;