summaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
Diffstat (limited to 'boot')
-rw-r--r--boot/stage20/cl.elna821
1 files changed, 389 insertions, 432 deletions
diff --git a/boot/stage20/cl.elna b/boot/stage20/cl.elna
index d47c418..99a8ab1 100644
--- a/boot/stage20/cl.elna
+++ b/boot/stage20/cl.elna
@@ -438,16 +438,17 @@ type
_goto,
eof
);
- ElnaLexerCursor = record
- state: ElnaLexerState;
- start: Word;
- finish: Word
- end;
ElnaLexerToken = record
kind: ElnaLexerKind;
start: Word;
length: Word
end;
+ ElnaLexerCursor = record
+ state: ElnaLexerState;
+ start: Word;
+ finish: Word;
+ token: ^ElnaLexerToken
+ end;
ElnaTacOperator = (
get_address,
@@ -768,6 +769,9 @@ begin
list^.last := nil
end;
+(**
+ * Appends a new element to the end of the list.
+ *)
proc elna_list_append(list: ^ElnaList, element: ^ElnaListNode);
begin
if element <> nil then
@@ -781,6 +785,31 @@ begin
return element
end;
+(**
+ * Prepends a new element to the beginning of the given list.
+ *)
+proc elna_list_prepend(list: ^ElnaList, element: ^ElnaListNode);
+begin
+ element^.next := list^.first;
+ list^.first := element;
+ if list^.last = nil then
+ list^.last := element
+ end
+end;
+
+(**
+ * Inserts a new element after an existing one into the given list.
+ *)
+proc elna_list_insert(list: ^ElnaList, existing: ^ElnaListNode, new: ^ElnaListNode);
+begin
+ if existing^.next = nil then
+ list^.last := new
+ else
+ new^.next := existing^.next
+ end;
+ existing^.next := new
+end;
+
proc elna_tac_generate_pseudo(operand_type: Word, operand_value: Word, operand_length: Word, symbol_table: ^ElnaSymbolTable);
var
buffer: Word;
@@ -799,28 +828,6 @@ begin
elna_symbol_table_enter(symbol_table, buffer, operand_length^, temporary_info)
end;
-proc elna_instruction_list_concatenate(this: ^ElnaListNode, value: Word);
-var
- start: Word;
-begin
- if this = 0 then
- start := value;
- goto elna_instruction_list_concatenate_end
- else
- start := this
- end;
- .elna_instruction_list_concatenate_loop;
- if value <> 0 then
- if this^ <> 0 then
- this := this^;
- goto elna_instruction_list_concatenate_loop
- end
- end;
- this^ := value;
- .elna_instruction_list_concatenate_end;
- return start
-end;
-
proc elna_tac_instruction_set_operand(this: ^ElnaTacInstruction, n: Word, operand_type: Word, operand_value: Word, operand_length: Word);
begin
this^.operands[n].kind := operand_type;
@@ -1314,26 +1321,25 @@ end;
* to be a register, but is not a register, then this procedure rewrites it
* to a temporary register and preserves its value in the following instruction.
*)
-proc elna_alloc_operation_target(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_operation_target(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
store_instruction: ^ElnaRtlInstruction;
begin
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
store_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
- store_instruction^.next := instruction^.next;
-
pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
variable_map);
+
elna_rtl_instruction_set_operand(store_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(store_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
- instruction^.next := store_instruction;
- elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0)
+ elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
+ elna_list_insert(instructions, instruction, store_instruction)
end
end;
-proc elna_alloc_load_address(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_load_address(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
begin
@@ -1346,18 +1352,21 @@ begin
elna_rtl_instruction_set_operand(instruction, 3, ElnaRtlKind.immediate, pseudo_symbol^.counter, 0)
end;
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
end
end;
-proc elna_alloc_store(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_store(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
old_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
- old_instruction := malloc(#size(ElnaRtlInstruction));
- memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
+ old_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
+
+ elna_rtl_instruction_set_operand(old_instruction, 1, instruction^.operands[1].kind,
+ instruction^.operands[1].value, instruction^.operands[1].length);
+ elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0);
pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
variable_map);
@@ -1365,85 +1374,83 @@ begin
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
-
- instruction^.next := old_instruction;
- elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.t1, 0)
+ elna_list_insert(instructions, instruction, old_instruction)
end
end;
-proc elna_alloc_load(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_load(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
- old_instruction: ^ElnaRtlInstruction;
+ new_instruction: ^ElnaRtlInstruction;
pseudo_symbol: ^ElnaRtlInfo;
begin
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- old_instruction := malloc(#size(ElnaRtlInstruction));
- memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
-
pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
variable_map);
- old_instruction^.operator := ElnaRtlOperator.sw;
+ new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.sw);
- elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
- elna_rtl_instruction_set_operand(old_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
+ elna_rtl_instruction_set_operand(new_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
+ elna_rtl_instruction_set_operand(new_instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
- instruction^.next := old_instruction;
- elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0)
+ elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t1, 0);
+ elna_list_insert(instructions, instruction, new_instruction)
end
end;
-proc elna_alloc_instruction(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_move(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
var
pseudo_symbol: ^ElnaRtlInfo;
- old_instruction: ^ElnaRtlInstruction;
begin
- if instruction^.operator = ElnaRtlOperator.move then
- if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
- variable_map);
- instruction^.operator = ElnaRtlOperator.sw;
-
- instruction^.operands[1].kind := instruction^.operands[2].kind;
- instruction^.operands[1].value := instruction^.operands[2].value;
- instruction^.operands[1].length := instruction^.operands[2].length;
- elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
+ if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
+ variable_map);
+ instruction^.operator = ElnaRtlOperator.sw;
- goto elna_alloc_instruction_end
- end;
- if instruction^.operands[2].kind = ElnaRtlKind.pseudo then
- pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
- variable_map);
- instruction^.operator = ElnaRtlOperator.lw;
- elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
+ elna_rtl_instruction_set_operand(instruction, 1, instruction^.operands[2].kind,
+ instruction^.operands[2].value, instruction^.operands[2].length);
+ elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter)
+ elsif instruction^.operands[2].kind = ElnaRtlKind.pseudo then
+ pseudo_symbol := elna_alloc_variable(instruction^.operands[2].value, instruction^.operands[2].length,
+ variable_map);
+ instruction^.operator = ElnaRtlOperator.lw;
+ elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter)
+ end
+end;
- goto elna_alloc_instruction_end
- end
+proc elna_alloc_instruction(instructions: ^ElnaList, instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+var
+ pseudo_symbol: ^ElnaRtlInfo;
+ new_instruction: ^ElnaRtlInstruction;
+begin
+ if instruction^.operator = ElnaRtlOperator.move then
+ elna_alloc_move(instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.la then
- elna_alloc_load_address(instruction, variable_map)
+ elna_alloc_load_address(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.lw then
- elna_alloc_load(instruction, variable_map)
+ elna_alloc_load(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sw then
- elna_alloc_store(instruction, variable_map)
+ elna_alloc_store(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._or then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.and then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.mul then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.sub then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.add then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator._xor then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.rem then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.slt then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.beqz then
if instruction^.operands[1].kind = ElnaRtlKind.pseudo then
- old_instruction := malloc(#size(ElnaRtlInstruction));
- memcpy(old_instruction, instruction, #size(ElnaRtlInstruction));
+ new_instruction := elna_rtl_instruction_create(ElnaRtlOperator.beqz);
+ elna_rtl_instruction_set_operand(new_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
+ elna_rtl_instruction_set_operand(new_instruction, 2, instruction^.operands[2].kind,
+ instruction^.operands[2].value, instruction^.operands[2].length);
pseudo_symbol := elna_alloc_variable(instruction^.operands[1].value, instruction^.operands[1].length,
variable_map);
@@ -1452,19 +1459,15 @@ begin
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
elna_rtl_instruction_set_operand(instruction, 2, ElnaRtlKind.offset, ElnaRtlRegister.sp, pseudo_symbol^.counter);
- instruction^.next := old_instruction;
- elna_rtl_instruction_set_operand(old_instruction, 1, ElnaRtlKind.register, ElnaRtlRegister.t0, 0);
-
- goto elna_alloc_instruction_end
+ elna_list_insert(instructions, instruction, new_instruction)
end
elsif instruction^.operator = ElnaRtlOperator.seqz then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.snez then
- elna_alloc_operation_target(instruction, variable_map)
+ elna_alloc_operation_target(instructions, instruction, variable_map)
elsif instruction^.operator = ElnaRtlOperator.xori then
- elna_alloc_operation_target(instruction, variable_map)
- end;
- .elna_alloc_instruction_end;
+ elna_alloc_operation_target(instructions, instruction, variable_map)
+ end
end;
proc elna_riscv_instruction(instruction: ^ElnaRtlInstruction);
@@ -1529,12 +1532,16 @@ begin
end
end;
-proc elna_alloc_instructions(instruction: ^ElnaRtlInstruction, variable_map: ^ElnaSymbolTable);
+proc elna_alloc_instructions(instructions: ^ElnaList, variable_map: ^ElnaSymbolTable);
+var
+ instruction: ^ElnaRtlInstruction;
begin
+ instruction := instructions^.first;
+
.elna_alloc_instructions_start;
if instruction <> nil then
- elna_alloc_instruction(instruction, variable_map);
+ elna_alloc_instruction(instructions, instruction, variable_map);
instruction := instruction^.next;
goto elna_alloc_instructions_start
end
@@ -1557,17 +1564,16 @@ begin
.elna_alloc_procedure_loop;
temporary_variable_counter := 0;
- elna_alloc_instructions(rtl_declaration^.body.first, rtl_declaration^.variable_map);
+ elna_alloc_instructions(@rtl_declaration^.body, rtl_declaration^.variable_map);
stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.allocate_stack);
- stack_instruction^.next := rtl_declaration^.body.first;
elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0);
+ elna_list_prepend(@rtl_declaration^.body, stack_instruction);
- rtl_declaration^.body := stack_instruction;
stack_instruction := elna_rtl_instruction_create(ElnaRtlOperator.ret);
elna_rtl_instruction_set_operand(stack_instruction, 1, ElnaRtlKind.immediate, temporary_variable_counter, 0);
- elna_instruction_list_concatenate(rtl_declaration^.body, stack_instruction);
+ elna_list_append(@rtl_declaration^.body, stack_instruction);
rtl_declaration := rtl_declaration^.next;
if rtl_declaration <> nil then
@@ -1660,17 +1666,16 @@ end;
proc elna_parser_integer_literal(cursor: ^ElnaLexerCursor);
var
- integer_length: Word;
+ token: ^ElnaLexerToken;
result: ^ElnaTreeIntegerLiteral;
buffer: Word;
begin
result := malloc(#size(ElnaTreeIntegerLiteral));
- integer_length := cursor^.finish - cursor^.start;
+ token := elna_lexer_read(cursor);
- buffer := malloc(integer_length + 1);
- bzero(buffer, integer_length + 1);
- memcpy(buffer, cursor^.start, integer_length);
- elna_lexer_skip_token(cursor);
+ buffer := malloc(token^.length + 1);
+ bzero(buffer, token^.length + 1);
+ memcpy(buffer, token^.start, token^.length);
result^.kind := ElnaTreeKind.integer_literal;
result^.value := atoi(buffer);
@@ -1689,7 +1694,7 @@ begin
result^.value := string_compare(cursor^.start, 4, "true", 4);
result^.type_decoration := nil;
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -1698,7 +1703,7 @@ proc elna_parser_nil_literal(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeNilLiteral;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeNilLiteral));
result^.kind := ElnaTreeKind.null;
@@ -1731,14 +1736,15 @@ end;
proc elna_parser_character_literal(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeCharacterLiteral;
+ token: ^ElnaLexerToken;
begin
result := malloc(#size(ElnaTreeCharacterLiteral));
+ token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.character_literal;
- result^.value := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
+ result^.value := token^.start;
+ result^.length := token^.length;
result^.type_decoration := nil;
- elna_lexer_skip_token(cursor);
return result
end;
@@ -1753,16 +1759,16 @@ end;
proc elna_parser_variable_expression(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeVariableExpression;
+ token: ^ElnaLexerToken;
begin
result := malloc(#size(ElnaTreeVariableExpression));
+ token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.variable_expression;
- result^.name := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
+ result^.name := token^.start;
+ result^.length := token^.length;
result^.type_decoration := nil;
- elna_lexer_skip_token(cursor);
-
return result
end;
@@ -1787,16 +1793,16 @@ end;
proc elna_parser_string_literal(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeStringLiteral;
+ token: ^ElnaLexerToken;
begin
result := malloc(#size(ElnaTreeStringLiteral));
+ token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.string_literal;
- result^.value := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
+ result^.value := token^.start;
+ result^.length := token^.length;
result^.type_decoration := nil;
- elna_lexer_skip_token(cursor);
-
return result
end;
@@ -1826,21 +1832,20 @@ end;
proc elna_parser_trait_expression(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeTraitExpression;
+ token: ^ElnaLexerToken;
begin
result := malloc(#size(ElnaTreeTraitExpression));
result^.kind := ElnaTreeKind.trait_expression;
- result^.name := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
+ token := elna_lexer_read(cursor);
+ result^.name := token^.start;
+ result^.length := token^.length;
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result^.argument := elna_parser_type_expression(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -1852,7 +1857,7 @@ var
token: ^ElnaLexerToken;
begin
parser_node := 0;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.character then
parser_node := elna_parser_character_literal(cursor)
@@ -1881,7 +1886,7 @@ begin
result^.kind := ElnaTreeKind.dereference_expression;
result^.pointer := simple_expression;
result^.type_decoration := nil;
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -1894,7 +1899,7 @@ begin
simple_expression := elna_parser_simple_expression(cursor);
.elna_parser_designator_loop;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.hat then
simple_expression := elna_parser_dereference_expression(cursor, simple_expression);
@@ -1954,7 +1959,7 @@ var
operator: Word;
token: ^ElnaLexerToken;
begin
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
operator := 0;
if token^.kind = ElnaLexerKind.at then
@@ -1965,7 +1970,7 @@ begin
operator := '~'
end;
if operator <> 0 then
- elna_lexer_skip_token(cursor)
+ elna_lexer_read(cursor)
end;
result := elna_parser_designator(cursor);
@@ -2055,49 +2060,49 @@ var
begin
lhs_node := elna_parser_unary_expression(cursor);
rhs_node := 0;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.plus then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.minus then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.multiplication then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.and then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind._or then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind._xor then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.equals then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.remainder then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.division then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.less_than then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.greater_than then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.less_equal then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.not_equal then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
elsif token^.kind = ElnaLexerKind.greater_equal then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
rhs_node := elna_parser_unary_expression(cursor)
end;
if rhs_node <> 0 then
@@ -2181,12 +2186,11 @@ begin
argument_number := 1;
result^.callee := callee;
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
- token := elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.right_paren then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
goto elna_parser_call_end
end;
@@ -2202,8 +2206,7 @@ begin
argument_entry^.expression := elna_parser_binary_expression(cursor);
argument_number := argument_number + 1;
- token := elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind = ElnaLexerKind.comma then
goto elna_parser_call_loop
@@ -2249,17 +2252,16 @@ end;
proc elna_parser_goto_statement(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeGotoStatement;
+ token: ^ElnaLexerToken;
begin
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
+ token := elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeGotoStatement));
result^.kind := ElnaTreeKind.goto_statement;
result^.next := nil;
- result^.label := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
-
- elna_lexer_skip_token(cursor);
+ result^.label := token^.start;
+ result^.length := token^.length;
return result
end;
@@ -2284,18 +2286,17 @@ end;
proc elna_parser_label_declaration(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeGotoStatement;
+ token: ^ElnaLexerToken;
begin
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
+ token := elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeLabelDeclaration));
result^.kind := ElnaTreeKind.label_declaration;
result^.next := nil;
- result^.label := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
-
- elna_lexer_skip_token(cursor);
+ result^.label := token^.start;
+ result^.length := token^.length;
return result
end;
@@ -2348,20 +2349,19 @@ end;
proc elna_parser_field_access_expression(cursor: ^ElnaLexerCursor, aggregate: Word);
var
result: ^ElnaTreeFieldAccessExpression;
+ token: ^ElnaLexerToken;
begin
(* Skip dot. Read the enumeration value. *)
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
+ token := elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeFieldAccessExpression));
result^.kind := ElnaTreeKind.field_access_expression;
result^.type_decoration := nil;
result^.aggregate := aggregate;
- result^.field := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
-
- elna_lexer_skip_token(cursor);
+ result^.field := token^.start;
+ result^.length := token^.length;
return result
end;
@@ -2370,7 +2370,7 @@ proc elna_parser_array_access_expression(cursor: ^ElnaLexerCursor, array: Word);
var
result: ^ElnaTreeArrayAccessExpression;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeArrayAccessExpression));
@@ -2379,8 +2379,7 @@ begin
result^.array := array;
result^.index := elna_parser_binary_expression(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -2530,9 +2529,7 @@ begin
result^.assignee := assignee;
(* Skip the assignment sign (:=) with surrounding whitespaces. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
-
+ elna_lexer_read(cursor);
result^.assignment := elna_parser_binary_expression(cursor);
return result
@@ -2601,8 +2598,7 @@ var
result: ^ElnaTreeReturnStatement;
begin
(* Skip "return" keyword and whitespace after it. *)
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
returned := elna_parser_binary_expression(cursor);
result := malloc(#size(ElnaTreeReturnStatement));
@@ -2651,14 +2647,13 @@ begin
result := malloc(#size(ElnaTreeConditionalStatements));
(* Skip "if", "while" or "elsif". *)
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result^.condition := elna_parser_binary_expression(cursor);
(* Skip "then" or "do". *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
- result^.statements := elna_parser_statements();
+ result^.statements := elna_parser_statements(cursor);
result^.next := nil;
return result
@@ -2708,7 +2703,7 @@ begin
result^.conditionals := previous_conditional;
.elna_parser_if_statement_loop;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind._elsif then
next_conditional := elna_parser_conditional_statements(cursor);
@@ -2717,12 +2712,12 @@ begin
goto elna_parser_if_statement_loop
elsif token^.kind = ElnaLexerKind._else then
- elna_lexer_skip_token(cursor);
- result^._else := elna_parser_statements()
+ elna_lexer_read(cursor);
+ result^._else := elna_parser_statements(cursor)
else
result^._else := nil
end;
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -2733,7 +2728,7 @@ var
token: ^ElnaLexerToken;
begin
result := nil;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind._goto then
result := elna_parser_goto_statement(cursor)
@@ -2769,10 +2764,10 @@ begin
end;
.elna_parser_statement_loop;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.semicolon then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
elna_lexer_skip_empty_lines(cursor);
next_statement := elna_parser_statement(cursor);
previous_statement^.next := next_statement;
@@ -2870,11 +2865,11 @@ var
previous_entry: Word;
token: ^ElnaLexerToken;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
member_count := 0;
memory_start := 0;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind = ElnaLexerKind._end then
goto elna_parser_record_type_expression_end
end;
@@ -2882,16 +2877,14 @@ begin
entry := malloc(16);
member_count := member_count + 1;
- entry^ := cursor^.start;
+ entry^ := token^.start;
entry := entry + 4;
- entry^ := cursor^.finish - cursor^.start;
+ entry^ := token^.length;
entry := entry + 4;
- (* Skip the identifier. *)
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ (* Skip the colon. *)
+ elna_lexer_read(cursor);
field_type := elna_parser_type_expression(cursor);
@@ -2906,15 +2899,12 @@ begin
end;
previous_entry := entry;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind = ElnaLexerKind.semicolon then
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
+ token := elna_lexer_read(cursor);
goto elna_parser_record_type_expression_loop
end;
-
.elna_parser_record_type_expression_end;
- elna_lexer_skip_token(cursor);
result := malloc(#size(ElnaTreeEnumerationTypeExpression));
@@ -2934,22 +2924,19 @@ var
previous_entry: Word;
token: ^ElnaLexerToken;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
memory_start := 0;
member_count := 0;
- token := elna_lexer_read_token(cursor);
- if token^.kind = ElnaLexerKind.right_paren then
- goto elna_parser_enumeration_type_expression_end
- end;
.elna_parser_enumeration_type_expression_loop;
+ token := elna_lexer_read(cursor);
entry := malloc(12);
member_count := member_count + 1;
- entry^ := cursor^.start;
+ entry^ := token^.start;
entry := entry + 4;
- entry^ := cursor^.finish - cursor^.start;
+ entry^ := token^.length;
entry := entry + 4;
entry^ := 0;
@@ -2961,18 +2948,10 @@ begin
previous_entry := entry;
(* Skip the identifier. *)
- elna_lexer_skip_token(cursor);
-
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind = ElnaLexerKind.comma then
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
goto elna_parser_enumeration_type_expression_loop
end;
-
- .elna_parser_enumeration_type_expression_end;
- elna_lexer_skip_token(cursor);
-
result := malloc(#size(ElnaTreeEnumerationTypeExpression));
result^.kind := ElnaTreeKind.enumeration_type_expression;
@@ -3117,13 +3096,14 @@ end;
proc elna_parser_named_type_expression(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeNamedTypeExpression;
+ token: ^ElnaLexerToken;
begin
result := malloc(#size(ElnaTreeNamedTypeExpression));
+ token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.named_type_expression;
- result^.name := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
- elna_lexer_skip_token(cursor);
+ result^.name := token^.start;
+ result^.length := token^.length;
return result
end;
@@ -3132,7 +3112,7 @@ proc elna_parser_pointer_type_expression(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreePointerTypeExpression;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result := malloc(#size(ElnaTreePointerTypeExpression));
result^.kind := ElnaTreeKind.pointer_type_expression;
@@ -3145,15 +3125,14 @@ proc elna_parser_array_type_expression(cursor: ^ElnaLexerCursor);
var
result: ^ElnaTreeArrayTypeExpression;
begin
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result := malloc(#size(ElnaTreeArrayTypeExpression));
result^.kind := ElnaTreeKind.array_type_expression;
result^.length := elna_parser_binary_expression(cursor);
(* Read and skip square bracket. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result^.base := elna_parser_type_expression(cursor);
@@ -3166,7 +3145,7 @@ var
token: ^ElnaLexerToken;
begin
result := nil;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.identifier then
result := elna_parser_named_type_expression(cursor)
@@ -3292,22 +3271,19 @@ begin
result^.next := nil;
(* Skip "proc ". *)
- elna_lexer_skip_token(cursor);
-
- elna_lexer_read_token(cursor);
+ elna_lexer_read(cursor);
- result^.name := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
(* Skip procedure name. *)
- elna_lexer_skip_token(cursor);
+ token := elna_lexer_read(cursor);
+ result^.name := token^.start;
+ result^.length := token^.length;
(* Skip open paren. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
parameter_head := nil;
.elna_parser_procedure_declaration_parameter;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind <> ElnaLexerKind.right_paren then
next_declaration := elna_parser_variable_declaration(cursor);
@@ -3318,25 +3294,23 @@ begin
end;
current_declaration := next_declaration;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.comma then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
goto elna_parser_procedure_declaration_parameter
end
end;
(* Skip close paren. *)
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result^.parameters := parameter_head;
(* Skip semicolon or arrow. *)
- token := elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind = ElnaLexerKind.arrow then
result^.return_type := elna_parser_type_expression(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor)
+ elna_lexer_read(cursor)
else
result^.return_type := nil
end;
@@ -3345,9 +3319,9 @@ begin
result^.temporaries := parameter_head;
(* Skip semicolon, "begin" and newline. *)
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind._begin then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
parameter_head := elna_parser_statements(cursor)
elsif token^.kind = ElnaLexerKind._return then
parameter_head := elna_parser_return_statement(cursor)
@@ -3355,8 +3329,7 @@ begin
result^.body := parameter_head;
(* Skip the "end" keyword. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -3559,7 +3532,7 @@ begin
.elna_parser_procedures_loop;
elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind._proc then
parser_node := elna_parser_procedure_declaration(cursor);
@@ -3571,8 +3544,7 @@ begin
current_declaration := parser_node;
(* Skip semicolon. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
goto elna_parser_procedures_loop
end;
@@ -3671,38 +3643,31 @@ var
begin
.skip_empty_lines_rerun;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.comment then
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
goto skip_empty_lines_rerun
end
end;
proc elna_parser_type_declaration(cursor: ^ElnaLexerCursor);
var
- type_name: Word;
- name_length: Word;
result: ^ElnaTreeTypeDeclaration;
+ token: ^ElnaLexerToken;
begin
- elna_lexer_read_token(cursor);
- type_name := cursor^.start;
- name_length := cursor^.finish - cursor^.start;
-
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
-
result := malloc(#size(ElnaTreeTypeDeclaration));
+ token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.type_declaration;
result^.next := nil;
- result^.name := type_name;
- result^.length := name_length;
+ result^.name := token^.start;
+ result^.length := token^.length;
+
+ elna_lexer_read(cursor);
result^._type := elna_parser_type_expression(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
return result
end;
@@ -3736,17 +3701,17 @@ var
begin
result := nil;
elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind <> ElnaLexerKind._type then
goto elna_parser_type_part_end
end;
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
.elna_parser_type_part_loop;
elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.identifier then
parser_node := elna_parser_type_declaration(cursor);
@@ -3765,28 +3730,22 @@ end;
proc elna_parser_variable_declaration(cursor: ^ElnaLexerCursor);
var
- name: Word;
- name_length: Word;
variable_type: Word;
result: ^ElnaTreeVariableDeclaration;
+ token: ^ElnaLexerToken;
begin
- elna_lexer_read_token(cursor);
-
- name := cursor^.start;
- name_length := cursor^.finish - cursor^.start;
+ token := elna_lexer_read(cursor);
(* Skip the variable name and colon with the type. *)
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
variable_type := elna_parser_type_expression(cursor);
result := malloc(#size(ElnaTreeVariableDeclaration));
result^.kind := ElnaTreeKind.variable_declaration;
result^.next := nil;
- result^.name := name;
- result^.length := name_length;
+ result^.name := token^.start;
+ result^.length := token^.length;
result^._type := variable_type;
return result
@@ -3816,24 +3775,23 @@ var
token: ^ElnaLexerToken;
begin
result := 0;
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind <> ElnaLexerKind._var then
goto elna_parser_var_part_end
end;
(* Skip "var". *)
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
.elna_parser_var_part_loop;
elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_peek(cursor);
if token^.kind = ElnaLexerKind.identifier then
variable_node := elna_parser_variable_declaration(cursor);
(* Skip semicolon. *)
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
if result = 0 then
result := variable_node
@@ -3889,7 +3847,7 @@ begin
(* Skip "program;". *)
elna_lexer_skip_empty_lines(cursor);
- token := elna_lexer_read_token(cursor);
+ token := elna_lexer_read(cursor);
if token^.kind <> ElnaLexerKind._program then
parser_error := malloc(#size(ElnaError));
@@ -3898,9 +3856,7 @@ begin
error_list^.first := parser_error;
error_list^.last := parser_error
else
- elna_lexer_skip_token(cursor);
- elna_lexer_read_token(cursor);
- elna_lexer_skip_token(cursor);
+ elna_lexer_read(cursor);
result^.types := elna_parser_type_part(cursor);
result^.globals := elna_parser_var_part(cursor);
@@ -4779,16 +4735,8 @@ begin
elna_lexer_transitions();
cursor^.start := code_pointer;
- cursor^.finish := code_pointer
-end;
-
-proc elna_lexer_next_transition(cursor: ^ElnaLexerCursor);
-var
- current_character: Word;
-begin
- current_character := _load_byte(cursor^.finish);
-
- return elna_lexer_get_transition(cursor^.state, classification[current_character + 1])
+ cursor^.finish := code_pointer;
+ cursor^.token := nil
end;
proc string_compare(lhs_pointer: Word, lhs_length: Word, rhs_pointer: Word, rhs_length: Word);
@@ -4804,183 +4752,198 @@ begin
return result
end;
-proc elna_lexer_classify_keyword(position_start: Word, position_end: Word);
+proc elna_lexer_classify_keyword(position_start: Word, position_end: Word) -> ^ElnaLexerToken;
var
- result: Word;
- token_length: Word;
+ result: ^ElnaLexerToken;
begin
- result := ElnaLexerKind.identifier;
- token_length := position_end - position_start;
+ result := malloc(#size(ElnaLexerToken));
+ result^.start := position_start;
+ result^.length := position_end - position_start;
if _load_byte(position_start) = '#' then
- result := ElnaLexerKind.trait
- elsif string_compare(position_start, token_length, "const", 5) then
- result := ElnaLexerKind._const
- elsif string_compare(position_start, token_length, "var", 3) then
- result := ElnaLexerKind._var
- elsif string_compare(position_start, token_length, "proc", 4) then
- result := ElnaLexerKind._proc
- elsif string_compare(position_start, token_length, "type", 4) then
- result := ElnaLexerKind._type
- elsif string_compare(position_start, token_length, "begin", 5) then
- result := ElnaLexerKind._begin
- elsif string_compare(position_start, token_length, "end", 3) then
- result := ElnaLexerKind._end
- elsif string_compare(position_start, token_length, "return", 6) then
- result := ElnaLexerKind._return
- elsif string_compare(position_start, token_length, "goto", 4) then
- result := ElnaLexerKind._goto
- elsif string_compare(position_start, token_length, "if", 2) then
- result := ElnaLexerKind._if
- elsif string_compare(position_start, token_length, "while", 5) then
- result := ElnaLexerKind._while
- elsif string_compare(position_start, token_length, "then", 4) then
- result := ElnaLexerKind._then
- elsif string_compare(position_start, token_length, "else", 4) then
- result := ElnaLexerKind._else
- elsif string_compare(position_start, token_length, "elsif", 5) then
- result := ElnaLexerKind._elsif
- elsif string_compare(position_start, token_length, "record", 6) then
- result := ElnaLexerKind._record
- elsif string_compare(position_start, token_length, "or", 2) then
- result := ElnaLexerKind._or
- elsif string_compare(position_start, token_length, "xor", 3) then
- result := ElnaLexerKind._xor
- elsif string_compare(position_start, token_length, "program", 7) then
- result := ElnaLexerKind._program
- elsif string_compare(position_start, token_length, "module", 6) then
- 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
+ result^.kind := ElnaLexerKind.trait
+ elsif string_compare(position_start, result^.length, "const", 5) then
+ result^.kind := ElnaLexerKind._const
+ elsif string_compare(position_start, result^.length, "var", 3) then
+ result^.kind := ElnaLexerKind._var
+ elsif string_compare(position_start, result^.length, "proc", 4) then
+ result^.kind := ElnaLexerKind._proc
+ elsif string_compare(position_start, result^.length, "type", 4) then
+ result^.kind := ElnaLexerKind._type
+ elsif string_compare(position_start, result^.length, "begin", 5) then
+ result^.kind := ElnaLexerKind._begin
+ elsif string_compare(position_start, result^.length, "end", 3) then
+ result^.kind := ElnaLexerKind._end
+ elsif string_compare(position_start, result^.length, "return", 6) then
+ result^.kind := ElnaLexerKind._return
+ elsif string_compare(position_start, result^.length, "goto", 4) then
+ result^.kind := ElnaLexerKind._goto
+ elsif string_compare(position_start, result^.length, "if", 2) then
+ result^.kind := ElnaLexerKind._if
+ elsif string_compare(position_start, result^.length, "while", 5) then
+ result^.kind := ElnaLexerKind._while
+ elsif string_compare(position_start, result^.length, "then", 4) then
+ result^.kind := ElnaLexerKind._then
+ elsif string_compare(position_start, result^.length, "else", 4) then
+ result^.kind := ElnaLexerKind._else
+ elsif string_compare(position_start, result^.length, "elsif", 5) then
+ result^.kind := ElnaLexerKind._elsif
+ elsif string_compare(position_start, result^.length, "record", 6) then
+ result^.kind := ElnaLexerKind._record
+ elsif string_compare(position_start, result^.length, "or", 2) then
+ result^.kind := ElnaLexerKind._or
+ elsif string_compare(position_start, result^.length, "xor", 3) then
+ result^.kind := ElnaLexerKind._xor
+ elsif string_compare(position_start, result^.length, "program", 7) then
+ result^.kind := ElnaLexerKind._program
+ elsif string_compare(position_start, result^.length, "module", 6) then
+ result^.kind := ElnaLexerKind._module
+ elsif string_compare(position_start, result^.length, "nil", 3) then
+ result^.kind := ElnaLexerKind.null
+ elsif string_compare(position_start, result^.length, "true", 4) then
+ result^.kind := ElnaLexerKind.boolean
+ elsif string_compare(position_start, result^.length, "false", 5) then
+ result^.kind := ElnaLexerKind.boolean
+ else
+ result^.kind := ElnaLexerKind.identifier
end;
return result
end;
-proc elna_lexer_classify_finalize(start_position: Word);
+proc elna_lexer_classify_finalize(start_position: Word) -> ^ElnaLexerToken;
var
character: Word;
- result: Word;
+ result: ^ElnaLexerToken;
begin
- result := 0;
+ result := malloc(#size(ElnaLexerToken));
character := _load_byte(start_position);
if character = ':' then
- result := ElnaLexerKind.colon
+ result^.kind := ElnaLexerKind.colon
elsif character = '.' then
- result := ElnaLexerKind.dot
+ result^.kind := ElnaLexerKind.dot
elsif character = '(' then
- result := ElnaLexerKind.left_paren
+ result^.kind := ElnaLexerKind.left_paren
elsif character = '-' then
- result := ElnaLexerKind.minus
+ result^.kind := ElnaLexerKind.minus
elsif character = '<' then
- result := ElnaLexerKind.less_than
+ result^.kind := ElnaLexerKind.less_than
elsif character = '>' then
- result := ElnaLexerKind.greater_than
+ result^.kind := ElnaLexerKind.greater_than
end;
return result
end;
-proc elna_lexer_classify_single(start_position: Word);
+proc elna_lexer_classify_single(start_position: Word) -> ^ElnaLexerToken;
var
character: Word;
- result: Word;
+ result: ^ElnaLexerToken;
begin
- result := 0;
+ result := malloc(#size(ElnaLexerToken));
character := _load_byte(start_position);
if character = ';' then
- result := ElnaLexerKind.semicolon
+ result^.kind := ElnaLexerKind.semicolon
elsif character = ',' then
- result := ElnaLexerKind.comma
+ result^.kind := ElnaLexerKind.comma
elsif character = ')' then
- result := ElnaLexerKind.right_paren
+ result^.kind := ElnaLexerKind.right_paren
elsif character = '@' then
- result := ElnaLexerKind.at
+ result^.kind := ElnaLexerKind.at
elsif character = '~' then
- result := ElnaLexerKind.not
+ result^.kind := ElnaLexerKind.not
elsif character = '&' then
- result := ElnaLexerKind.and
+ result^.kind := ElnaLexerKind.and
elsif character = '+' then
- result := ElnaLexerKind.plus
+ result^.kind := ElnaLexerKind.plus
elsif character = '*' then
- result := ElnaLexerKind.multiplication
+ result^.kind := ElnaLexerKind.multiplication
elsif character = '=' then
- result := ElnaLexerKind.equals
+ result^.kind := ElnaLexerKind.equals
elsif character = '%' then
- result := ElnaLexerKind.remainder
+ result^.kind := ElnaLexerKind.remainder
elsif character = '/' then
- result := ElnaLexerKind.division
+ result^.kind := ElnaLexerKind.division
elsif character = '.' then
- result := ElnaLexerKind.dot
+ result^.kind := ElnaLexerKind.dot
elsif character = '^' then
- result := ElnaLexerKind.hat
+ result^.kind := ElnaLexerKind.hat
elsif character = '[' then
- result := ElnaLexerKind.left_square
+ result^.kind := ElnaLexerKind.left_square
elsif character = ']' then
- result := ElnaLexerKind.right_square
+ result^.kind := ElnaLexerKind.right_square
end;
return result
end;
-proc elna_lexer_classify_composite(start_position: Word, one_before_last: Word);
+proc elna_lexer_classify_composite(start_position: Word, one_before_last: Word) -> ^ElnaLexerToken;
var
first_character: Word;
last_character: Word;
- result: Word;
+ result: ^ElnaLexerToken;
begin
first_character := _load_byte(start_position);
last_character := _load_byte(one_before_last);
+ result := malloc(#size(ElnaLexerToken));
if first_character = ':' then
- result := ElnaLexerKind.assignment
+ result^.kind := ElnaLexerKind.assignment
elsif first_character = '<' then
if last_character = '=' then
- result := ElnaLexerKind.less_equal
+ result^.kind := ElnaLexerKind.less_equal
elsif last_character = '>' then
- result := ElnaLexerKind.not_equal
+ result^.kind := ElnaLexerKind.not_equal
end
elsif first_character = '>' then
if last_character = '=' then
- result := ElnaLexerKind.greater_equal
+ result^.kind := ElnaLexerKind.greater_equal
end
elsif first_character = '-' then
- result := ElnaLexerKind.arrow
+ result^.kind := ElnaLexerKind.arrow
end;
return result
end;
-proc elna_lexer_classify_delimited(start_position: Word, end_position: Word);
+proc elna_lexer_classify_delimited(start_position: Word, end_position: Word) -> ^ElnaLexerToken;
var
- token_length: Word;
delimiter: Word;
- result: Word;
+ result: ^ElnaLexerToken;
begin
- token_length := end_position - start_position;
delimiter := _load_byte(start_position);
+ result := malloc(#size(ElnaLexerToken));
+
+ result^.start := start_position;
+ result^.length := end_position - start_position;
if delimiter = '(' then
- result := ElnaLexerKind.comment
+ result^.kind := ElnaLexerKind.comment
elsif delimiter = '\'' then
- result := ElnaLexerKind.character
+ result^.kind:= ElnaLexerKind.character
elsif delimiter = '"' then
- result := ElnaLexerKind.string
+ result^.kind := ElnaLexerKind.string
end;
return result
end;
-proc elna_lexer_classify_integer(start_position: Word, end_position: Word);
- return ElnaLexerKind.integer
+proc elna_lexer_classify_integer(start_position: Word, end_position: Word) -> ^ElnaLexerToken;
+var
+ result: ^ElnaLexerToken;
+begin
+ result := malloc(#size(ElnaLexerToken));
+ result^.kind := ElnaLexerKind.integer;
+ result^.start := start_position;
+ result^.length := end_position - start_position;
+
+ return result
end;
-proc elna_lexer_execute_action(cursor: ^ElnaLexerCursor, action_to_perform: Word, kind: ^ElnaLexerKind);
+proc elna_lexer_execute_action(cursor: ^ElnaLexerCursor, action_to_perform: Word) -> ^ElnaLexerToken;
var
- intermediate: Word;
+ token: ^ElnaLexerToken;
begin
+ token := nil;
+
if action_to_perform = ElnaLexerAction.none then
elsif action_to_perform = ElnaLexerAction.accumulate then
cursor^.finish := cursor^.finish + 1
@@ -4990,82 +4953,76 @@ begin
elsif action_to_perform = ElnaLexerAction.single then
cursor^.finish := cursor^.finish + 1;
- intermediate := elna_lexer_classify_single(cursor^.start);
- kind^ := intermediate
+ token := elna_lexer_classify_single(cursor^.start)
elsif action_to_perform = ElnaLexerAction.eof then
- intermediate := ElnaLexerKind.eof;
- kind^ := intermediate
+ token := malloc(#size(ElnaLexerToken));
+ token^.kind := ElnaLexerKind.eof
elsif action_to_perform = ElnaLexerAction.finalize then
- intermediate := elna_lexer_classify_finalize(cursor^.start);
- kind^ := intermediate
+ token := elna_lexer_classify_finalize(cursor^.start)
elsif action_to_perform = ElnaLexerAction.composite then
- intermediate := elna_lexer_classify_composite(cursor^.start, cursor^.finish);
- kind^ := intermediate;
+ token := elna_lexer_classify_composite(cursor^.start, cursor^.finish);
cursor^.finish := cursor^.finish + 1
elsif action_to_perform = ElnaLexerAction.key_id then
- intermediate := elna_lexer_classify_keyword(cursor^.start, cursor^.finish);
- kind^ := intermediate
+ token := elna_lexer_classify_keyword(cursor^.start, cursor^.finish)
elsif action_to_perform = ElnaLexerAction.integer then
- intermediate := elna_lexer_classify_integer(cursor^.start, cursor^.finish);
- kind^ := intermediate
+ token := elna_lexer_classify_integer(cursor^.start, cursor^.finish)
elsif action_to_perform = ElnaLexerAction.delimited then
cursor^.finish := cursor^.finish + 1;
- intermediate := elna_lexer_classify_delimited(cursor^.start, cursor^.finish);
- kind^ := intermediate
- end
+ token := elna_lexer_classify_delimited(cursor^.start, cursor^.finish)
+ end;
+ return token
end;
-proc elna_lexer_execute_transition(cursor: ^ElnaLexerCursor, kind: ^ElnaLexerKind) -> ElnaLexerState;
+proc elna_lexer_execute_transition(cursor: ^ElnaLexerCursor, kind: ^ElnaLexerKind) -> ^ElnaLexerToken;
var
next_transition: ^ElnaLexerTransition;
+ current_character: Word;
begin
- next_transition := elna_lexer_next_transition(cursor);
+ current_character := _load_byte(cursor^.finish);
+ next_transition := elna_lexer_get_transition(cursor^.state, classification[current_character + 1]);
cursor^.state := next_transition^.next_state;
- elna_lexer_execute_action(cursor, next_transition^.action, kind);
-
- return next_transition^.next_state
+ return elna_lexer_execute_action(cursor, next_transition^.action, kind)
end;
-proc elna_lexer_advance_token(cursor: ^ElnaLexerCursor);
+proc elna_lexer_advance_token(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken;
var
- result_state: ElnaLexerState;
- kind: ElnaLexerKind;
+ token: ^ElnaLexerToken;
begin
- result_state := elna_lexer_execute_transition(cursor, @kind);
- if result_state <> ElnaLexerState.finish then
- kind := elna_lexer_advance_token(cursor)
+ token := elna_lexer_execute_transition(cursor);
+ if cursor^.state <> ElnaLexerState.finish then
+ token := elna_lexer_advance_token(cursor)
end;
- return kind
+ return token
end;
(**
* Reads the next token and writes its type into the address in the kind parameter.
* Resets the lexer state for reading the next token.
*)
-proc elna_lexer_read_token(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken;
-var
- result: ^ElnaLexerToken;
+proc elna_lexer_peek(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken;
begin
- cursor^.state := ElnaLexerState.start;
- cursor^.finish := cursor^.start;
-
- result := malloc(#size(ElnaLexerToken));
- result^.kind := elna_lexer_advance_token(cursor);
- result^.start := cursor^.start;
- result^.length := cursor^.finish - cursor^.start;
-
- return result
+ if cursor^.token = nil then
+ cursor^.state := ElnaLexerState.start;
+ cursor^.token := elna_lexer_advance_token(cursor)
+ end;
+ return cursor^.token
end;
(**
- * Advances the token stream past the last read token.
+ * Reads the token and advance the lexer.
*)
-proc elna_lexer_skip_token(cursor: ^ElnaLexerCursor);
+proc elna_lexer_read(cursor: ^ElnaLexerCursor) -> ^ElnaLexerToken;
+var
+ token: ^ElnaLexerToken;
begin
- cursor^.start := cursor^.finish
+ token := elna_lexer_peek(cursor);
+ cursor^.token := nil;
+ cursor^.start := cursor^.finish;
+
+ return token
end;
proc _initialize_global_state();