Parse the variable part to AST

This commit is contained in:
Eugen Wissner 2025-06-04 12:14:04 +02:00
parent 82f0d40a56
commit 7c12fc1364
Signed by: belka
GPG Key ID: A27FDC1E8EE902C0
5 changed files with 89 additions and 31 deletions

View File

@ -101,6 +101,7 @@ task :backport do
source = File.read source_path source = File.read source_path
current_procedure = nil current_procedure = nil
target = '' target = ''
module_name = source_path.basename.sub_ext('')
source source
.gsub(/^(var|type|const|begin)/) { |match| match.upcase } .gsub(/^(var|type|const|begin)/) { |match| match.upcase }
@ -109,7 +110,8 @@ task :backport do
.gsub(/proc\(/, 'PROCEDURE(') .gsub(/proc\(/, 'PROCEDURE(')
.gsub(/ & /, ' AND ') .gsub(/ & /, ' AND ')
.gsub(/ -> /, ': ') .gsub(/ -> /, ': ')
.gsub(/end\./, "END #{source_path.basename.sub_ext('')}.") .gsub(/program;/, "MODULE #{module_name};")
.gsub(/end\./, "END #{module_name}.")
.gsub(/([[:space:]]*)end(;?)$/, '\1END\2') .gsub(/([[:space:]]*)end(;?)$/, '\1END\2')
.gsub(/^([[:space:]]*)(while|return|if)\b/) { |match| match.upcase } .gsub(/^([[:space:]]*)(while|return|if)\b/) { |match| match.upcase }
.gsub(/^from ([[:alnum:]]+) import/, 'FROM \1 IMPORT') .gsub(/^from ([[:alnum:]]+) import/, 'FROM \1 IMPORT')

View File

@ -1,4 +1,4 @@
module Compiler; program;
from FIO import Close, IsNoError, File, OpenToRead, StdErr, StdOut, WriteLine, WriteString; from FIO import Close, IsNoError, File, OpenToRead, StdErr, StdOut, WriteLine, WriteString;
from SYSTEM import ADR; from SYSTEM import ADR;

View File

@ -46,6 +46,8 @@ TYPE
PPAstTypeDeclaration = POINTER TO PAstTypeDeclaration; PPAstTypeDeclaration = POINTER TO PAstTypeDeclaration;
AstVariableDeclaration = RECORD AstVariableDeclaration = RECORD
variable_name: Identifier;
variable_type: PAstTypeExpression
END; END;
PAstVariableDeclaration = POINTER TO AstVariableDeclaration; PAstVariableDeclaration = POINTER TO AstVariableDeclaration;
PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration; PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration;
@ -58,7 +60,7 @@ TYPE
PAstModule = POINTER TO AstModule; PAstModule = POINTER TO AstModule;
PROCEDURE parse_type_expression(lexer: PLexer): PAstTypeExpression; PROCEDURE parse_type_expression(lexer: PLexer): PAstTypeExpression;
PROCEDURE parse_type_declaration(lexer: PLexer): PAstTypeDeclaration;
PROCEDURE parse_type_part(lexer: PLexer): PPAstTypeDeclaration; PROCEDURE parse_type_part(lexer: PLexer): PPAstTypeDeclaration;
PROCEDURE parse_variable_part(lexer: PLexer): PPAstVariableDeclaration;
END Parser. END Parser.

View File

@ -283,4 +283,58 @@ begin
return result return result
end; end;
proc parse_variable_declaration(lexer: PLexer) -> PAstVariableDeclaration;
var
token: LexerToken;
result: PAstVariableDeclaration;
begin
ALLOCATE(result, TSIZE(AstVariableDeclaration));
token := lexer_current(lexer);
result^.variable_name := token.identifierKind;
token := transpiler_lex(lexer);
token := transpiler_lex(lexer);
result^.variable_type := parse_type_expression(lexer);
token := transpiler_lex(lexer);
return result
end;
proc parse_variable_part(lexer: PLexer) -> PPAstVariableDeclaration;
var
token: LexerToken;
result: PPAstVariableDeclaration;
current_declaration: PPAstVariableDeclaration;
declaration_count: CARDINAL;
begin
token := lexer_current(lexer);
ALLOCATE(result, TSIZE(PAstVariableDeclaration));
current_declaration := result;
declaration_count := 0;
if token.kind = lexerKindVar then
token := transpiler_lex(lexer);
while token.kind = lexerKindIdentifier do
INC(declaration_count);
REALLOCATE(result, TSIZE(PAstVariableDeclaration) * (declaration_count + 1));
current_declaration := result;
INC(current_declaration, TSIZE(PAstVariableDeclaration) * (declaration_count - 1));
current_declaration^ := parse_variable_declaration(lexer);
token := transpiler_lex(lexer)
end
end;
if declaration_count <> 0 then
INC(current_declaration, TSIZE(PAstVariableDeclaration))
end;
current_declaration^ := nil;
return result
end;
end. end.

View File

@ -12,9 +12,9 @@ from Lexer import Lexer, LexerToken, lexer_current, lexer_lex, LexerKind;
from Parser import AstModule, PAstModule, AstTypeExpressionKind, from Parser import AstModule, PAstModule, AstTypeExpressionKind,
AstConstantDeclaration, PPAstConstantDeclaration, AstConstantDeclaration, PPAstConstantDeclaration,
AstTypeDeclaration, PAstTypeDeclaration, PPAstTypeDeclaration, AstTypeDeclaration, PAstTypeDeclaration, PPAstTypeDeclaration,
AstVariableDeclaration, PPAstVariableDeclaration, PAstVariableDeclaration, PPAstVariableDeclaration,
PAstTypeExpression, AstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration, PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration,
parse_type_expression, parse_type_declaration, parse_type_part; parse_type_expression, parse_variable_part, parse_type_part;
(* Calls lexer_lex() but skips the comments. *) (* Calls lexer_lex() but skips the comments. *)
proc transpiler_lex(lexer: PLexer) -> LexerToken; proc transpiler_lex(lexer: PLexer) -> LexerToken;
@ -138,7 +138,9 @@ begin
WriteString(context^.output, 'MODULE '); WriteString(context^.output, 'MODULE ');
(* Write the module name and end the line with a semicolon and newline. *) (* Write the module name and end the line with a semicolon and newline. *)
if token.kind <> lexerKindProgram then
token := transpiler_lex(context^.lexer); token := transpiler_lex(context^.lexer);
end;
transpile_module_name(context); transpile_module_name(context);
token := transpiler_lex(context^.lexer); token := transpiler_lex(context^.lexer);
@ -152,7 +154,9 @@ begin
result^.constants := transpile_constant_part(context); result^.constants := transpile_constant_part(context);
result^.types := parse_type_part(context^.lexer); result^.types := parse_type_part(context^.lexer);
transpile_type_part(context, result^.types); transpile_type_part(context, result^.types);
result^.variables := transpile_variable_part(context);
result^.variables := parse_variable_part(context^.lexer);
transpile_variable_part(context, result^.variables);
transpile_procedure_part(context); transpile_procedure_part(context);
transpile_statement_part(context); transpile_statement_part(context);
@ -334,41 +338,35 @@ begin
end end
end; end;
proc transpile_variable_declaration(context: PTranspilerContext); proc transpile_variable_declaration(context: PTranspilerContext, declaration: PAstVariableDeclaration);
var var
token: LexerToken; written_bytes: CARDINAL;
type_expression: PAstTypeExpression;
begin begin
WriteString(context^.output, ' '); WriteString(context^.output, ' ');
token := lexer_current(context^.lexer); written_bytes := WriteNBytes(context^.output, ORD(declaration^.variable_name[1]), ADR(declaration^.variable_name[2]));
write_current(context^.lexer, context^.output);
token := transpiler_lex(context^.lexer);
WriteString(context^.output, ': '); WriteString(context^.output, ': ');
token := transpiler_lex(context^.lexer);
type_expression := parse_type_expression(context^.lexer); transpile_type_expression(context, declaration^.variable_type);
transpile_type_expression(context, type_expression);
token := transpiler_lex(context^.lexer);
write_semicolon(context^.output) write_semicolon(context^.output)
end; end;
proc transpile_variable_part(context: PTranspilerContext) -> PPAstVariableDeclaration; proc transpile_variable_part(context: PTranspilerContext, declarations: PPAstVariableDeclaration);
var var
token: LexerToken; current_declaration: PPAstVariableDeclaration;
begin begin
token := lexer_current(context^.lexer); if declarations^ <> nil then
if token.kind = lexerKindVar then
WriteString(context^.output, 'VAR'); WriteString(context^.output, 'VAR');
WriteLine(context^.output); WriteLine(context^.output);
token := transpiler_lex(context^.lexer);
while token.kind = lexerKindIdentifier do current_declaration := declarations;
transpile_variable_declaration(context); while current_declaration^ <> nil do
token := transpiler_lex(context^.lexer) transpile_variable_declaration(context, current_declaration^);
end
INC(current_declaration, TSIZE(PAstVariableDeclaration))
end; end;
return nil WriteLine(context^.output)
end
end; end;
proc transpile_procedure_heading(context: PTranspilerContext) -> LexerToken; proc transpile_procedure_heading(context: PTranspilerContext) -> LexerToken;
@ -624,7 +622,9 @@ var
begin begin
token := transpile_procedure_heading(context); token := transpile_procedure_heading(context);
seen_constants := transpile_constant_part(context); seen_constants := transpile_constant_part(context);
seen_variables := transpile_variable_part(context);
seen_variables := parse_variable_part(context^.lexer);
transpile_variable_part(context, seen_variables);
transpile_statement_part(context); transpile_statement_part(context);
WriteString(context^.output, 'END '); WriteString(context^.output, 'END ');