Trace the source code position in the lexer

This commit is contained in:
2025-06-12 18:44:06 +02:00
parent 90aa5a0030
commit fdaeb25f73
7 changed files with 252 additions and 232 deletions

View File

@ -1,53 +1,37 @@
IMPLEMENTATION MODULE Transpiler;
FROM FIO IMPORT WriteNBytes, WriteLine, WriteChar, WriteString;
FROM SYSTEM IMPORT ADR, ADDRESS, TSIZE;
FROM SYSTEM IMPORT ADR, TSIZE;
FROM NumberIO IMPORT IntToStr;
FROM Storage IMPORT ALLOCATE, REALLOCATE;
FROM MemUtils IMPORT MemCopy, MemZero;
FROM Common IMPORT Identifier, PIdentifier, ShortString;
FROM Lexer IMPORT Lexer, LexerToken, lexer_current, lexer_lex, LexerKind;
FROM Parser IMPORT AstTypeExpressionKind, AstExpressionKind, AstLiteralKind, AstUnaryOperator, AstBinaryOperator,
AstModule, PAstModule, AstExpression, PPAstExpression, PAstExpression, PAstLiteral, PPAstProcedureDeclaration,
PAstModule, PPAstExpression, PAstExpression, PAstLiteral, PPAstProcedureDeclaration,
PAstConstantDeclaration, PPAstConstantDeclaration, PPAstStatement, PAstStatement, AstStatementKind,
AstTypedDeclaration, PAstTypedDeclaration, PPAstTypedDeclaration, AstCompoundStatement, PAstProcedureDeclaration,
PAstVariableDeclaration, PPAstVariableDeclaration, PAstImportStatement, PPAstImportStatement,
PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration;
(* Calls lexer_lex() but skips the comments. *)
PROCEDURE transpiler_lex(lexer: PLexer): LexerToken;
PROCEDURE indent(context: PTranspilerContext);
VAR
result: LexerToken;
count: CARDINAL;
BEGIN
result := lexer_lex(lexer);
count := 0;
WHILE result.kind = lexerKindComment DO
result := lexer_lex(lexer)
END;
RETURN result
END transpiler_lex;
WHILE count < context^.indentation DO
WriteString(context^.output, ' ');
INC(count)
END
END indent;
(* Write a semicolon followed by a newline. *)
PROCEDURE write_semicolon(output: File);
BEGIN
WriteChar(output, ';');
WriteLine(output)
END write_semicolon;
PROCEDURE write_current(lexer: PLexer; output: File);
VAR
written_bytes: CARDINAL;
count: CARDINAL;
BEGIN
count := lexer^.current;
DEC(count, lexer^.start);
written_bytes := WriteNBytes(output, count, lexer^.start)
END write_current;
PROCEDURE transpile_import_statement(context: PTranspilerContext; import_statement: PAstImportStatement);
VAR
token: LexerToken;
written_bytes: CARDINAL;
current_symbol: PIdentifier;
BEGIN
@ -92,7 +76,7 @@ BEGIN
write_semicolon(context^.output)
END transpile_constant_declaration;
PROCEDURE transpile_constant_part(context: PTranspilerContext; declarations: PPAstConstantDeclaration);
PROCEDURE transpile_constant_part(context: PTranspilerContext; declarations: PPAstConstantDeclaration; extra_newline: BOOLEAN);
VAR
current_declaration: PPAstConstantDeclaration;
BEGIN
@ -106,12 +90,12 @@ BEGIN
INC(current_declaration, TSIZE(PAstConstantDeclaration))
END;
WriteLine(context^.output)
IF extra_newline THEN
WriteLine(context^.output)
END
END
END transpile_constant_part;
PROCEDURE transpile_module(context: PTranspilerContext; result: PAstModule);
VAR
token: LexerToken;
BEGIN
IF result^.main = FALSE THEN
WriteString(context^.output, 'IMPLEMENTATION ')
@ -127,9 +111,9 @@ BEGIN
(* Write the module body. *)
transpile_import_part(context, result^.imports);
transpile_constant_part(context, result^.constants);
transpile_constant_part(context, result^.constants, TRUE);
transpile_type_part(context, result^.types);
transpile_variable_part(context, result^.variables);
transpile_variable_part(context, result^.variables, TRUE);
transpile_procedure_part(context, result^.procedures);
transpile_statement_part(context, result^.statements);
@ -169,8 +153,6 @@ BEGIN
WriteString(context^.output, ' END')
END transpile_record_type;
PROCEDURE transpile_pointer_type(context: PTranspilerContext; type_expression: PAstTypeExpression);
VAR
token: LexerToken;
BEGIN
WriteString(context^.output, 'POINTER TO ');
@ -306,7 +288,7 @@ BEGIN
transpile_type_expression(context, declaration^.variable_type);
write_semicolon(context^.output)
END transpile_variable_declaration;
PROCEDURE transpile_variable_part(context: PTranspilerContext; declarations: PPAstVariableDeclaration);
PROCEDURE transpile_variable_part(context: PTranspilerContext; declarations: PPAstVariableDeclaration; extra_newline: BOOLEAN);
VAR
current_declaration: PPAstVariableDeclaration;
BEGIN
@ -320,12 +302,13 @@ BEGIN
INC(current_declaration, TSIZE(PAstVariableDeclaration))
END;
WriteLine(context^.output)
IF extra_newline THEN
WriteLine(context^.output)
END
END
END transpile_variable_part;
PROCEDURE transpile_procedure_heading(context: PTranspilerContext; declaration: PAstProcedureDeclaration);
VAR
token: LexerToken;
written_bytes: CARDINAL;
parameter_index: CARDINAL;
current_parameter: PAstTypedDeclaration;
@ -487,32 +470,32 @@ BEGIN
END
END transpile_expression;
PROCEDURE transpile_if_statement(context: PTranspilerContext; statement: PAstStatement);
VAR
token: LexerToken;
BEGIN
IF statement <> NIL THEN
WriteString(context^.output, ' IF ');
transpile_expression(context, statement^.if_condition);
WriteString(context^.output, 'IF ');
transpile_expression(context, statement^.if_condition);
WriteString(context^.output, ' THEN');
WriteLine(context^.output);
WriteString(context^.output, ' THEN');
WriteLine(context^.output);
INC(context^.indentation);
transpile_compound_statement(context, statement^.if_branch);
WriteString(context^.output, ' END')
END
transpile_compound_statement(context, statement^.if_branch);
DEC(context^.indentation);
indent(context);
WriteString(context^.output, 'END')
END transpile_if_statement;
PROCEDURE transpile_while_statement(context: PTranspilerContext; statement: PAstStatement);
VAR
token: LexerToken;
BEGIN
WriteString(context^.output, ' WHILE ');
WriteString(context^.output, 'WHILE ');
transpile_expression(context, statement^.while_condition);
WriteString(context^.output, ' DO');
WriteLine(context^.output);
INC(context^.indentation);
transpile_compound_statement(context, statement^.while_body);
WriteString(context^.output, ' END')
DEC(context^.indentation);
indent(context);
WriteString(context^.output, 'END')
END transpile_while_statement;
PROCEDURE transpile_assignment_statement(context: PTranspilerContext; statement: PAstStatement);
BEGIN
@ -522,7 +505,7 @@ BEGIN
END transpile_assignment_statement;
PROCEDURE transpile_return_statement(context: PTranspilerContext; statement: PAstStatement);
BEGIN
WriteString(context^.output, ' RETURN ');
WriteString(context^.output, 'RETURN ');
transpile_expression(context, statement^.returned)
END transpile_return_statement;
@ -548,6 +531,8 @@ BEGIN
END transpile_compound_statement;
PROCEDURE transpile_statement(context: PTranspilerContext; statement: PAstStatement);
BEGIN
indent(context);
IF statement^.kind = astStatementKindIf THEN
transpile_if_statement(context, statement)
END;
@ -569,7 +554,10 @@ BEGIN
IF compound.count > 0 THEN
WriteString(context^.output, 'BEGIN');
WriteLine(context^.output);
transpile_compound_statement(context, compound)
INC(context^.indentation);
transpile_compound_statement(context, compound);
DEC(context^.indentation)
END
END transpile_statement_part;
PROCEDURE transpile_procedure_declaration(context: PTranspilerContext; declaration: PAstProcedureDeclaration);
@ -578,8 +566,8 @@ VAR
BEGIN
transpile_procedure_heading(context, declaration);
transpile_constant_part(context, declaration^.constants);
transpile_variable_part(context, declaration^.variables);
transpile_constant_part(context, declaration^.constants, FALSE);
transpile_variable_part(context, declaration^.variables, FALSE);
transpile_statement_part(context, declaration^.statements);
WriteString(context^.output, 'END ');
@ -628,6 +616,7 @@ VAR
BEGIN
context.input_name := input_name;
context.output := output;
context.indentation := 0;
transpile_module(ADR(context), ast_module)
END transpile;