Parse call expressions

This commit is contained in:
2025-06-07 23:50:33 +02:00
parent c9c9b217a2
commit 2c27047ffb
5 changed files with 571 additions and 355 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. *)
PROCEDURE transpiler_lex(lexer: PLexer): LexerToken;
@ -40,8 +40,12 @@ END write_semicolon;
PROCEDURE 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 write_current;
PROCEDURE transpile_import_statement(context: PTranspilerContext; import_statement: PAstImportStatement);
VAR
@ -385,59 +389,6 @@ BEGIN
RETURN result
END transpile_procedure_heading;
PROCEDURE transpile_unchanged(context: PTranspilerContext; trailing_token: LexerKind);
VAR
token: LexerToken;
written_bytes: CARDINAL;
BEGIN
token := lexer_current(context^.lexer);
WHILE (token.kind <> trailing_token) AND (token.kind <> lexerKindEnd) DO
written_bytes := 0;
IF token.kind = lexerKindNull THEN
WriteString(context^.output, 'NIL ');
written_bytes := 1
END;
IF (token.kind = lexerKindBoolean) AND token.booleanKind THEN
WriteString(context^.output, 'TRUE ');
written_bytes := 1
END;
IF (token.kind = lexerKindBoolean) AND (~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 transpile_unchanged;
PROCEDURE 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 parse_expression;
PROCEDURE transpile_unary_operator(context: PTranspilerContext; operator: AstUnaryOperator);
BEGIN
IF operator = astUnaryOperatorMinus THEN
@ -447,11 +398,49 @@ BEGIN
WriteChar(context^.output, '~')
END
END transpile_unary_operator;
PROCEDURE 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 transpile_binary_operator;
PROCEDURE transpile_expression(context: PTranspilerContext; expression: PAstExpression);
VAR
literal: PAstLiteral;
buffer: ARRAY[1..20] OF CHAR;
written_bytes: CARDINAL;
argument_index: CARDINAL;
current_argument: PPAstExpression;
BEGIN
IF expression^.kind = astExpressionKindLiteral THEN
literal := expression^.literal;
@ -462,7 +451,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) AND literal^.boolean THEN
WriteString(context^.output, 'TRUE')
END;
IF (literal^.kind = astLiteralKindBoolean) AND (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]))
@ -485,31 +483,53 @@ 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 transpile_expression;
PROCEDURE 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');
@ -518,12 +538,17 @@ END transpile_if_statement;
PROCEDURE 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');
@ -532,10 +557,14 @@ END transpile_while_statement;
PROCEDURE 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 transpile_assignment_statement;
PROCEDURE transpile_call_statement(context: PTranspilerContext);
VAR
@ -595,14 +624,17 @@ END transpile_designator_expression;
PROCEDURE 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 transpile_return_statement;
PROCEDURE transpile_statement(context: PTranspilerContext);
VAR
token: LexerToken;
written_bytes: CARDINAL;
BEGIN
token := transpiler_lex(context^.lexer);
@ -620,7 +652,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) AND (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)