Parse escape sequences in strings
This commit is contained in:
+37
-4
@@ -9,6 +9,7 @@ program;
|
||||
|
||||
(* - Allow assigning variables refering to aggregates. *)
|
||||
(* - Cast expressions. *)
|
||||
(* - Strings are typed as records with a pointer and length. *)
|
||||
|
||||
type
|
||||
ElnaListNode = record
|
||||
@@ -58,7 +59,7 @@ type
|
||||
kind: ElnaTypeKind;
|
||||
size: Word;
|
||||
alignment: Word;
|
||||
members: Word;
|
||||
members: ^ElnaTypeField;
|
||||
length: Word
|
||||
end;
|
||||
ElnaTypePointer = record
|
||||
@@ -692,6 +693,7 @@ var
|
||||
word_type: ^ElnaType;
|
||||
char_type: ^ElnaType;
|
||||
bool_type: ^ElnaType;
|
||||
string_type: ^ElnaTypeRecord;
|
||||
|
||||
source_code: Word;
|
||||
compiler_strings_position: Word;
|
||||
@@ -4934,7 +4936,7 @@ end;
|
||||
|
||||
proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral);
|
||||
begin
|
||||
parser_node^.type_decoration := word_type
|
||||
parser_node^.type_decoration := string_type
|
||||
end;
|
||||
|
||||
proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral);
|
||||
@@ -5291,12 +5293,39 @@ begin
|
||||
symbol_table^.count := symbol_table^.count + 1
|
||||
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. *)
|
||||
proc elna_symbol_table_build();
|
||||
var
|
||||
current_info: ^ElnaSymbolTypeInfo;
|
||||
current_type: ^ElnaType;
|
||||
global_pointer: ^Word;
|
||||
begin
|
||||
symbol_table_global := elna_symbol_table_create(nil);
|
||||
|
||||
@@ -5327,7 +5356,11 @@ begin
|
||||
char_type^.size := 1;
|
||||
char_type^.alignment := 1;
|
||||
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;
|
||||
|
||||
proc elna_lexer_classifications1();
|
||||
|
||||
+214
-156
@@ -8,6 +8,8 @@ program;
|
||||
(* Stage 22 compiler. *)
|
||||
|
||||
(* - 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
|
||||
ElnaListNode = record
|
||||
@@ -138,7 +140,7 @@ type
|
||||
ElnaTreeStringLiteral = record
|
||||
kind: ElnaTreeKind;
|
||||
type_decoration: ^ElnaType;
|
||||
value: Word;
|
||||
value: ^Char;
|
||||
length: Word
|
||||
end
|
||||
ElnaTreeVariableExpression = record
|
||||
@@ -679,14 +681,9 @@ type
|
||||
var
|
||||
symbol_table_global: ^ElnaSymbolTable
|
||||
variable_map_global: ^ElnaSymbolTable
|
||||
compiler_strings: [1024]Word
|
||||
compiler_strings: [4096]Char
|
||||
|
||||
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
|
||||
word_type: ^ElnaType
|
||||
char_type: ^ElnaType
|
||||
@@ -705,33 +702,70 @@ var
|
||||
*
|
||||
* Parameters:
|
||||
* 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
|
||||
contents: Word
|
||||
result: Word
|
||||
current_byte: Char
|
||||
length_to_copy: Word
|
||||
current_target: ^Char
|
||||
begin
|
||||
contents := string + 1;
|
||||
result := compiler_strings_length;
|
||||
length_to_copy := 0;
|
||||
(* Global character pointer is appearently dereferenced wrongly. *)
|
||||
current_target := compiler_strings_position;
|
||||
|
||||
.add_string_loop;
|
||||
current_byte := contents^;
|
||||
if current_byte <> '"' then
|
||||
length_to_copy := length_to_copy + 1;
|
||||
contents := contents + 1;
|
||||
current_byte := string^;
|
||||
|
||||
if current_byte <> '\\' then
|
||||
compiler_strings_length := compiler_strings_length + 1
|
||||
end;
|
||||
if current_byte = 92 then
|
||||
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;
|
||||
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
|
||||
end;
|
||||
memcpy(compiler_strings_position, string + 1, length_to_copy);
|
||||
compiler_strings_position := compiler_strings_position + length_to_copy;
|
||||
compiler_strings_position := current_target;
|
||||
|
||||
return result
|
||||
end
|
||||
@@ -756,7 +790,7 @@ end
|
||||
*)
|
||||
proc _write_i(number: Word)
|
||||
begin
|
||||
printf("%i\0", number);
|
||||
printf("%i\0".ptr, number);
|
||||
fflush(nil)
|
||||
end
|
||||
|
||||
@@ -826,7 +860,7 @@ begin
|
||||
pseudo_counter := pseudo_counter + 1;
|
||||
buffer := malloc(7);
|
||||
|
||||
sprintf(buffer, "$a%i\0", pseudo_counter);
|
||||
sprintf(buffer, "$a%i\0".ptr, pseudo_counter);
|
||||
|
||||
operand^.kind := ElnaTacKind.variable;
|
||||
operand^.value := buffer;
|
||||
@@ -1385,7 +1419,7 @@ begin
|
||||
elna_list_append(instructions, instruction);
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
@@ -1518,91 +1552,91 @@ var
|
||||
begin
|
||||
if instruction_kind = ElnaRtlOperator.li then
|
||||
argument_count := 2;
|
||||
_write_s("\tli", 3)
|
||||
_write_s("\tli".ptr, 3)
|
||||
elsif instruction_kind = ElnaRtlOperator.la then
|
||||
argument_count := 2;
|
||||
_write_s("\tla", 3)
|
||||
_write_s("\tla".ptr, 3)
|
||||
elsif instruction_kind = ElnaRtlOperator.add then
|
||||
argument_count := 3;
|
||||
_write_s("\tadd", 4)
|
||||
_write_s("\tadd".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.addi then
|
||||
argument_count := 3;
|
||||
_write_s("\taddi", 5)
|
||||
_write_s("\taddi".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator.lw then
|
||||
argument_count := 2;
|
||||
if source_type^.kind = ElnaRtlTypeKind.byte then
|
||||
_write_s("\tlb", 3)
|
||||
_write_s("\tlb".ptr, 3)
|
||||
else
|
||||
_write_s("\tlw", 3)
|
||||
_write_s("\tlw".ptr, 3)
|
||||
end
|
||||
elsif instruction_kind = ElnaRtlOperator.sw then
|
||||
argument_count := 2;
|
||||
if source_type^.kind = ElnaRtlTypeKind.byte then
|
||||
_write_s("\tsb", 3)
|
||||
_write_s("\tsb".ptr, 3)
|
||||
else
|
||||
_write_s("\tsw", 3)
|
||||
_write_s("\tsw".ptr, 3)
|
||||
end
|
||||
elsif instruction_kind = ElnaRtlOperator.jal then
|
||||
argument_count := 1;
|
||||
_write_s("\tcall", 5)
|
||||
_write_s("\tcall".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator.mv then
|
||||
argument_count := 2;
|
||||
_write_s("\tmv", 3)
|
||||
_write_s("\tmv".ptr, 3)
|
||||
elsif instruction_kind = ElnaRtlOperator.sub then
|
||||
argument_count := 3;
|
||||
_write_s("\tsub", 4)
|
||||
_write_s("\tsub".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.mul then
|
||||
argument_count := 3;
|
||||
_write_s("\tmul", 4)
|
||||
_write_s("\tmul".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.div then
|
||||
argument_count := 3;
|
||||
_write_s("\tdiv", 4)
|
||||
_write_s("\tdiv".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.rem then
|
||||
argument_count := 3;
|
||||
_write_s("\trem", 4)
|
||||
_write_s("\trem".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator._xor then
|
||||
argument_count := 3;
|
||||
_write_s("\txor", 4)
|
||||
_write_s("\txor".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.xori then
|
||||
argument_count := 3;
|
||||
_write_s("\txori", 5)
|
||||
_write_s("\txori".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator._or then
|
||||
argument_count := 3;
|
||||
_write_s("\tor", 3)
|
||||
_write_s("\tor".ptr, 3)
|
||||
elsif instruction_kind = ElnaRtlOperator.and then
|
||||
argument_count := 3;
|
||||
_write_s("\tand", 4)
|
||||
_write_s("\tand".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.seqz then
|
||||
argument_count := 2;
|
||||
_write_s("\tseqz", 5)
|
||||
_write_s("\tseqz".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator.snez then
|
||||
argument_count := 2;
|
||||
_write_s("\tsnez", 5)
|
||||
_write_s("\tsnez".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator.slt then
|
||||
argument_count := 3;
|
||||
_write_s("\tslt", 4)
|
||||
_write_s("\tslt".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.neg then
|
||||
argument_count := 2;
|
||||
_write_s("\tneg", 4)
|
||||
_write_s("\tneg".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.not then
|
||||
argument_count := 2;
|
||||
_write_s("\tnot", 4)
|
||||
_write_s("\tnot".ptr, 4)
|
||||
elsif instruction_kind = ElnaRtlOperator.j then
|
||||
argument_count := 1;
|
||||
_write_s("\tj", 2)
|
||||
_write_s("\tj".ptr, 2)
|
||||
elsif instruction_kind = ElnaRtlOperator.beqz then
|
||||
argument_count := 2;
|
||||
_write_s("\tbeqz", 5)
|
||||
_write_s("\tbeqz".ptr, 5)
|
||||
elsif instruction_kind = ElnaRtlOperator.bnez then
|
||||
argument_count := 2;
|
||||
_write_s("\tbnez", 5)
|
||||
_write_s("\tbnez".ptr, 5)
|
||||
end;
|
||||
return argument_count
|
||||
end
|
||||
|
||||
proc elna_riscv_register(register: Word)
|
||||
begin
|
||||
printf("x%i\0", register - 1);
|
||||
printf("x%i\0".ptr, register - 1);
|
||||
fflush(nil)
|
||||
end
|
||||
|
||||
@@ -2010,24 +2044,24 @@ begin
|
||||
operand_value := instruction^.operands[1].value;
|
||||
|
||||
(* 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);
|
||||
fflush(nil)
|
||||
elsif instruction^.operator = ElnaRtlOperator.ret then
|
||||
operand_value := instruction^.operands[1].value;
|
||||
|
||||
(* 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)
|
||||
elsif instruction^.operator = ElnaRtlOperator.nop then
|
||||
operand_value := instruction^.operands[1].kind;
|
||||
|
||||
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[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
|
||||
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[2].kind, instruction^.operands[2].length, instruction^.operands[2].value)
|
||||
end;
|
||||
@@ -2117,13 +2151,13 @@ begin
|
||||
.elna_riscv_procedure_loop;
|
||||
|
||||
(* 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: *)
|
||||
printf("%.*s:\n\0", procedure^.length, procedure^.name);
|
||||
printf("%.*s:\n\0".ptr, procedure^.length, procedure^.name);
|
||||
|
||||
elna_riscv_instructions(procedure^.body.first);
|
||||
printf("\tret\n\0");
|
||||
printf("\tret\n\0".ptr);
|
||||
fflush(nil);
|
||||
|
||||
procedure := procedure^.next;
|
||||
@@ -2136,9 +2170,9 @@ proc elna_riscv_variable(variable: ^ElnaRtlStaticVariable)
|
||||
begin
|
||||
.elna_riscv_variable_loop;
|
||||
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;
|
||||
|
||||
goto elna_riscv_variable_loop
|
||||
@@ -2241,16 +2275,16 @@ var
|
||||
compiler_strings_end: ^Char
|
||||
current_byte: Char
|
||||
begin
|
||||
printf(".globl main\n\n\0");
|
||||
printf(".section .data\n\0");
|
||||
printf(".globl main\n\n\0".ptr);
|
||||
printf(".section .data\n\0".ptr);
|
||||
|
||||
elna_riscv_variable(pair^.data);
|
||||
|
||||
printf(".section .text\n\n\0");
|
||||
printf(".section .text\n\n\0".ptr);
|
||||
|
||||
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);
|
||||
_write_c('"');
|
||||
|
||||
@@ -2296,7 +2330,7 @@ begin
|
||||
result := malloc(#size(ElnaTreeBooleanLiteral));
|
||||
|
||||
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;
|
||||
|
||||
elna_lexer_read(cursor);
|
||||
@@ -2338,6 +2372,55 @@ begin
|
||||
operand^.length := 4
|
||||
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
|
||||
var
|
||||
result: ^ElnaTreeCharacterLiteral
|
||||
@@ -2345,10 +2428,11 @@ var
|
||||
begin
|
||||
result := malloc(#size(ElnaTreeCharacterLiteral));
|
||||
token := elna_lexer_read(cursor);
|
||||
|
||||
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;
|
||||
|
||||
return result
|
||||
@@ -2360,51 +2444,7 @@ var
|
||||
current_position: ^Char
|
||||
begin
|
||||
operand^.kind := ElnaTacKind.constant;
|
||||
current_position := character_literal_node^.value + 1;
|
||||
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^.value := character_literal_node^.value;
|
||||
operand^.length := 1
|
||||
end
|
||||
|
||||
@@ -2435,13 +2475,31 @@ proc elna_parser_string_literal(cursor: ^ElnaLexerCursor) -> ^ElnaTreeStringLite
|
||||
var
|
||||
result: ^ElnaTreeStringLiteral
|
||||
token: ^ElnaLexerToken
|
||||
current_position: ^Char
|
||||
parsed_length: Word
|
||||
parsed_total: Word
|
||||
target_position: ^Char
|
||||
begin
|
||||
result := malloc(#size(ElnaTreeStringLiteral));
|
||||
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^.value := token^.start;
|
||||
result^.length := token^.length;
|
||||
result^.value := target_position;
|
||||
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;
|
||||
|
||||
return result
|
||||
@@ -2453,12 +2511,12 @@ var
|
||||
offset: Word
|
||||
instruction: ^ElnaTacInstruction
|
||||
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);
|
||||
|
||||
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_list_append(instructions, instruction);
|
||||
|
||||
@@ -3385,9 +3443,9 @@ var
|
||||
first_byte: Word
|
||||
begin
|
||||
if length = 0 then
|
||||
printf(".L%i\0", counter)
|
||||
printf(".L%i\0".ptr, counter)
|
||||
else
|
||||
printf(".%.*s\0", length, counter);
|
||||
printf(".%.*s\0".ptr, length, counter);
|
||||
end;
|
||||
fflush(nil)
|
||||
end
|
||||
@@ -4207,7 +4265,7 @@ begin
|
||||
pseudo_symbol^.kind := ElnaRtlInfoKind.object_info;
|
||||
buffer := malloc(7);
|
||||
|
||||
sprintf(buffer, "$b%i\0", pseudo_counter);
|
||||
sprintf(buffer, "$b%i\0".ptr, pseudo_counter);
|
||||
pseudo_symbol^.allocated := false;
|
||||
|
||||
operand^.value := buffer;
|
||||
@@ -4683,10 +4741,10 @@ begin
|
||||
|
||||
elna_list_initialize(@result^.body);
|
||||
|
||||
result^.name := "main";
|
||||
result^.name := "main".ptr;
|
||||
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;
|
||||
|
||||
@@ -4896,7 +4954,7 @@ begin
|
||||
new_symbol_table := elna_symbol_table_create(symbol_table_global);
|
||||
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
|
||||
|
||||
proc elna_type_conditional_statements(parser_node: ^ElnaTreeConditionalStatements, symbol_table: ^ElnaSymbolTable)
|
||||
@@ -4993,7 +5051,7 @@ end
|
||||
|
||||
proc elna_type_string_literal(parser_node: ^ElnaTreeStringLiteral)
|
||||
begin
|
||||
parser_node^.type_decoration := word_type
|
||||
parser_node^.type_decoration := string_type
|
||||
end
|
||||
|
||||
proc elna_type_boolean_literal(parser_node: ^ElnaTreeBooleanLiteral)
|
||||
@@ -5005,7 +5063,7 @@ proc elna_type_nil_literal(parser_node: ^ElnaTreeNilLiteral)
|
||||
var
|
||||
symbol_info: ^ElnaSymbolTypeInfo
|
||||
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
|
||||
end
|
||||
|
||||
@@ -5368,14 +5426,14 @@ begin
|
||||
char_pointer^.base := char_type;
|
||||
|
||||
current_field := string_type^.members;
|
||||
current_field^.name := "ptr";
|
||||
current_field^.name := "ptr".ptr;
|
||||
current_field^.length := 3;
|
||||
current_field^.field_type := char_pointer;
|
||||
|
||||
current_field := current_field + 1;
|
||||
current_field^.name := "length";
|
||||
current_field^.name := "length".ptr;
|
||||
current_field^.length := 6;
|
||||
current_field^.field_type := word_type;
|
||||
current_field^.field_type := word_type
|
||||
end
|
||||
|
||||
(* Build global symbol table with predefined symbols. *)
|
||||
@@ -5391,32 +5449,32 @@ begin
|
||||
word_type^.size := 4;
|
||||
word_type^.alignment := 4;
|
||||
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^.kind := ElnaTypeKind.primitive;
|
||||
current_type^.size := 4;
|
||||
current_type^.alignment := 4;
|
||||
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^.kind := ElnaTypeKind.primitive;
|
||||
bool_type^.size := 1;
|
||||
bool_type^.alignment := 1;
|
||||
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^.kind := ElnaTypeKind.primitive;
|
||||
char_type^.size := 1;
|
||||
char_type^.alignment := 1;
|
||||
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();
|
||||
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
|
||||
|
||||
proc elna_lexer_classifications1()
|
||||
@@ -5820,49 +5878,49 @@ begin
|
||||
|
||||
if position_start^ = '#' then
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
end;
|
||||
return result
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
<hex-character> = `\\x' <hex-digit> \{<hex-digit>\}.
|
||||
|
||||
<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?.
|
||||
|
||||
|
||||
+1
-5
@@ -84,7 +84,7 @@ called the \textit{the length} of the string.
|
||||
|
||||
\begin{grammar}
|
||||
<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>\}.
|
||||
|
||||
@@ -106,10 +106,6 @@ beginning with a backslash (\textbackslash).
|
||||
\toprule
|
||||
\verb|\n| & Newline \\
|
||||
\midrule
|
||||
\verb|\a| & Bell \\
|
||||
\midrule
|
||||
\verb|\b| & Backspace \\
|
||||
\midrule
|
||||
\verb|\t| & Horizontal tab \\
|
||||
\midrule
|
||||
\verb|\f| & Form feed \\
|
||||
|
||||
Reference in New Issue
Block a user