Parse escape sequences in strings

This commit is contained in:
2026-05-31 01:41:39 +02:00
parent 7401038971
commit 9634ad51a2
4 changed files with 253 additions and 166 deletions
+37 -4
View File
@@ -9,6 +9,7 @@ program;
(* - Allow assigning variables refering to aggregates. *) (* - Allow assigning variables refering to aggregates. *)
(* - Cast expressions. *) (* - Cast expressions. *)
(* - Strings are typed as records with a pointer and length. *)
type type
ElnaListNode = record ElnaListNode = record
@@ -58,7 +59,7 @@ type
kind: ElnaTypeKind; kind: ElnaTypeKind;
size: Word; size: Word;
alignment: Word; alignment: Word;
members: Word; members: ^ElnaTypeField;
length: Word length: Word
end; end;
ElnaTypePointer = record ElnaTypePointer = record
@@ -692,6 +693,7 @@ var
word_type: ^ElnaType; word_type: ^ElnaType;
char_type: ^ElnaType; char_type: ^ElnaType;
bool_type: ^ElnaType; bool_type: ^ElnaType;
string_type: ^ElnaTypeRecord;
source_code: Word; source_code: Word;
compiler_strings_position: Word; compiler_strings_position: Word;
@@ -4934,7 +4936,7 @@ end;
proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral); proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral);
begin begin
parser_node^.type_decoration := word_type parser_node^.type_decoration := string_type
end; end;
proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral); proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral);
@@ -5291,12 +5293,39 @@ begin
symbol_table^.count := symbol_table^.count + 1 symbol_table^.count := symbol_table^.count + 1
end; end;
proc elna_symbol_string_build();
var
current_field: ^ElnaTypeField;
char_pointer: ^ElnaTypePointer;
begin
string_type := malloc(#size(ElnaTypeRecord));
string_type^.kind := ElnaTypeKind._record;
string_type^.size := 8;
string_type^.alignment := 4;
string_type^.members := malloc(2 * #size(ElnaTypeField));
char_pointer := malloc(#size(ElnaTypePointer));
char_pointer^.kind := ElnaTypeKind.pointer;
char_pointer^.size := 4;
char_pointer^.alignment := 4;
char_pointer^.base := char_type;
current_field := string_type^.members;
current_field^.name := "ptr";
current_field^.length := 3;
current_field^.field_type := char_pointer;
current_field := current_field + 1;
current_field^.name := "length";
current_field^.length := 6;
current_field^.field_type := word_type
end;
(* Build global symbol table with predefined symbols. *) (* Build global symbol table with predefined symbols. *)
proc elna_symbol_table_build(); proc elna_symbol_table_build();
var var
current_info: ^ElnaSymbolTypeInfo; current_info: ^ElnaSymbolTypeInfo;
current_type: ^ElnaType; current_type: ^ElnaType;
global_pointer: ^Word;
begin begin
symbol_table_global := elna_symbol_table_create(nil); symbol_table_global := elna_symbol_table_create(nil);
@@ -5327,7 +5356,11 @@ begin
char_type^.size := 1; char_type^.size := 1;
char_type^.alignment := 1; char_type^.alignment := 1;
current_info := type_info_create(char_type); current_info := type_info_create(char_type);
elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info) elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info);
elna_symbol_string_build();
current_info := type_info_create(string_type);
elna_symbol_table_enter(symbol_table_global, "String", 6, current_info)
end; end;
proc elna_lexer_classifications1(); proc elna_lexer_classifications1();
+213 -155
View File
@@ -8,6 +8,8 @@ program;
(* Stage 22 compiler. *) (* Stage 22 compiler. *)
(* - Support 2 word procedure arguments. *) (* - Support 2 word procedure arguments. *)
(* - Characters are parsed to a character ASCII code. *)
(* - Strings are parsed and their length doesn't count for escaping backslash. *)
type type
ElnaListNode = record ElnaListNode = record
@@ -138,7 +140,7 @@ type
ElnaTreeStringLiteral = record ElnaTreeStringLiteral = record
kind: ElnaTreeKind; kind: ElnaTreeKind;
type_decoration: ^ElnaType; type_decoration: ^ElnaType;
value: Word; value: ^Char;
length: Word length: Word
end end
ElnaTreeVariableExpression = record ElnaTreeVariableExpression = record
@@ -679,14 +681,9 @@ type
var var
symbol_table_global: ^ElnaSymbolTable symbol_table_global: ^ElnaSymbolTable
variable_map_global: ^ElnaSymbolTable variable_map_global: ^ElnaSymbolTable
compiler_strings: [1024]Word compiler_strings: [4096]Char
classification: [256]Word classification: [256]Word
(**
* Lexer state is saved after the transition tables.
* Each transition table entry is 8 bytes long. The table has 19 rows (transition states)
* and 23 columns (character classes), so 3496 = 8 * 19 * 23.
*)
transition_table: [19][23]ElnaLexerTransition transition_table: [19][23]ElnaLexerTransition
word_type: ^ElnaType word_type: ^ElnaType
char_type: ^ElnaType char_type: ^ElnaType
@@ -705,33 +702,70 @@ var
* *
* Parameters: * Parameters:
* string - String token. * string - String token.
* string_length - String length.
* *
* Returns the offset from the beginning of the storage to the new string in a0. * Returns the offset from the beginning of the storage to the new string.
*) *)
proc _add_string(string: ^Char) -> Word proc elna_tac_add_string(string: ^Char, string_length: Word) -> Word
var var
contents: Word
result: Word result: Word
current_byte: Char current_byte: Char
length_to_copy: Word current_target: ^Char
begin begin
contents := string + 1;
result := compiler_strings_length; result := compiler_strings_length;
length_to_copy := 0; (* Global character pointer is appearently dereferenced wrongly. *)
current_target := compiler_strings_position;
.add_string_loop; .add_string_loop;
current_byte := contents^; current_byte := string^;
if current_byte <> '"' then
length_to_copy := length_to_copy + 1;
contents := contents + 1;
if current_byte <> '\\' then if current_byte = 92 then
compiler_strings_length := compiler_strings_length + 1 current_target^ := '\\';
current_target := current_target + 1;
current_target^ := '\\'
elsif current_byte = 10 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := 'n'
elsif current_byte = 9 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := 't'
elsif current_byte = 12 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := 'f'
elsif current_byte = 13 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := 'r'
elsif current_byte = 11 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := 'v'
elsif current_byte = 34 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := '"'
elsif current_byte = 39 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := '\''
elsif current_byte = 0 then
current_target^ := '\\';
current_target := current_target + 1;
current_target^ := '0'
else
current_target^ := current_byte
end; end;
current_target := current_target + 1;
string := string + 1;
string_length := string_length - 1;
compiler_strings_length := compiler_strings_length + 1;
if string_length > 0 then
goto add_string_loop goto add_string_loop
end; end;
memcpy(compiler_strings_position, string + 1, length_to_copy); compiler_strings_position := current_target;
compiler_strings_position := compiler_strings_position + length_to_copy;
return result return result
end end
@@ -756,7 +790,7 @@ end
*) *)
proc _write_i(number: Word) proc _write_i(number: Word)
begin begin
printf("%i\0", number); printf("%i\0".ptr, number);
fflush(nil) fflush(nil)
end end
@@ -826,7 +860,7 @@ begin
pseudo_counter := pseudo_counter + 1; pseudo_counter := pseudo_counter + 1;
buffer := malloc(7); buffer := malloc(7);
sprintf(buffer, "$a%i\0", pseudo_counter); sprintf(buffer, "$a%i\0".ptr, pseudo_counter);
operand^.kind := ElnaTacKind.variable; operand^.kind := ElnaTacKind.variable;
operand^.value := buffer; operand^.value := buffer;
@@ -1385,7 +1419,7 @@ begin
elna_list_append(instructions, instruction); elna_list_append(instructions, instruction);
instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal); instruction := elna_rtl_instruction_create(ElnaRtlOperator.jal);
elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.data, "memcpy", 6, 0); elna_rtl_instruction_set_operand(instruction, 1, ElnaRtlKind.data, "memcpy".ptr, 6, 0);
elna_list_append(instructions, instruction) elna_list_append(instructions, instruction)
end end
@@ -1518,91 +1552,91 @@ var
begin begin
if instruction_kind = ElnaRtlOperator.li then if instruction_kind = ElnaRtlOperator.li then
argument_count := 2; argument_count := 2;
_write_s("\tli", 3) _write_s("\tli".ptr, 3)
elsif instruction_kind = ElnaRtlOperator.la then elsif instruction_kind = ElnaRtlOperator.la then
argument_count := 2; argument_count := 2;
_write_s("\tla", 3) _write_s("\tla".ptr, 3)
elsif instruction_kind = ElnaRtlOperator.add then elsif instruction_kind = ElnaRtlOperator.add then
argument_count := 3; argument_count := 3;
_write_s("\tadd", 4) _write_s("\tadd".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.addi then elsif instruction_kind = ElnaRtlOperator.addi then
argument_count := 3; argument_count := 3;
_write_s("\taddi", 5) _write_s("\taddi".ptr, 5)
elsif instruction_kind = ElnaRtlOperator.lw then elsif instruction_kind = ElnaRtlOperator.lw then
argument_count := 2; argument_count := 2;
if source_type^.kind = ElnaRtlTypeKind.byte then if source_type^.kind = ElnaRtlTypeKind.byte then
_write_s("\tlb", 3) _write_s("\tlb".ptr, 3)
else else
_write_s("\tlw", 3) _write_s("\tlw".ptr, 3)
end end
elsif instruction_kind = ElnaRtlOperator.sw then elsif instruction_kind = ElnaRtlOperator.sw then
argument_count := 2; argument_count := 2;
if source_type^.kind = ElnaRtlTypeKind.byte then if source_type^.kind = ElnaRtlTypeKind.byte then
_write_s("\tsb", 3) _write_s("\tsb".ptr, 3)
else else
_write_s("\tsw", 3) _write_s("\tsw".ptr, 3)
end end
elsif instruction_kind = ElnaRtlOperator.jal then elsif instruction_kind = ElnaRtlOperator.jal then
argument_count := 1; argument_count := 1;
_write_s("\tcall", 5) _write_s("\tcall".ptr, 5)
elsif instruction_kind = ElnaRtlOperator.mv then elsif instruction_kind = ElnaRtlOperator.mv then
argument_count := 2; argument_count := 2;
_write_s("\tmv", 3) _write_s("\tmv".ptr, 3)
elsif instruction_kind = ElnaRtlOperator.sub then elsif instruction_kind = ElnaRtlOperator.sub then
argument_count := 3; argument_count := 3;
_write_s("\tsub", 4) _write_s("\tsub".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.mul then elsif instruction_kind = ElnaRtlOperator.mul then
argument_count := 3; argument_count := 3;
_write_s("\tmul", 4) _write_s("\tmul".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.div then elsif instruction_kind = ElnaRtlOperator.div then
argument_count := 3; argument_count := 3;
_write_s("\tdiv", 4) _write_s("\tdiv".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.rem then elsif instruction_kind = ElnaRtlOperator.rem then
argument_count := 3; argument_count := 3;
_write_s("\trem", 4) _write_s("\trem".ptr, 4)
elsif instruction_kind = ElnaRtlOperator._xor then elsif instruction_kind = ElnaRtlOperator._xor then
argument_count := 3; argument_count := 3;
_write_s("\txor", 4) _write_s("\txor".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.xori then elsif instruction_kind = ElnaRtlOperator.xori then
argument_count := 3; argument_count := 3;
_write_s("\txori", 5) _write_s("\txori".ptr, 5)
elsif instruction_kind = ElnaRtlOperator._or then elsif instruction_kind = ElnaRtlOperator._or then
argument_count := 3; argument_count := 3;
_write_s("\tor", 3) _write_s("\tor".ptr, 3)
elsif instruction_kind = ElnaRtlOperator.and then elsif instruction_kind = ElnaRtlOperator.and then
argument_count := 3; argument_count := 3;
_write_s("\tand", 4) _write_s("\tand".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.seqz then elsif instruction_kind = ElnaRtlOperator.seqz then
argument_count := 2; argument_count := 2;
_write_s("\tseqz", 5) _write_s("\tseqz".ptr, 5)
elsif instruction_kind = ElnaRtlOperator.snez then elsif instruction_kind = ElnaRtlOperator.snez then
argument_count := 2; argument_count := 2;
_write_s("\tsnez", 5) _write_s("\tsnez".ptr, 5)
elsif instruction_kind = ElnaRtlOperator.slt then elsif instruction_kind = ElnaRtlOperator.slt then
argument_count := 3; argument_count := 3;
_write_s("\tslt", 4) _write_s("\tslt".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.neg then elsif instruction_kind = ElnaRtlOperator.neg then
argument_count := 2; argument_count := 2;
_write_s("\tneg", 4) _write_s("\tneg".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.not then elsif instruction_kind = ElnaRtlOperator.not then
argument_count := 2; argument_count := 2;
_write_s("\tnot", 4) _write_s("\tnot".ptr, 4)
elsif instruction_kind = ElnaRtlOperator.j then elsif instruction_kind = ElnaRtlOperator.j then
argument_count := 1; argument_count := 1;
_write_s("\tj", 2) _write_s("\tj".ptr, 2)
elsif instruction_kind = ElnaRtlOperator.beqz then elsif instruction_kind = ElnaRtlOperator.beqz then
argument_count := 2; argument_count := 2;
_write_s("\tbeqz", 5) _write_s("\tbeqz".ptr, 5)
elsif instruction_kind = ElnaRtlOperator.bnez then elsif instruction_kind = ElnaRtlOperator.bnez then
argument_count := 2; argument_count := 2;
_write_s("\tbnez", 5) _write_s("\tbnez".ptr, 5)
end; end;
return argument_count return argument_count
end end
proc elna_riscv_register(register: Word) proc elna_riscv_register(register: Word)
begin begin
printf("x%i\0", register - 1); printf("x%i\0".ptr, register - 1);
fflush(nil) fflush(nil)
end end
@@ -2010,24 +2044,24 @@ begin
operand_value := instruction^.operands[1].value; operand_value := instruction^.operands[1].value;
(* Write the prologue. *) (* Write the prologue. *)
printf("\taddi sp, sp, -%i\n\tsw ra, %i(sp)\n\tsw s0, %i(sp)\n\taddi s0, sp, %i\n\0", printf("\taddi sp, sp, -%i\n\tsw ra, %i(sp)\n\tsw s0, %i(sp)\n\taddi s0, sp, %i\n\0".ptr,
operand_value, operand_value - 4, operand_value - 8, operand_value); operand_value, operand_value - 4, operand_value - 8, operand_value);
fflush(nil) fflush(nil)
elsif instruction^.operator = ElnaRtlOperator.ret then elsif instruction^.operator = ElnaRtlOperator.ret then
operand_value := instruction^.operands[1].value; operand_value := instruction^.operands[1].value;
(* Write the epilogue. *) (* Write the epilogue. *)
printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0", operand_value - 4, operand_value - 8, operand_value); printf("\tlw ra, %i(sp)\n\tlw s0, %i(sp)\n\taddi sp, sp, %i\n\0".ptr, operand_value - 4, operand_value - 8, operand_value);
fflush(nil) fflush(nil)
elsif instruction^.operator = ElnaRtlOperator.nop then elsif instruction^.operator = ElnaRtlOperator.nop then
operand_value := instruction^.operands[1].kind; operand_value := instruction^.operands[1].kind;
if operand_value = ElnaTacKind.constant then if operand_value = ElnaTacKind.constant then
printf("\n# copy %i (%i %i) (%i %.*s)\n\0", instruction^.operands[3].kind, printf("\n# copy %i (%i %i) (%i %.*s)\n\0".ptr, instruction^.operands[3].kind,
instruction^.operands[1].kind, instruction^.operands[1].value, instruction^.operands[1].kind, instruction^.operands[1].value,
instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value) instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
else else
printf("\n# copy (%i %.*s) (%i %.*s)\n\0", printf("\n# copy (%i %.*s) (%i %.*s)\n\0".ptr,
instruction^.operands[1].kind, instruction^.operands[1].length, instruction^.operands[1].value, instruction^.operands[1].kind, instruction^.operands[1].length, instruction^.operands[1].value,
instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value) instruction^.operands[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
end; end;
@@ -2117,13 +2151,13 @@ begin
.elna_riscv_procedure_loop; .elna_riscv_procedure_loop;
(* Write .type _procedure_name, @function. *) (* Write .type _procedure_name, @function. *)
printf(".type %.*s, @function\n\0", procedure^.length, procedure^.name); printf(".type %.*s, @function\n\0".ptr, procedure^.length, procedure^.name);
(* Write procedure label, _procedure_name: *) (* Write procedure label, _procedure_name: *)
printf("%.*s:\n\0", procedure^.length, procedure^.name); printf("%.*s:\n\0".ptr, procedure^.length, procedure^.name);
elna_riscv_instructions(procedure^.body.first); elna_riscv_instructions(procedure^.body.first);
printf("\tret\n\0"); printf("\tret\n\0".ptr);
fflush(nil); fflush(nil);
procedure := procedure^.next; procedure := procedure^.next;
@@ -2136,9 +2170,9 @@ proc elna_riscv_variable(variable: ^ElnaRtlStaticVariable)
begin begin
.elna_riscv_variable_loop; .elna_riscv_variable_loop;
if variable <> 0 then if variable <> 0 then
printf(".type %.*s, @object\n\0", variable^.length, variable^.name); printf(".type %.*s, @object\n\0".ptr, variable^.length, variable^.name);
printf("%.*s: .zero %i\n\0", variable^.length, variable^.name, variable^.body); printf("%.*s: .zero %i\n\0".ptr, variable^.length, variable^.name, variable^.body);
variable := variable^.next; variable := variable^.next;
goto elna_riscv_variable_loop goto elna_riscv_variable_loop
@@ -2241,16 +2275,16 @@ var
compiler_strings_end: ^Char compiler_strings_end: ^Char
current_byte: Char current_byte: Char
begin begin
printf(".globl main\n\n\0"); printf(".globl main\n\n\0".ptr);
printf(".section .data\n\0"); printf(".section .data\n\0".ptr);
elna_riscv_variable(pair^.data); elna_riscv_variable(pair^.data);
printf(".section .text\n\n\0"); printf(".section .text\n\n\0".ptr);
elna_riscv_procedure(pair^.code); elna_riscv_procedure(pair^.code);
printf(".section .rodata\n.type strings, @object\nstrings: .ascii \0"); printf(".section .rodata\n.type strings, @object\nstrings: .ascii \0".ptr);
fflush(nil); fflush(nil);
_write_c('"'); _write_c('"');
@@ -2296,7 +2330,7 @@ begin
result := malloc(#size(ElnaTreeBooleanLiteral)); result := malloc(#size(ElnaTreeBooleanLiteral));
result^.kind := ElnaTreeKind.boolean_literal; result^.kind := ElnaTreeKind.boolean_literal;
result^.value := string_compare(cursor^.start, 4, "true", 4); result^.value := string_compare(cursor^.start, 4, "true".ptr, 4);
result^.type_decoration := nil; result^.type_decoration := nil;
elna_lexer_read(cursor); elna_lexer_read(cursor);
@@ -2338,6 +2372,55 @@ begin
operand^.length := 4 operand^.length := 4
end end
(* Escape a single character if needed. *)
proc elna_parser_escape(current_position: ^Char, result: ^Char) -> Word
var
parsed_length: Word
next_character: Char
begin
next_character := current_position^;
if next_character = '\\' then
parsed_length := 2;
current_position := current_position + 1;
next_character := current_position^;
if next_character = '\\' then
(* \\ Backslash. *)
result^ := 92
elsif next_character = 'n' then
(* \n Newline. *)
result^ := 10
elsif next_character = 't' then
(* \t Tab. *)
result^ := 9
elsif next_character = 'f' then
(* \f Formfeed. *)
result^ := 12
elsif next_character = 'r' then
(* \r Carriage return. *)
result^ := 13
elsif next_character = 'v' then
(* \v Vertical tab. *)
result^ := 11
elsif next_character = '"' then
(* \" Double quote. *)
result^ := 34
elsif next_character = '\'' then
(* \' Single quote. *)
result^ := 39
elsif next_character = '0' then
(* \0 Null character. *)
result^ := 0
end
else
parsed_length := 1;
result^ := next_character
end;
return parsed_length
end
proc elna_parser_character_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeCharacterLiteral proc elna_parser_character_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeCharacterLiteral
var var
result: ^ElnaTreeCharacterLiteral result: ^ElnaTreeCharacterLiteral
@@ -2345,10 +2428,11 @@ var
begin begin
result := malloc(#size(ElnaTreeCharacterLiteral)); result := malloc(#size(ElnaTreeCharacterLiteral));
token := elna_lexer_read(cursor); token := elna_lexer_read(cursor);
result^.kind := ElnaTreeKind.character_literal; result^.kind := ElnaTreeKind.character_literal;
result^.value := token^.start;
result^.length := token^.length; elna_parser_escape(token^.start + 1, @result^.value);
result^.length := 0;
result^.type_decoration := nil; result^.type_decoration := nil;
return result return result
@@ -2360,51 +2444,7 @@ var
current_position: ^Char current_position: ^Char
begin begin
operand^.kind := ElnaTacKind.constant; operand^.kind := ElnaTacKind.constant;
current_position := character_literal_node^.value + 1; operand^.value := character_literal_node^.value;
next_character := current_position^;
(* Escape. *)
if next_character = '\\' then
current_position := current_position + 1;
next_character := current_position^;
if next_character = '\\' then
(* \\ Backslash. *)
operand^.value := 92
elsif next_character = 'n' then
(* \n Newline. *)
operand^.value := 10
elsif next_character = 'a' then
(* \a Bell. *)
operand^.value := 7
elsif next_character = 'b' then
(* \b Backspace. *)
operand^.value := 8
elsif next_character = 't' then
(* \t Tab. *)
operand^.value := 9
elsif next_character = 'f' then
(* \f Formfeed. *)
operand^.value := 12
elsif next_character = 'r' then
(* \r Carriage return. *)
operand^.value := 13
elsif next_character = 'v' then
(* \v Vertical tab. *)
operand^.value := 11
elsif next_character = '"' then
(* \" Double quote. *)
operand^.value := 34
elsif next_character = '\'' then
(* \" Single quote. *)
operand^.value := 39
elsif next_character = '0' then
(* \0 Null character. *)
operand^.value := 0
end
else
operand^.value := next_character
end;
operand^.length := 1 operand^.length := 1
end end
@@ -2435,13 +2475,31 @@ proc elna_parser_string_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStringLite
var var
result: ^ElnaTreeStringLiteral result: ^ElnaTreeStringLiteral
token: ^ElnaLexerToken token: ^ElnaLexerToken
current_position: ^Char
parsed_length: Word
parsed_total: Word
target_position: ^Char
begin begin
result := malloc(#size(ElnaTreeStringLiteral)); result := malloc(#size(ElnaTreeStringLiteral));
token := elna_lexer_read(cursor); token := elna_lexer_read(cursor);
target_position := malloc(token^.length - 2);
current_position := token^.start + 1;
parsed_total := 2;
result^.kind := ElnaTreeKind.string_literal; result^.kind := ElnaTreeKind.string_literal;
result^.value := token^.start; result^.value := target_position;
result^.length := token^.length; result^.length := 0;
.elna_parser_escape_loop;
parsed_length := elna_parser_escape(current_position, target_position);
current_position := current_position + parsed_length;
parsed_total := parsed_total + parsed_length;
target_position := target_position + 1;
if parsed_total < token^.length then
goto elna_parser_escape_loop
end;
result^.length := target_position - result^.value;
result^.type_decoration := nil; result^.type_decoration := nil;
return result return result
@@ -2453,12 +2511,12 @@ var
offset: Word offset: Word
instruction: ^ElnaTacInstruction instruction: ^ElnaTacInstruction
begin begin
offset := _add_string(string_literal_node^.value); offset := elna_tac_add_string(string_literal_node^.value, string_literal_node^.length);
elna_tac_make_variable(operand, symbol_table, word_type); elna_tac_make_variable(operand, symbol_table, word_type);
instruction := elna_tac_instruction_create(ElnaTacOperator.get_address); instruction := elna_tac_instruction_create(ElnaTacOperator.get_address);
elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.variable, "strings", 7); elna_tac_instruction_set_operand(instruction, 1, ElnaTacKind.variable, "strings".ptr, 7);
elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length); elna_tac_instruction_set_operand(instruction, 2, operand^.kind, operand^.value, operand^.length);
elna_list_append(instructions, instruction); elna_list_append(instructions, instruction);
@@ -3385,9 +3443,9 @@ var
first_byte: Word first_byte: Word
begin begin
if length = 0 then if length = 0 then
printf(".L%i\0", counter) printf(".L%i\0".ptr, counter)
else else
printf(".%.*s\0", length, counter); printf(".%.*s\0".ptr, length, counter);
end; end;
fflush(nil) fflush(nil)
end end
@@ -4207,7 +4265,7 @@ begin
pseudo_symbol^.kind := ElnaRtlInfoKind.object_info; pseudo_symbol^.kind := ElnaRtlInfoKind.object_info;
buffer := malloc(7); buffer := malloc(7);
sprintf(buffer, "$b%i\0", pseudo_counter); sprintf(buffer, "$b%i\0".ptr, pseudo_counter);
pseudo_symbol^.allocated := false; pseudo_symbol^.allocated := false;
operand^.value := buffer; operand^.value := buffer;
@@ -4683,10 +4741,10 @@ begin
elna_list_initialize(@result^.body); elna_list_initialize(@result^.body);
result^.name := "main"; result^.name := "main".ptr;
result^.length := 4; result^.length := 4;
symbol_info := elna_symbol_table_lookup(symbol_table_global, "main", 4); symbol_info := elna_symbol_table_lookup(symbol_table_global, result^.name, result^.length);
result^.symbol_table := symbol_info^.symbol_table; result^.symbol_table := symbol_info^.symbol_table;
@@ -4896,7 +4954,7 @@ begin
new_symbol_table := elna_symbol_table_create(symbol_table_global); new_symbol_table := elna_symbol_table_create(symbol_table_global);
symbol_info := procedure_info_create(new_symbol_table); symbol_info := procedure_info_create(new_symbol_table);
elna_symbol_table_enter(symbol_table_global, "main", 4, symbol_info) elna_symbol_table_enter(symbol_table_global, "main".ptr, 4, symbol_info)
end end
proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable) proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable)
@@ -4993,7 +5051,7 @@ end
proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral) proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral)
begin begin
parser_node^.type_decoration := word_type parser_node^.type_decoration := string_type
end end
proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral) proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral)
@@ -5005,7 +5063,7 @@ proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral)
var var
symbol_info: ^ElnaSymbolTypeInfo symbol_info: ^ElnaSymbolTypeInfo
begin begin
symbol_info := elna_symbol_table_lookup(symbol_table_global, "Pointer", 7); symbol_info := elna_symbol_table_lookup(symbol_table_global, "Pointer".ptr, 7);
parser_node^.type_decoration := symbol_info^._type parser_node^.type_decoration := symbol_info^._type
end end
@@ -5368,14 +5426,14 @@ begin
char_pointer^.base := char_type; char_pointer^.base := char_type;
current_field := string_type^.members; current_field := string_type^.members;
current_field^.name := "ptr"; current_field^.name := "ptr".ptr;
current_field^.length := 3; current_field^.length := 3;
current_field^.field_type := char_pointer; current_field^.field_type := char_pointer;
current_field := current_field + 1; current_field := current_field + 1;
current_field^.name := "length"; current_field^.name := "length".ptr;
current_field^.length := 6; current_field^.length := 6;
current_field^.field_type := word_type; current_field^.field_type := word_type
end end
(* Build global symbol table with predefined symbols. *) (* Build global symbol table with predefined symbols. *)
@@ -5391,32 +5449,32 @@ begin
word_type^.size := 4; word_type^.size := 4;
word_type^.alignment := 4; word_type^.alignment := 4;
current_info := type_info_create(word_type); current_info := type_info_create(word_type);
elna_symbol_table_enter(symbol_table_global, "Word", 4, current_info); elna_symbol_table_enter(symbol_table_global, "Word".ptr, 4, current_info);
current_type := malloc(#size(ElnaType)); current_type := malloc(#size(ElnaType));
current_type^.kind := ElnaTypeKind.primitive; current_type^.kind := ElnaTypeKind.primitive;
current_type^.size := 4; current_type^.size := 4;
current_type^.alignment := 4; current_type^.alignment := 4;
current_info := type_info_create(current_type); current_info := type_info_create(current_type);
elna_symbol_table_enter(symbol_table_global, "Pointer", 7, current_info); elna_symbol_table_enter(symbol_table_global, "Pointer".ptr, 7, current_info);
bool_type := malloc(#size(ElnaType)); bool_type := malloc(#size(ElnaType));
bool_type^.kind := ElnaTypeKind.primitive; bool_type^.kind := ElnaTypeKind.primitive;
bool_type^.size := 1; bool_type^.size := 1;
bool_type^.alignment := 1; bool_type^.alignment := 1;
current_info := type_info_create(bool_type); current_info := type_info_create(bool_type);
elna_symbol_table_enter(symbol_table_global, "Bool", 4, current_info); elna_symbol_table_enter(symbol_table_global, "Bool".ptr, 4, current_info);
char_type := malloc(#size(ElnaType)); char_type := malloc(#size(ElnaType));
char_type^.kind := ElnaTypeKind.primitive; char_type^.kind := ElnaTypeKind.primitive;
char_type^.size := 1; char_type^.size := 1;
char_type^.alignment := 1; char_type^.alignment := 1;
current_info := type_info_create(char_type); current_info := type_info_create(char_type);
elna_symbol_table_enter(symbol_table_global, "Char", 4, current_info); elna_symbol_table_enter(symbol_table_global, "Char".ptr, 4, current_info);
elna_symbol_string_build(); elna_symbol_string_build();
current_info := type_info_create(string_type); current_info := type_info_create(string_type);
elna_symbol_table_enter(symbol_table_global, "String", 6, current_info) elna_symbol_table_enter(symbol_table_global, "String".ptr, 6, current_info)
end end
proc elna_lexer_classifications1() proc elna_lexer_classifications1()
@@ -5820,49 +5878,49 @@ begin
if position_start^ = '#' then if position_start^ = '#' then
result^.kind := ElnaLexerKind.trait result^.kind := ElnaLexerKind.trait
elsif string_compare(position_start, result^.length, "const", 5) then elsif string_compare(position_start, result^.length, "const".ptr, 5) then
result^.kind := ElnaLexerKind._const result^.kind := ElnaLexerKind._const
elsif string_compare(position_start, result^.length, "var", 3) then elsif string_compare(position_start, result^.length, "var".ptr, 3) then
result^.kind := ElnaLexerKind._var result^.kind := ElnaLexerKind._var
elsif string_compare(position_start, result^.length, "proc", 4) then elsif string_compare(position_start, result^.length, "proc".ptr, 4) then
result^.kind := ElnaLexerKind._proc result^.kind := ElnaLexerKind._proc
elsif string_compare(position_start, result^.length, "type", 4) then elsif string_compare(position_start, result^.length, "type".ptr, 4) then
result^.kind := ElnaLexerKind._type result^.kind := ElnaLexerKind._type
elsif string_compare(position_start, result^.length, "begin", 5) then elsif string_compare(position_start, result^.length, "begin".ptr, 5) then
result^.kind := ElnaLexerKind._begin result^.kind := ElnaLexerKind._begin
elsif string_compare(position_start, result^.length, "end", 3) then elsif string_compare(position_start, result^.length, "end".ptr, 3) then
result^.kind := ElnaLexerKind._end result^.kind := ElnaLexerKind._end
elsif string_compare(position_start, result^.length, "return", 6) then elsif string_compare(position_start, result^.length, "return".ptr, 6) then
result^.kind := ElnaLexerKind._return result^.kind := ElnaLexerKind._return
elsif string_compare(position_start, result^.length, "goto", 4) then elsif string_compare(position_start, result^.length, "goto".ptr, 4) then
result^.kind := ElnaLexerKind._goto result^.kind := ElnaLexerKind._goto
elsif string_compare(position_start, result^.length, "if", 2) then elsif string_compare(position_start, result^.length, "if".ptr, 2) then
result^.kind := ElnaLexerKind._if result^.kind := ElnaLexerKind._if
elsif string_compare(position_start, result^.length, "while", 5) then elsif string_compare(position_start, result^.length, "while".ptr, 5) then
result^.kind := ElnaLexerKind._while result^.kind := ElnaLexerKind._while
elsif string_compare(position_start, result^.length, "then", 4) then elsif string_compare(position_start, result^.length, "then".ptr, 4) then
result^.kind := ElnaLexerKind._then result^.kind := ElnaLexerKind._then
elsif string_compare(position_start, result^.length, "else", 4) then elsif string_compare(position_start, result^.length, "else".ptr, 4) then
result^.kind := ElnaLexerKind._else result^.kind := ElnaLexerKind._else
elsif string_compare(position_start, result^.length, "elsif", 5) then elsif string_compare(position_start, result^.length, "elsif".ptr, 5) then
result^.kind := ElnaLexerKind._elsif result^.kind := ElnaLexerKind._elsif
elsif string_compare(position_start, result^.length, "record", 6) then elsif string_compare(position_start, result^.length, "record".ptr, 6) then
result^.kind := ElnaLexerKind._record result^.kind := ElnaLexerKind._record
elsif string_compare(position_start, result^.length, "or", 2) then elsif string_compare(position_start, result^.length, "or".ptr, 2) then
result^.kind := ElnaLexerKind._or result^.kind := ElnaLexerKind._or
elsif string_compare(position_start, result^.length, "xor", 3) then elsif string_compare(position_start, result^.length, "xor".ptr, 3) then
result^.kind := ElnaLexerKind._xor result^.kind := ElnaLexerKind._xor
elsif string_compare(position_start, result^.length, "program", 7) then elsif string_compare(position_start, result^.length, "program".ptr, 7) then
result^.kind := ElnaLexerKind._program result^.kind := ElnaLexerKind._program
elsif string_compare(position_start, result^.length, "module", 6) then elsif string_compare(position_start, result^.length, "module".ptr, 6) then
result^.kind := ElnaLexerKind._module result^.kind := ElnaLexerKind._module
elsif string_compare(position_start, result^.length, "nil", 3) then elsif string_compare(position_start, result^.length, "nil".ptr, 3) then
result^.kind := ElnaLexerKind.null result^.kind := ElnaLexerKind.null
elsif string_compare(position_start, result^.length, "true", 4) then elsif string_compare(position_start, result^.length, "true".ptr, 4) then
result^.kind := ElnaLexerKind.boolean result^.kind := ElnaLexerKind.boolean
elsif string_compare(position_start, result^.length, "false", 5) then elsif string_compare(position_start, result^.length, "false".ptr, 5) then
result^.kind := ElnaLexerKind.boolean result^.kind := ElnaLexerKind.boolean
elsif string_compare(position_start, result^.length, "cast", 4) then elsif string_compare(position_start, result^.length, "cast".ptr, 4) then
result^.kind := ElnaLexerKind._cast result^.kind := ElnaLexerKind._cast
end; end;
return result return result
+1 -1
View File
@@ -17,7 +17,7 @@
<hex-character> = `\\x' <hex-digit> \{<hex-digit>\}. <hex-character> = `\\x' <hex-digit> \{<hex-digit>\}.
<escaped-character> = `\\' \\ <escaped-character> = `\\' \\
(`n' | `a' | `b' | `t' | `f' | `r' | `v' | `\\' | `\textquotesingle' | `\textquotedbl' | `0'). (`n' | `t' | `f' | `r' | `v' | `\\' | `\textquotesingle' | `\textquotedbl' | `0').
<printable-character> = \enspace? a printable ASCII character\space?. <printable-character> = \enspace? a printable ASCII character\space?.
+1 -5
View File
@@ -84,7 +84,7 @@ called the \textit{the length} of the string.
\begin{grammar} \begin{grammar}
<escaped-character> = `\\' \\ <escaped-character> = `\\' \\
(`n' | `a' | `b' | `t' | `f' | `r' | `v' | `\\' | `\textquotesingle' | `\textquotedbl' | `0'). (`n' | `t' | `f' | `r' | `v' | `\\' | `\textquotesingle' | `\textquotedbl' | `0').
<hex-character> = `\\x' <hex-digit> \{<hex-digit>\}. <hex-character> = `\\x' <hex-digit> \{<hex-digit>\}.
@@ -106,10 +106,6 @@ beginning with a backslash (\textbackslash).
\toprule \toprule
\verb|\n| & Newline \\ \verb|\n| & Newline \\
\midrule \midrule
\verb|\a| & Bell \\
\midrule
\verb|\b| & Backspace \\
\midrule
\verb|\t| & Horizontal tab \\ \verb|\t| & Horizontal tab \\
\midrule \midrule
\verb|\f| & Form feed \\ \verb|\f| & Form feed \\