Support comments between (* and *)
This commit is contained in:
45
Rakefile
45
Rakefile
@@ -14,7 +14,7 @@ directory 'build/boot'
|
|||||||
directory 'build/valid'
|
directory 'build/valid'
|
||||||
|
|
||||||
def compile(input, output)
|
def compile(input, output)
|
||||||
sh ENV.fetch('CC', 'gcc'), '-nostdlib', '-o', output, input
|
sh ENV.fetch('CC', 'gcc'), '-nostdlib', '-fpie', '-g', '-o', output, input
|
||||||
end
|
end
|
||||||
|
|
||||||
def run(exe)
|
def run(exe)
|
||||||
@@ -39,43 +39,16 @@ end
|
|||||||
|
|
||||||
desc 'Convert previous stage language into the current stage language'
|
desc 'Convert previous stage language into the current stage language'
|
||||||
task :convert do
|
task :convert do
|
||||||
File.open('boot/stage8.elna', 'w') do |current_stage|
|
File.open('boot/stage9.elna', 'w') do |current_stage|
|
||||||
File.readlines('boot/stage7.elna').each do |line|
|
File.readlines('boot/stage8.elna').each do |line|
|
||||||
if line == ".section .bss\n"
|
comment_match = /^(\s*)#(.*)/.match line
|
||||||
current_stage << <<~SECTION
|
|
||||||
const
|
|
||||||
symbol_builtin_name_int := "Int";
|
|
||||||
symbol_builtin_name_word := "Word";
|
|
||||||
symbol_builtin_name_pointer := "Pointer";
|
|
||||||
symbol_builtin_name_char := "Char";
|
|
||||||
symbol_builtin_name_bool := "Bool";
|
|
||||||
|
|
||||||
# Every type info starts with a word describing what type it is.
|
if comment_match.nil?
|
||||||
#
|
|
||||||
# PRIMITIVE_TYPE = 1
|
|
||||||
#
|
|
||||||
# Primitive types have only type size.
|
|
||||||
symbol_builtin_type_int := S(1, 4);
|
|
||||||
symbol_builtin_type_word := S(1, 4);
|
|
||||||
symbol_builtin_type_pointer := S(1, 4);
|
|
||||||
symbol_builtin_type_char := S(1, 1);
|
|
||||||
symbol_builtin_type_bool := S(1, 1);
|
|
||||||
|
|
||||||
# Info objects start with a word describing its type.
|
|
||||||
#
|
|
||||||
# INFO_TYPE = 1
|
|
||||||
#
|
|
||||||
# Type info has the type it belongs to.
|
|
||||||
symbol_type_info_int := S(1, @symbol_builtin_type_int);
|
|
||||||
symbol_type_info_word := S(1, @symbol_builtin_type_word);
|
|
||||||
symbol_type_info_pointer := S(1, @symbol_builtin_type_pointer);
|
|
||||||
symbol_type_info_char := S(1, @symbol_builtin_type_char);
|
|
||||||
symbol_type_info_bool := S(1, @symbol_builtin_type_bool);
|
|
||||||
SECTION
|
|
||||||
elsif line == ".section .data\n"
|
|
||||||
current_stage << "var\n"
|
|
||||||
elsif !(line == ".section .text\n" || line == ".globl _start\n")
|
|
||||||
current_stage << line
|
current_stage << line
|
||||||
|
elsif comment_match[2].empty?
|
||||||
|
current_stage << "\n"
|
||||||
|
else
|
||||||
|
current_stage << "#{comment_match[1]}(* #{comment_match[2].strip} *)\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
694
boot/stage8.elna
694
boot/stage8.elna
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
# Stage 8 compiler.
|
# Stage 8 compiler.
|
||||||
#
|
#
|
||||||
|
# - Procedure calls in expressions.
|
||||||
|
# - Comments between (* and *) are supported. These are still single line
|
||||||
|
# comments and they should be on a separate line.
|
||||||
const
|
const
|
||||||
symbol_builtin_name_int := "Int";
|
symbol_builtin_name_int := "Int";
|
||||||
symbol_builtin_name_word := "Word";
|
symbol_builtin_name_word := "Word";
|
||||||
@@ -34,14 +36,13 @@ const
|
|||||||
symbol_type_info_char := S(1, @symbol_builtin_type_char);
|
symbol_type_info_char := S(1, @symbol_builtin_type_char);
|
||||||
symbol_type_info_bool := S(1, @symbol_builtin_type_bool);
|
symbol_type_info_bool := S(1, @symbol_builtin_type_bool);
|
||||||
|
|
||||||
# When modifiying also change the read size in the entry point procedure.
|
|
||||||
.type source_code, @object
|
|
||||||
source_code: .zero 81920
|
|
||||||
|
|
||||||
.type compiler_strings, @object
|
|
||||||
compiler_strings: .zero 8192
|
|
||||||
|
|
||||||
var
|
var
|
||||||
|
source_code: Array;
|
||||||
|
compiler_strings: Array;
|
||||||
|
symbol_table_global: Array;
|
||||||
|
symbol_table_local: Array;
|
||||||
|
classification: Array;
|
||||||
|
|
||||||
compiler_strings_position: Pointer := @compiler_strings;
|
compiler_strings_position: Pointer := @compiler_strings;
|
||||||
compiler_strings_length: Word := 0;
|
compiler_strings_length: Word := 0;
|
||||||
source_code_position: Pointer := @source_code;
|
source_code_position: Pointer := @source_code;
|
||||||
@@ -130,7 +131,8 @@ begin
|
|||||||
mv a1, a0
|
mv a1, a0
|
||||||
# STDIN.
|
# STDIN.
|
||||||
li a0, 0
|
li a0, 0
|
||||||
li a7, 63 # SYS_READ.
|
# SYS_READ.
|
||||||
|
li a7, 63
|
||||||
ecall
|
ecall
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -145,7 +147,8 @@ begin
|
|||||||
mv a1, a0
|
mv a1, a0
|
||||||
# STDOUT.
|
# STDOUT.
|
||||||
li a0, 1
|
li a0, 1
|
||||||
li a7, 64 # SYS_WRITE.
|
# SYS_WRITE.
|
||||||
|
li a7, 64
|
||||||
ecall
|
ecall
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@@ -323,7 +326,8 @@ begin
|
|||||||
|
|
||||||
.read_token_loop:
|
.read_token_loop:
|
||||||
lw t0, 0(sp)
|
lw t0, 0(sp)
|
||||||
lb t0, (t0) # Current character.
|
# Current character.
|
||||||
|
lb t0, (t0)
|
||||||
|
|
||||||
# First we try to read a derictive.
|
# First we try to read a derictive.
|
||||||
# A derictive can contain a dot and characters.
|
# A derictive can contain a dot and characters.
|
||||||
@@ -425,44 +429,6 @@ begin
|
|||||||
return v88
|
return v88
|
||||||
end;
|
end;
|
||||||
|
|
||||||
proc _compile_section();
|
|
||||||
begin
|
|
||||||
# Print and skip the ".section" (8 characters) directive and a space after it.
|
|
||||||
_write_token(9);
|
|
||||||
_advance_token();
|
|
||||||
|
|
||||||
# Read the section name.
|
|
||||||
_read_token();
|
|
||||||
addi a0, a0, 1
|
|
||||||
|
|
||||||
_write_token();
|
|
||||||
_advance_token();
|
|
||||||
end;
|
|
||||||
|
|
||||||
# Prints and skips a line.
|
|
||||||
proc _skip_comment();
|
|
||||||
begin
|
|
||||||
la t0, source_code_position
|
|
||||||
lw t1, (t0)
|
|
||||||
|
|
||||||
.skip_comment_loop:
|
|
||||||
# Check for newline character.
|
|
||||||
lb t2, (t1)
|
|
||||||
li t3, '\n'
|
|
||||||
beq t2, t3, .skip_comment_end
|
|
||||||
|
|
||||||
# Advance the input string by one byte.
|
|
||||||
addi t1, t1, 1
|
|
||||||
sw t1, (t0)
|
|
||||||
|
|
||||||
goto .skip_comment_loop;
|
|
||||||
|
|
||||||
.skip_comment_end:
|
|
||||||
# Skip the newline.
|
|
||||||
addi t1, t1, 1
|
|
||||||
sw t1, (t0)
|
|
||||||
end;
|
|
||||||
|
|
||||||
# Prints and skips a line.
|
# Prints and skips a line.
|
||||||
proc _compile_line();
|
proc _compile_line();
|
||||||
begin
|
begin
|
||||||
@@ -601,6 +567,9 @@ begin
|
|||||||
li t1, '"'
|
li t1, '"'
|
||||||
beq a0, t1, .compile_term_string_literal
|
beq a0, t1, .compile_term_string_literal
|
||||||
|
|
||||||
|
li t1, '_'
|
||||||
|
beq a0, t1, .compile_term_call
|
||||||
|
|
||||||
_is_digit(v0);
|
_is_digit(v0);
|
||||||
bnez a0, .compile_term_integer_literal
|
bnez a0, .compile_term_integer_literal
|
||||||
|
|
||||||
@@ -630,6 +599,11 @@ begin
|
|||||||
_compile_string_literal();
|
_compile_string_literal();
|
||||||
goto .compile_term_end;
|
goto .compile_term_end;
|
||||||
|
|
||||||
|
.compile_term_call:
|
||||||
|
_compile_call();
|
||||||
|
_write_z("\nmv t0, a0\n\0");
|
||||||
|
goto .compile_term_end;
|
||||||
|
|
||||||
.compile_term_variable:
|
.compile_term_variable:
|
||||||
_compile_variable_expression();
|
_compile_variable_expression();
|
||||||
goto .compile_term_end;
|
goto .compile_term_end;
|
||||||
@@ -1038,6 +1012,8 @@ end;
|
|||||||
proc _compile_procedure_body();
|
proc _compile_procedure_body();
|
||||||
begin
|
begin
|
||||||
.compile_procedure_body_loop:
|
.compile_procedure_body_loop:
|
||||||
|
_skip_empty_lines();
|
||||||
|
|
||||||
# 3 is "end" length.
|
# 3 is "end" length.
|
||||||
_memcmp(source_code_position, "end", 3);
|
_memcmp(source_code_position, "end", 3);
|
||||||
|
|
||||||
@@ -1091,7 +1067,8 @@ begin
|
|||||||
_advance_token(5);
|
_advance_token(5);
|
||||||
|
|
||||||
_read_token();
|
_read_token();
|
||||||
sw a0, 0(sp) # Save the procedure name length.
|
# Save the procedure name length.
|
||||||
|
sw a0, 0(sp)
|
||||||
|
|
||||||
# Write .type _procedure_name, @function.
|
# Write .type _procedure_name, @function.
|
||||||
_write_z(".type \0");
|
_write_z(".type \0");
|
||||||
@@ -1136,13 +1113,41 @@ begin
|
|||||||
.skip_newlines_end:
|
.skip_newlines_end:
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
# Prints and skips a line.
|
||||||
|
proc _skip_comment();
|
||||||
|
begin
|
||||||
|
la t0, source_code_position
|
||||||
|
lw t1, (t0)
|
||||||
|
|
||||||
|
.skip_comment_loop:
|
||||||
|
# Check for newline character.
|
||||||
|
lb t2, (t1)
|
||||||
|
li t3, '\n'
|
||||||
|
beq t2, t3, .skip_comment_end
|
||||||
|
|
||||||
|
# Advance the input string by one byte.
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, (t0)
|
||||||
|
|
||||||
|
goto .skip_comment_loop;
|
||||||
|
|
||||||
|
.skip_comment_end:
|
||||||
|
# Skip the newline.
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, (t0)
|
||||||
|
end;
|
||||||
|
|
||||||
# Skip newlines and comments.
|
# Skip newlines and comments.
|
||||||
proc _skip_empty_lines();
|
proc _skip_empty_lines();
|
||||||
begin
|
begin
|
||||||
.skip_empty_lines_loop:
|
.skip_empty_lines_rerun:
|
||||||
la t0, source_code_position
|
la t0, source_code_position
|
||||||
lw t0, (t0)
|
lw t0, (t0)
|
||||||
lb t0, (t0)
|
sw t0, 0(sp)
|
||||||
|
|
||||||
|
.skip_empty_lines_loop:
|
||||||
|
lw t2, 0(sp)
|
||||||
|
lb t0, (t2)
|
||||||
|
|
||||||
li t1, '#'
|
li t1, '#'
|
||||||
beq t0, t1, .skip_empty_lines_comment
|
beq t0, t1, .skip_empty_lines_comment
|
||||||
@@ -1150,15 +1155,35 @@ begin
|
|||||||
li t1, '\n'
|
li t1, '\n'
|
||||||
beq t0, t1, .skip_empty_lines_newline
|
beq t0, t1, .skip_empty_lines_newline
|
||||||
|
|
||||||
|
li t1, '\t'
|
||||||
|
beq t0, t1, .skip_empty_lines_tab
|
||||||
|
|
||||||
|
li t1, '('
|
||||||
|
bne t0, t1, .skip_empty_lines_end
|
||||||
|
addi t2, t2, 1
|
||||||
|
lb t0, (t2)
|
||||||
|
li t1, '*'
|
||||||
|
beq t0, t1, .skip_empty_lines_comment
|
||||||
|
|
||||||
goto .skip_empty_lines_end;
|
goto .skip_empty_lines_end;
|
||||||
|
|
||||||
.skip_empty_lines_comment:
|
.skip_empty_lines_comment:
|
||||||
|
la t0, source_code_position
|
||||||
|
lw t1, 0(sp)
|
||||||
|
sw t1, (t0)
|
||||||
_skip_comment();
|
_skip_comment();
|
||||||
goto .skip_empty_lines_loop;
|
goto .skip_empty_lines_rerun;
|
||||||
|
|
||||||
.skip_empty_lines_newline:
|
.skip_empty_lines_newline:
|
||||||
_advance_token(1);
|
la t0, source_code_position
|
||||||
goto .skip_empty_lines_loop;
|
lw t1, 0(sp)
|
||||||
|
addi t1, t1, 1
|
||||||
|
sw t1, (t0)
|
||||||
|
goto .skip_empty_lines_rerun;
|
||||||
|
|
||||||
|
.skip_empty_lines_tab:
|
||||||
|
v0 := v0 + 1;
|
||||||
|
goto .skip_empty_lines_loop
|
||||||
|
|
||||||
.skip_empty_lines_end:
|
.skip_empty_lines_end:
|
||||||
end;
|
end;
|
||||||
@@ -1295,12 +1320,6 @@ begin
|
|||||||
|
|
||||||
_advance_token(1);
|
_advance_token(1);
|
||||||
|
|
||||||
la t0, source_code_position
|
|
||||||
lw t0, (t0)
|
|
||||||
lb t0, (t0)
|
|
||||||
li t1, '#'
|
|
||||||
beq t0, t1, .compile_const_part_loop
|
|
||||||
|
|
||||||
_compile_constant_declaration();
|
_compile_constant_declaration();
|
||||||
goto .compile_const_part_loop;
|
goto .compile_const_part_loop;
|
||||||
|
|
||||||
@@ -1358,18 +1377,16 @@ begin
|
|||||||
_write_z(".section .data\n\0");
|
_write_z(".section .data\n\0");
|
||||||
|
|
||||||
.compile_var_part_loop:
|
.compile_var_part_loop:
|
||||||
|
_skip_empty_lines();
|
||||||
|
|
||||||
la t0, source_code_position
|
la t0, source_code_position
|
||||||
lw t0, (t0)
|
lw t0, (t0)
|
||||||
lb t0, (t0)
|
lb t0, (t0)
|
||||||
|
|
||||||
li t1, 'p'
|
|
||||||
beq t0, t1, .compile_var_part_end
|
|
||||||
|
|
||||||
li t1, '\t'
|
li t1, '\t'
|
||||||
beq t0, t1, .compile_var_part_declaration
|
beq t0, t1, .compile_var_part_declaration
|
||||||
|
|
||||||
_compile_line();
|
goto .compile_var_part_end;
|
||||||
goto .compile_var_part_loop;
|
|
||||||
|
|
||||||
.compile_var_part_declaration:
|
.compile_var_part_declaration:
|
||||||
_advance_token(1);
|
_advance_token(1);
|
||||||
@@ -1383,64 +1400,25 @@ end;
|
|||||||
proc _compile_module();
|
proc _compile_module();
|
||||||
begin
|
begin
|
||||||
_compile_const_part();
|
_compile_const_part();
|
||||||
_write_z(".section .bss\n\0");
|
_skip_empty_lines();
|
||||||
|
|
||||||
.compile_module_bss:
|
|
||||||
la t0, source_code_position
|
|
||||||
lw t0, (t0)
|
|
||||||
lb t0, (t0)
|
|
||||||
li t1, 'v'
|
|
||||||
beq t0, t1, .compile_module_code
|
|
||||||
|
|
||||||
li t1, 'p'
|
|
||||||
beq t0, t1, .compile_module_code
|
|
||||||
|
|
||||||
_compile_line();
|
|
||||||
goto .compile_module_bss;
|
|
||||||
|
|
||||||
.compile_module_code:
|
|
||||||
_compile_var_part();
|
_compile_var_part();
|
||||||
|
|
||||||
_write_z(".section .text\n\0");
|
_write_z(".section .text\n\0");
|
||||||
.compile_module_loop:
|
.compile_module_loop:
|
||||||
_skip_newlines();
|
_skip_empty_lines();
|
||||||
|
|
||||||
la t0, source_code_position
|
la t0, source_code_position
|
||||||
lw t0, (t0)
|
lw t0, (t0)
|
||||||
lb t0, (t0)
|
lb t0, (t0)
|
||||||
beqz t0, .compile_module_end
|
beqz t0, .compile_module_end
|
||||||
li t1, '#'
|
|
||||||
beq t0, t1, .compile_module_comment
|
|
||||||
|
|
||||||
# 8 is ".section" length.
|
|
||||||
_memcmp(source_code_position, ".section", 8);
|
|
||||||
beqz a0, .compile_module_section
|
|
||||||
|
|
||||||
# 5 is "proc " length. Space is needed to distinguish from "procedure".
|
# 5 is "proc " length. Space is needed to distinguish from "procedure".
|
||||||
_memcmp(source_code_position, "proc ", 5);
|
_memcmp(source_code_position, "proc ", 5);
|
||||||
beqz a0, .compile_module_procedure
|
beqz a0, .compile_module_procedure
|
||||||
|
|
||||||
# 6 is ".globl" length.
|
|
||||||
_memcmp(source_code_position, ".globl", 6);
|
|
||||||
beqz a0, .compile_module_global
|
|
||||||
|
|
||||||
# Not a known token, exit.
|
# Not a known token, exit.
|
||||||
goto .compile_module_end;
|
goto .compile_module_end;
|
||||||
|
|
||||||
.compile_module_section:
|
|
||||||
_compile_section();
|
|
||||||
|
|
||||||
goto .compile_module_loop;
|
|
||||||
|
|
||||||
.compile_module_global:
|
|
||||||
_compile_line();
|
|
||||||
|
|
||||||
goto .compile_module_loop;
|
|
||||||
|
|
||||||
.compile_module_comment:
|
|
||||||
_skip_comment();
|
|
||||||
|
|
||||||
goto .compile_module_loop;
|
|
||||||
|
|
||||||
.compile_module_procedure:
|
.compile_module_procedure:
|
||||||
_compile_procedure();
|
_compile_procedure();
|
||||||
|
|
||||||
@@ -1490,14 +1468,512 @@ begin
|
|||||||
ecall
|
ecall
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
# Inserts a symbol into the table.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# a0 - Symbol pointer.
|
||||||
|
# a1 - Symbol name length.
|
||||||
|
# a2 - Symbol name pointer.
|
||||||
|
# a3 - Symbol table.
|
||||||
|
proc _symbol_table_enter();
|
||||||
|
begin
|
||||||
|
# The first word in the symbol table is its length, get it.
|
||||||
|
lw a0, 76(sp)
|
||||||
|
lw a0, (a0)
|
||||||
|
sw a0, 0(sp)
|
||||||
|
|
||||||
|
# Calculate the offset for the new symbol.
|
||||||
|
v4 := v0 * 4;
|
||||||
|
v4 := v4 + 4;
|
||||||
|
v4 := v76 + 4;
|
||||||
|
|
||||||
|
_memcpy(v4, @v80, 12);
|
||||||
|
|
||||||
|
# Increment the symbol table length.
|
||||||
|
v0 := v0 + 1;
|
||||||
|
lw t0, 0(sp)
|
||||||
|
lw t1, 76(sp)
|
||||||
|
sw t0, (t1)
|
||||||
|
end;
|
||||||
|
|
||||||
|
proc _symbol_table_build();
|
||||||
|
begin
|
||||||
|
_symbol_table_enter(@symbol_type_info_int, 3, symbol_builtin_name_int, @symbol_table_global);
|
||||||
|
_symbol_table_enter(@symbol_type_info_word, 4, symbol_builtin_name_word, @symbol_table_global);
|
||||||
|
_symbol_table_enter(@symbol_type_info_pointer, 7, symbol_builtin_name_pointer, @symbol_table_global);
|
||||||
|
_symbol_table_enter(@symbol_type_info_char, 4, symbol_builtin_name_char, @symbol_table_global);
|
||||||
|
_symbol_table_enter(@symbol_type_info_bool, 4, symbol_builtin_name_bool, @symbol_table_global);
|
||||||
|
end;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Classification table assigns each possible character to a group (class). All
|
||||||
|
# characters of the same group a handled equivalently.
|
||||||
|
#
|
||||||
|
# Classification:
|
||||||
|
#
|
||||||
|
# TransitionClass = (
|
||||||
|
# transitionClassInvalid = 1,
|
||||||
|
# transitionClassDigit = 2,
|
||||||
|
# transitionClassAlpha = 3,
|
||||||
|
# transitionClassSpace = 4,
|
||||||
|
# transitionClassColon = 5,
|
||||||
|
# transitionClassEquals = 6,
|
||||||
|
# transitionClassLeftParen = 7,
|
||||||
|
# transitionClassRightParen = 8,
|
||||||
|
# transitionClassAsterisk = 9,
|
||||||
|
# transitionClassUnderscore = 10,
|
||||||
|
# transitionClassSingle = 11,
|
||||||
|
# transitionClassHex = 12,
|
||||||
|
# transitionClassZero = 13,
|
||||||
|
# transitionClassX = 14,
|
||||||
|
# transitionClassEof = 15,
|
||||||
|
# transitionClassDot = 16,
|
||||||
|
# transitionClassMinus = 17,
|
||||||
|
# transitionClassSingleQuote = 18,
|
||||||
|
# transitionClassDoubleQuote = 19,
|
||||||
|
# transitionClassGreater = 20,
|
||||||
|
# transitionClassLess = 21,
|
||||||
|
# transitionClassOther = 22
|
||||||
|
# );
|
||||||
|
# TransitionState = (
|
||||||
|
# transitionStateStart = 1,
|
||||||
|
# transitionStateColon = 2,
|
||||||
|
# transitionStateIdentifier = 3,
|
||||||
|
# transitionStateDecimal = 4,
|
||||||
|
# transitionStateGreater = 5,
|
||||||
|
# transitionStateMinus = 6,
|
||||||
|
# transitionStateLeftParen = 7,
|
||||||
|
# transitionStateLess = 8,
|
||||||
|
# transitionStateDot = 9,
|
||||||
|
# transitionStateComment = 10,
|
||||||
|
# transitionStateClosingComment = 11,
|
||||||
|
# transitionStateCharacter = 12,
|
||||||
|
# transitionStateString = 13,
|
||||||
|
# transitionStateLeadingZero = 14,
|
||||||
|
# transitionStateDecimalSuffix = 15,
|
||||||
|
# transitionStateEnd = 16
|
||||||
|
# );
|
||||||
|
# Transition = record
|
||||||
|
# action: TransitionAction;
|
||||||
|
# next_state: TransitionState
|
||||||
|
# end;
|
||||||
|
# TransitionAction = (
|
||||||
|
# none = 1,
|
||||||
|
# accumulate = 2,
|
||||||
|
# skip = 3,
|
||||||
|
# single = 4,
|
||||||
|
# eof = 5,
|
||||||
|
# finalize = 6,
|
||||||
|
# composite = 7,
|
||||||
|
# key_id = 8,
|
||||||
|
# integer = 9,
|
||||||
|
# delimited = 10
|
||||||
|
# );
|
||||||
|
|
||||||
|
# Assigns some value to at array index.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# a0 - Array pointer.
|
||||||
|
# a1 - Index (word offset into the array).
|
||||||
|
# a2 - Data to assign.
|
||||||
|
proc _assign_at();
|
||||||
|
begin
|
||||||
|
v0 := v84 + -1;
|
||||||
|
v0 := v0 * 4;
|
||||||
|
v0 := v88 + v0;
|
||||||
|
|
||||||
|
lw t0, 0(sp)
|
||||||
|
lw t1, 80(sp)
|
||||||
|
sw t1, (t0)
|
||||||
|
end;
|
||||||
|
|
||||||
|
proc _initialize_classification();
|
||||||
|
begin
|
||||||
|
_assign_at(@classification, 1, 15);
|
||||||
|
_assign_at(@classification, 2, 1);
|
||||||
|
_assign_at(@classification, 3, 1);
|
||||||
|
_assign_at(@classification, 4, 1);
|
||||||
|
_assign_at(@classification, 5, 1);
|
||||||
|
_assign_at(@classification, 6, 1);
|
||||||
|
_assign_at(@classification, 7, 1);
|
||||||
|
_assign_at(@classification, 8, 1);
|
||||||
|
_assign_at(@classification, 9, 1);
|
||||||
|
_assign_at(@classification, 10, 4);
|
||||||
|
_assign_at(@classification, 11, 4);
|
||||||
|
_assign_at(@classification, 12, 1);
|
||||||
|
_assign_at(@classification, 13, 1);
|
||||||
|
_assign_at(@classification, 14, 4);
|
||||||
|
_assign_at(@classification, 15, 1);
|
||||||
|
_assign_at(@classification, 16, 1);
|
||||||
|
_assign_at(@classification, 17, 1);
|
||||||
|
_assign_at(@classification, 18, 1);
|
||||||
|
_assign_at(@classification, 19, 1);
|
||||||
|
_assign_at(@classification, 20, 1);
|
||||||
|
_assign_at(@classification, 21, 1);
|
||||||
|
_assign_at(@classification, 22, 1);
|
||||||
|
_assign_at(@classification, 23, 1);
|
||||||
|
_assign_at(@classification, 24, 1);
|
||||||
|
_assign_at(@classification, 25, 1);
|
||||||
|
_assign_at(@classification, 26, 1);
|
||||||
|
_assign_at(@classification, 27, 1);
|
||||||
|
_assign_at(@classification, 28, 1);
|
||||||
|
_assign_at(@classification, 29, 1);
|
||||||
|
_assign_at(@classification, 30, 1);
|
||||||
|
_assign_at(@classification, 31, 1);
|
||||||
|
_assign_at(@classification, 32, 1);
|
||||||
|
_assign_at(@classification, 33, 4);
|
||||||
|
_assign_at(@classification, 34, 11);
|
||||||
|
_assign_at(@classification, 35, 19);
|
||||||
|
_assign_at(@classification, 36, 22);
|
||||||
|
_assign_at(@classification, 37, 22);
|
||||||
|
_assign_at(@classification, 38, 11);
|
||||||
|
_assign_at(@classification, 39, 11);
|
||||||
|
_assign_at(@classification, 40, 18);
|
||||||
|
_assign_at(@classification, 41, 7);
|
||||||
|
_assign_at(@classification, 42, 8);
|
||||||
|
_assign_at(@classification, 43, 9);
|
||||||
|
_assign_at(@classification, 44, 11);
|
||||||
|
_assign_at(@classification, 45, 11);
|
||||||
|
_assign_at(@classification, 46, 17);
|
||||||
|
_assign_at(@classification, 47, 16);
|
||||||
|
_assign_at(@classification, 48, 11);
|
||||||
|
_assign_at(@classification, 49, 13);
|
||||||
|
_assign_at(@classification, 50, 2);
|
||||||
|
_assign_at(@classification, 51, 2);
|
||||||
|
_assign_at(@classification, 52, 2);
|
||||||
|
_assign_at(@classification, 53, 2);
|
||||||
|
_assign_at(@classification, 54, 2);
|
||||||
|
_assign_at(@classification, 55, 2);
|
||||||
|
_assign_at(@classification, 56, 2);
|
||||||
|
_assign_at(@classification, 57, 2);
|
||||||
|
_assign_at(@classification, 58, 2);
|
||||||
|
_assign_at(@classification, 59, 5);
|
||||||
|
_assign_at(@classification, 60, 11);
|
||||||
|
_assign_at(@classification, 61, 21);
|
||||||
|
_assign_at(@classification, 62, 6);
|
||||||
|
_assign_at(@classification, 63, 20);
|
||||||
|
_assign_at(@classification, 64, 22);
|
||||||
|
_assign_at(@classification, 65, 11);
|
||||||
|
_assign_at(@classification, 66, 3);
|
||||||
|
_assign_at(@classification, 67, 3);
|
||||||
|
_assign_at(@classification, 68, 3);
|
||||||
|
_assign_at(@classification, 69, 3);
|
||||||
|
_assign_at(@classification, 70, 3);
|
||||||
|
_assign_at(@classification, 71, 3);
|
||||||
|
_assign_at(@classification, 72, 3);
|
||||||
|
_assign_at(@classification, 73, 3);
|
||||||
|
_assign_at(@classification, 74, 3);
|
||||||
|
_assign_at(@classification, 75, 3);
|
||||||
|
_assign_at(@classification, 76, 3);
|
||||||
|
_assign_at(@classification, 77, 3);
|
||||||
|
_assign_at(@classification, 78, 3);
|
||||||
|
_assign_at(@classification, 79, 3);
|
||||||
|
_assign_at(@classification, 80, 3);
|
||||||
|
_assign_at(@classification, 81, 3);
|
||||||
|
_assign_at(@classification, 82, 3);
|
||||||
|
_assign_at(@classification, 83, 3);
|
||||||
|
_assign_at(@classification, 84, 3);
|
||||||
|
_assign_at(@classification, 85, 3);
|
||||||
|
_assign_at(@classification, 86, 3);
|
||||||
|
_assign_at(@classification, 87, 3);
|
||||||
|
_assign_at(@classification, 88, 3);
|
||||||
|
_assign_at(@classification, 89, 3);
|
||||||
|
_assign_at(@classification, 90, 3);
|
||||||
|
_assign_at(@classification, 91, 3);
|
||||||
|
_assign_at(@classification, 92, 11);
|
||||||
|
_assign_at(@classification, 93, 22);
|
||||||
|
_assign_at(@classification, 94, 11);
|
||||||
|
_assign_at(@classification, 95, 11);
|
||||||
|
_assign_at(@classification, 96, 10);
|
||||||
|
_assign_at(@classification, 97, 22);
|
||||||
|
_assign_at(@classification, 98, 12);
|
||||||
|
_assign_at(@classification, 99, 12);
|
||||||
|
_assign_at(@classification, 100, 12);
|
||||||
|
_assign_at(@classification, 101, 12);
|
||||||
|
_assign_at(@classification, 102, 12);
|
||||||
|
_assign_at(@classification, 103, 12);
|
||||||
|
_assign_at(@classification, 104, 3);
|
||||||
|
_assign_at(@classification, 105, 3);
|
||||||
|
_assign_at(@classification, 106, 3);
|
||||||
|
_assign_at(@classification, 107, 3);
|
||||||
|
_assign_at(@classification, 108, 3);
|
||||||
|
_assign_at(@classification, 109, 3);
|
||||||
|
_assign_at(@classification, 110, 3);
|
||||||
|
_assign_at(@classification, 111, 3);
|
||||||
|
_assign_at(@classification, 112, 3);
|
||||||
|
_assign_at(@classification, 113, 3);
|
||||||
|
_assign_at(@classification, 114, 3);
|
||||||
|
_assign_at(@classification, 115, 3);
|
||||||
|
_assign_at(@classification, 116, 3);
|
||||||
|
_assign_at(@classification, 117, 3);
|
||||||
|
_assign_at(@classification, 118, 3);
|
||||||
|
_assign_at(@classification, 119, 3);
|
||||||
|
_assign_at(@classification, 120, 3);
|
||||||
|
_assign_at(@classification, 121, 14);
|
||||||
|
_assign_at(@classification, 122, 3);
|
||||||
|
_assign_at(@classification, 123, 3);
|
||||||
|
_assign_at(@classification, 124, 22);
|
||||||
|
_assign_at(@classification, 125, 11);
|
||||||
|
_assign_at(@classification, 126, 22);
|
||||||
|
_assign_at(@classification, 127, 11);
|
||||||
|
_assign_at(@classification, 128, 1);
|
||||||
|
|
||||||
|
v0 := 129;
|
||||||
|
|
||||||
|
# Set the remaining 129 - 256 bytes to transitionClassOther.
|
||||||
|
.initialize_classification_loop:
|
||||||
|
_assign_at(@classification, v0, 22);
|
||||||
|
v0 := v0 + 1;
|
||||||
|
|
||||||
|
lw t0, 0(sp)
|
||||||
|
li t1, 257
|
||||||
|
blt t0, t1, .initialize_classification_loop
|
||||||
|
end;
|
||||||
|
|
||||||
|
# Parameters:
|
||||||
|
# a0 - Current state (first index into transitions table).
|
||||||
|
# a1 - Transition (second index into transitions table)..
|
||||||
|
# a2 - Action to assign.
|
||||||
|
# a3 - Next state to assign.
|
||||||
|
proc _set_transition();
|
||||||
|
begin
|
||||||
|
# Transitions start at offset in classification array. Save the transitions start in v0.
|
||||||
|
la t0, classification
|
||||||
|
addi t0, t0, 256
|
||||||
|
sw t0, 0(sp)
|
||||||
|
|
||||||
|
# Each state is 8 bytes long (2 words: action and next state).
|
||||||
|
# There are 16 transition classes, so a transition 8 * 16 = 128 bytes long.
|
||||||
|
|
||||||
|
v4 := v88 + -1;
|
||||||
|
v4 := v4 * 128;
|
||||||
|
|
||||||
|
v8 := v84 + -1;
|
||||||
|
v8 := v8 * 8;
|
||||||
|
|
||||||
|
v12 := v0 + v4;
|
||||||
|
v12 := v12 + v8;
|
||||||
|
|
||||||
|
lw t0, 12(sp)
|
||||||
|
lw t1, 80(sp)
|
||||||
|
lw t2, 76(sp)
|
||||||
|
sw t1, (t0)
|
||||||
|
addi t0, t0, 4
|
||||||
|
sw t2, (t0)
|
||||||
|
end;
|
||||||
|
|
||||||
|
# Parameters:
|
||||||
|
# a0 - Current state (Transition state enumeration).
|
||||||
|
# a1 - Default action (Callback).
|
||||||
|
# a2 - Next state (Transition state enumeration).
|
||||||
|
proc _set_default_transition();
|
||||||
|
begin
|
||||||
|
_set_transition(v88, 1, v84, v80);
|
||||||
|
_set_transition(v88, 2, v84, v80);
|
||||||
|
_set_transition(v88, 3, v84, v80);
|
||||||
|
_set_transition(v88, 4, v84, v80);
|
||||||
|
_set_transition(v88, 5, v84, v80);
|
||||||
|
_set_transition(v88, 6, v84, v80);
|
||||||
|
_set_transition(v88, 7, v84, v80);
|
||||||
|
_set_transition(v88, 8, v84, v80);
|
||||||
|
_set_transition(v88, 9, v84, v80);
|
||||||
|
_set_transition(v88, 10, v84, v80);
|
||||||
|
_set_transition(v88, 11, v84, v80);
|
||||||
|
_set_transition(v88, 12, v84, v80);
|
||||||
|
_set_transition(v88, 13, v84, v80);
|
||||||
|
_set_transition(v88, 14, v84, v80);
|
||||||
|
_set_transition(v88, 15, v84, v80);
|
||||||
|
_set_transition(v88, 16, v84, v80);
|
||||||
|
_set_transition(v88, 17, v84, v80);
|
||||||
|
_set_transition(v88, 18, v84, v80);
|
||||||
|
_set_transition(v88, 19, v84, v80);
|
||||||
|
_set_transition(v88, 20, v84, v80);
|
||||||
|
_set_transition(v88, 21, v84, v80);
|
||||||
|
_set_transition(v88, 22, v84, v80);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
# The transition table describes transitions from one state to another, given
|
||||||
|
# a symbol (character class).
|
||||||
|
#
|
||||||
|
# The table has m rows and n columns, where m is the amount of states and n is
|
||||||
|
# the amount of classes. So given the current state and a classified character
|
||||||
|
# the table can be used to look up the next state.
|
||||||
|
#
|
||||||
|
# Each cell is a word long.
|
||||||
|
# - The least significant byte of the word is a row number (beginning with 0).
|
||||||
|
# It specifies the target state. "ff" means that this is an end state and no
|
||||||
|
# transition is possible.
|
||||||
|
# - The next byte is the action that should be performed when transitioning.
|
||||||
|
# For the meaning of actions see labels in the lex_next function, which
|
||||||
|
# handles each action.
|
||||||
|
proc _initialize_transitions();
|
||||||
|
begin
|
||||||
|
# Start state.
|
||||||
|
_set_transition(1, 1, 1, 16);
|
||||||
|
_set_transition(1, 2, 2, 4);
|
||||||
|
_set_transition(1, 3, 2, 3);
|
||||||
|
_set_transition(1, 4, 3, 1);
|
||||||
|
_set_transition(1, 5, 2, 5);
|
||||||
|
_set_transition(1, 6, 4, 16);
|
||||||
|
_set_transition(1, 7, 2, 7);
|
||||||
|
_set_transition(1, 8, 4, 16);
|
||||||
|
_set_transition(1, 9, 4, 16);
|
||||||
|
_set_transition(1, 10, 2, 3);
|
||||||
|
_set_transition(1, 11, 4, 16);
|
||||||
|
_set_transition(1, 12, 2, 3);
|
||||||
|
_set_transition(1, 13, 2, 14);
|
||||||
|
_set_transition(1, 14, 2, 3);
|
||||||
|
_set_transition(1, 15, 5, 16);
|
||||||
|
_set_transition(1, 16, 2, 9);
|
||||||
|
_set_transition(1, 17, 2, 6);
|
||||||
|
_set_transition(1, 18, 2, 12);
|
||||||
|
_set_transition(1, 19, 2, 13);
|
||||||
|
_set_transition(1, 20, 2, 5);
|
||||||
|
_set_transition(1, 21, 2, 8);
|
||||||
|
_set_transition(1, 22, 1, 16);
|
||||||
|
|
||||||
|
# Colon state.
|
||||||
|
_set_default_transition(2, 6, 16);
|
||||||
|
_set_transition(2, 6, 7, 16);
|
||||||
|
|
||||||
|
# Identifier state.
|
||||||
|
_set_default_transition(3, 8, 16);
|
||||||
|
_set_transition(3, 2, 2, 3);
|
||||||
|
_set_transition(3, 3, 2, 3);
|
||||||
|
_set_transition(3, 10, 2, 3);
|
||||||
|
_set_transition(3, 12, 2, 3);
|
||||||
|
_set_transition(3, 13, 2, 3);
|
||||||
|
_set_transition(3, 14, 2, 3);
|
||||||
|
|
||||||
|
# Decimal state.
|
||||||
|
_set_default_transition(4, 9, 16);
|
||||||
|
_set_transition(4, 2, 2, 4);
|
||||||
|
_set_transition(4, 3, 2, 15);
|
||||||
|
_set_transition(4, 10, 1, 16);
|
||||||
|
_set_transition(4, 12, 2, 15);
|
||||||
|
_set_transition(4, 13, 2, 4);
|
||||||
|
_set_transition(4, 14, 2, 15);
|
||||||
|
|
||||||
|
# Greater state.
|
||||||
|
_set_default_transition(5, 6, 16);
|
||||||
|
_set_transition(5, 6, 7, 16);
|
||||||
|
|
||||||
|
# Minus state.
|
||||||
|
_set_default_transition(6, 6, 16);
|
||||||
|
_set_transition(6, 20, 7, 16);
|
||||||
|
|
||||||
|
# Left paren state.
|
||||||
|
_set_default_transition(7, 6, 16);
|
||||||
|
_set_transition(7, 9, 2, 10);
|
||||||
|
|
||||||
|
# Less state.
|
||||||
|
_set_default_transition(8, 6, 16);
|
||||||
|
_set_transition(8, 6, 7, 16);
|
||||||
|
_set_transition(8, 20, 7, 16);
|
||||||
|
|
||||||
|
# Hexadecimal after 0x.
|
||||||
|
_set_default_transition(9, 6, 16);
|
||||||
|
_set_transition(9, 16, 7, 16);
|
||||||
|
|
||||||
|
# Comment.
|
||||||
|
_set_default_transition(10, 2, 10);
|
||||||
|
_set_transition(10, 9, 2, 11);
|
||||||
|
_set_transition(10, 15, 1, 16);
|
||||||
|
|
||||||
|
# Closing comment.
|
||||||
|
_set_default_transition(11, 2, 10);
|
||||||
|
_set_transition(11, 1, 1, 16);
|
||||||
|
_set_transition(11, 8, 10, 16);
|
||||||
|
_set_transition(11, 9, 2, 11);
|
||||||
|
_set_transition(11, 15, 1, 16);
|
||||||
|
|
||||||
|
# Character.
|
||||||
|
_set_default_transition(12, 2, 12);
|
||||||
|
_set_transition(12, 1, 1, 16);
|
||||||
|
_set_transition(12, 15, 1, 16);
|
||||||
|
_set_transition(12, 18, 10, 16);
|
||||||
|
|
||||||
|
# String.
|
||||||
|
_set_default_transition(13, 2, 13);
|
||||||
|
_set_transition(13, 1, 1, 16);
|
||||||
|
_set_transition(13, 15, 1, 16);
|
||||||
|
_set_transition(13, 19, 10, 16);
|
||||||
|
|
||||||
|
# Leading zero.
|
||||||
|
_set_default_transition(14, 9, 16);
|
||||||
|
_set_transition(14, 2, 1, 16);
|
||||||
|
_set_transition(14, 3, 1, 16);
|
||||||
|
_set_transition(14, 10, 1, 16);
|
||||||
|
_set_transition(14, 12, 1, 16);
|
||||||
|
_set_transition(14, 13, 1, 16);
|
||||||
|
_set_transition(14, 14, 1, 16);
|
||||||
|
|
||||||
|
# Digit with a character suffix.
|
||||||
|
_set_default_transition(15, 9, 16);
|
||||||
|
_set_transition(15, 3, 1, 16);
|
||||||
|
_set_transition(15, 2, 1, 16);
|
||||||
|
_set_transition(15, 12, 1, 16);
|
||||||
|
_set_transition(15, 13, 1, 16);
|
||||||
|
_set_transition(15, 14, 1, 16);
|
||||||
|
end;
|
||||||
|
|
||||||
|
proc _lexer_get_state();
|
||||||
|
begin
|
||||||
|
# Lexer state is saved after the transition tables. The offset is 256 + 16 * 22.
|
||||||
|
v0 := @classification;
|
||||||
|
v4 := 16 * 22;
|
||||||
|
v0 := v0 + 256;
|
||||||
|
|
||||||
|
return v0 + v4
|
||||||
|
end;
|
||||||
|
|
||||||
|
# Gets pointer to the current source text.
|
||||||
|
proc _lexer_get_current();
|
||||||
|
begin
|
||||||
|
_lexer_get_state();
|
||||||
|
sw a0, 0(sp)
|
||||||
|
|
||||||
|
return v0 + 4
|
||||||
|
end;
|
||||||
|
|
||||||
|
# Resets the lexer state for reading the next token.
|
||||||
|
proc _lexer_reset();
|
||||||
|
begin
|
||||||
|
# Transition start state is 1.
|
||||||
|
_lexer_get_state();
|
||||||
|
li t0, 1
|
||||||
|
sw t0, (a0)
|
||||||
|
sw a0, 0(sp)
|
||||||
|
|
||||||
|
# Text pointer to the beginning of the currently read token.
|
||||||
|
_lexer_get_current();
|
||||||
|
la t0, source_code_position
|
||||||
|
lw t0, (t0)
|
||||||
|
sw t0, (a0)
|
||||||
|
|
||||||
|
# Initial length of the token is 0.
|
||||||
|
addi t0, t0, 4
|
||||||
|
sw zero, (t0)
|
||||||
|
end;
|
||||||
|
|
||||||
|
# One time lexer initialization.
|
||||||
|
proc _lexer_initialize();
|
||||||
|
begin
|
||||||
|
_initialize_classification();
|
||||||
|
_initialize_transitions();
|
||||||
|
end;
|
||||||
|
|
||||||
# Entry point.
|
# Entry point.
|
||||||
proc _start();
|
proc _start();
|
||||||
begin
|
begin
|
||||||
|
_lexer_initialize();
|
||||||
|
_symbol_table_build();
|
||||||
|
|
||||||
# Read the source from the standard input.
|
# Read the source from the standard input.
|
||||||
# Second argument is buffer size. Modifying update the source_code definition.
|
# Second argument is buffer size. Modifying update the source_code definition.
|
||||||
_read_file(@source_code, 81920);
|
_read_file(@source_code, 81920);
|
||||||
_compile();
|
_compile();
|
||||||
|
|
||||||
_exit(0);
|
_exit(0);
|
||||||
|
|
||||||
end;
|
end;
|
||||||
|
1181
boot/stage9.elna
1181
boot/stage9.elna
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user