Parse call expressions

This commit is contained in:
2025-06-07 23:50:53 +02:00
parent 8d52410be9
commit d707bdeaf9
5 changed files with 574 additions and 357 deletions

View File

@ -9,14 +9,14 @@ 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,
AstModule, PAstModule, AstExpression, PAstExpression, PAstLiteral,
from Parser import AstTypeExpressionKind, AstExpressionKind, AstLiteralKind, AstUnaryOperator, AstBinaryOperator,
AstModule, PAstModule, AstExpression, PPAstExpression, PAstExpression, PAstLiteral,
PAstConstantDeclaration, PPAstConstantDeclaration,
AstTypeDeclaration, PAstTypeDeclaration, PPAstTypeDeclaration,
PAstVariableDeclaration, PPAstVariableDeclaration, PAstImportStatement, PPAstImportStatement,
PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration,
parse_type_expression, parse_variable_part, parse_type_part, parse_constant_part, parse_import_part,
parse_designator;
parse_designator, parse_expression;
(* Calls lexer_lex() but skips the comments. *)
proc transpiler_lex(lexer: PLexer) -> LexerToken;
@ -42,8 +42,12 @@ end;
proc write_current(lexer: PLexer, output: File);
var
written_bytes: CARDINAL;
count: CARDINAL;
begin
written_bytes := WriteNBytes(output, ADDRESS(lexer^.Current - lexer^.Start), lexer^.Start)
count := lexer^.current;
DEC(count, lexer^.start);
written_bytes := WriteNBytes(output, count, lexer^.start)
end;
proc transpile_import_statement(context: PTranspilerContext, import_statement: PAstImportStatement);
@ -406,61 +410,6 @@ begin
return result
end;
proc transpile_unchanged(context: PTranspilerContext, trailing_token: LexerKind);
var
token: LexerToken;
written_bytes: CARDINAL;
begin
token := lexer_current(context^.lexer);
while (token.kind <> trailing_token) & (token.kind <> lexerKindEnd) do
written_bytes := 0;
if token.kind = lexerKindNull then
WriteString(context^.output, 'NIL ');
written_bytes := 1
end;
if (token.kind = lexerKindBoolean) & token.booleanKind then
WriteString(context^.output, 'TRUE ');
written_bytes := 1
end;
if (token.kind = lexerKindBoolean) & (~token.booleanKind) then
WriteString(context^.output, 'FALSE ');
written_bytes := 1
end;
if token.kind = lexerKindOr then
WriteString(context^.output, 'OR ');
written_bytes := 1
end;
if token.kind = lexerKindAnd then
WriteString(context^.output, 'AND ');
written_bytes := 1
end;
if token.kind = lexerKindTilde then
WriteString(context^.output, 'NOT ');
written_bytes := 1
end;
if written_bytes = 0 then
write_current(context^.lexer, context^.output);
WriteChar(context^.output, ' ')
end;
token := transpiler_lex(context^.lexer)
end
end;
proc parse_expression(lexer: PLexer) -> PAstExpression;
var
next_token: LexerToken;
result: PAstExpression;
written_bytes: CARDINAL;
begin
result := parse_designator(lexer);
written_bytes := WriteNBytes(StdErr, ADDRESS(lexer^.Current - lexer^.Start), lexer^.Start);
WriteLine(StdErr);
return result
end;
proc transpile_unary_operator(context: PTranspilerContext, operator: AstUnaryOperator);
begin
if operator = astUnaryOperatorMinus then
@ -471,11 +420,50 @@ begin
end
end;
proc transpile_binary_operator(context: PTranspilerContext, operator: AstBinaryOperator);
begin
if operator = astBinaryOperatorSum then
WriteChar(context^.output, '+')
end;
if operator = astBinaryOperatorSubtraction then
WriteChar(context^.output, '-')
end;
if operator = astBinaryOperatorMultiplication then
WriteChar(context^.output, '*')
end;
if operator = astBinaryOperatorEquals then
WriteChar(context^.output, '=')
end;
if operator = astBinaryOperatorNotEquals then
WriteChar(context^.output, '#')
end;
if operator = astBinaryOperatorLess then
WriteChar(context^.output, '<')
end;
if operator = astBinaryOperatorGreater then
WriteChar(context^.output, '>')
end;
if operator = astBinaryOperatorLessEqual then
WriteString(context^.output, '<=')
end;
if operator = astBinaryOperatorGreaterEqual then
WriteString(context^.output, '>=')
end;
if operator = astBinaryOperatorDisjunction then
WriteString(context^.output, 'OR')
end;
if operator = astBinaryOperatorConjunction then
WriteString(context^.output, 'AND')
end
end;
proc transpile_expression(context: PTranspilerContext, expression: PAstExpression);
var
literal: PAstLiteral;
buffer: [20]CHAR;
written_bytes: CARDINAL;
argument_index: CARDINAL;
current_argument: PPAstExpression;
begin
if expression^.kind = astExpressionKindLiteral then
literal := expression^.literal;
@ -486,7 +474,16 @@ begin
end;
if literal^.kind = astLiteralKindString then
WriteString(context^.output, literal^.string)
end
end;
if literal^.kind = astLiteralKindNull then
WriteString(context^.output, 'NIL')
end;
if (literal^.kind = astLiteralKindBoolean) & literal^.boolean then
WriteString(context^.output, 'TRUE')
end;
if (literal^.kind = astLiteralKindBoolean) & (literal^.boolean = false) then
WriteString(context^.output, 'FALSE')
end
end;
if expression^.kind = astExpressionKindIdentifier then
written_bytes := WriteNBytes(context^.output, ORD(expression^.identifier[1]), ADR(expression^.identifier[2]))
@ -509,32 +506,54 @@ begin
if expression^.kind = astExpressionKindUnary then
transpile_unary_operator(context, expression^.unary_operator);
transpile_expression(context, expression^.unary_operand)
end;
if expression^.kind = astExpressionKindBinary then
WriteChar(context^.output, '(');
transpile_expression(context, expression^.lhs);
WriteChar(context^.output, ' ');
transpile_binary_operator(context, expression^.binary_operator);
WriteChar(context^.output, ' ');
transpile_expression(context, expression^.rhs);
WriteChar(context^.output, ')')
end;
if expression^.kind = astExpressionKindCall then
transpile_expression(context, expression^.callable);
WriteChar(context^.output, '(');
current_argument := expression^.arguments;
if expression^.argument_count > 0 then
transpile_expression(context, current_argument^);
argument_index := 1;
INC(current_argument, TSIZE(PAstExpression));
while argument_index < expression^.argument_count do
WriteString(context^.output, ', ');
transpile_expression(context, current_argument^);
INC(current_argument, TSIZE(PAstExpression));
INC(argument_index)
end
end;
WriteChar(context^.output, ')')
end
end;
proc transpile_if_statement(context: PTranspilerContext);
var
token: LexerToken;
expression: PAstExpression;
lexer: Lexer;
condition: PAstExpression;
begin
WriteString(context^.output, ' IF ');
lexer := context^.lexer^;
token := transpiler_lex(ADR(lexer));
expression := parse_expression(ADR(lexer));
token := transpiler_lex(context^.lexer);
condition := parse_expression(context^.lexer);
if expression <> nil then
context^.lexer^ := lexer;
transpile_expression(context, expression);
WriteChar(context^.output, ' ')
end;
if expression = nil then
token := transpiler_lex(context^.lexer)
end;
transpile_unchanged(context, lexerKindThen);
transpile_expression(context, condition);
token := lexer_current(context^.lexer);
WriteString(context^.output, 'THEN');
WriteString(context^.output, ' THEN');
WriteLine(context^.output);
transpile_statements(context);
WriteString(context^.output, ' END');
@ -544,12 +563,17 @@ end;
proc transpile_while_statement(context: PTranspilerContext);
var
token: LexerToken;
condition: PAstExpression;
begin
WriteString(context^.output, ' WHILE ');
token := transpiler_lex(context^.lexer);
transpile_unchanged(context, lexerKindDo);
WriteString(context^.output, 'DO');
token := transpiler_lex(context^.lexer);
condition := parse_expression(context^.lexer);
transpile_expression(context, condition);
token := lexer_current(context^.lexer);
WriteString(context^.output, ' DO');
WriteLine(context^.output);
transpile_statements(context);
WriteString(context^.output, ' END');
@ -559,10 +583,14 @@ end;
proc transpile_assignment_statement(context: PTranspilerContext);
var
token: LexerToken;
assignment: PAstExpression;
begin
WriteString(context^.output, ' := ');
token := transpiler_lex(context^.lexer);
transpile_unchanged(context, lexerKindSemicolon);
assignment := parse_expression(context^.lexer);
transpile_expression(context, assignment)
end;
proc transpile_call_statement(context: PTranspilerContext);
@ -625,15 +653,18 @@ end;
proc transpile_return_statement(context: PTranspilerContext);
var
token: LexerToken;
return_expression: PAstExpression;
begin
WriteString(context^.output, ' RETURN ');
token := transpiler_lex(context^.lexer);
transpile_unchanged(context, lexerKindSemicolon)
return_expression := parse_expression(context^.lexer);
transpile_expression(context, return_expression)
end;
proc transpile_statement(context: PTranspilerContext);
var
token: LexerToken;
written_bytes: CARDINAL;
begin
token := transpiler_lex(context^.lexer);
@ -651,7 +682,13 @@ begin
token := lexer_current(context^.lexer);
if token.kind = lexerKindAssignment then
transpile_assignment_statement(context)
transpile_assignment_statement(context);
token := lexer_current(context^.lexer);
if (token.kind <> lexerKindSemicolon) & (token.kind <> lexerKindEnd) then
written_bytes := WriteNBytes(StdErr, 10, context^.lexer^.start);
WriteLine(StdErr)
end
end;
if token.kind = lexerKindLeftParen then
transpile_call_statement(context)