Parse call expressions

This commit is contained in:
2025-06-07 23:50:33 +02:00
parent c9c9b217a2
commit 6cfeb46dbf
5 changed files with 674 additions and 435 deletions

View File

@ -1,11 +1,12 @@
IMPLEMENTATION MODULE Parser;
FROM FIO IMPORT ReadNBytes;
FROM SYSTEM IMPORT TSIZE;
FROM MemUtils IMPORT MemZero;
FROM Storage IMPORT ALLOCATE, REALLOCATE;
FROM Lexer IMPORT LexerKind, LexerToken, lexer_current, lexer_lex;
FROM Lexer IMPORT Lexer, LexerKind, LexerToken, lexer_current, lexer_lex;
(* Calls lexer_lex() but skips the comments. *)
PROCEDURE transpiler_lex(lexer: PLexer): LexerToken;
@ -33,7 +34,9 @@ BEGIN
WHILE token.kind <> lexerKindEnd DO
INC(field_count);
REALLOCATE(field_declarations, TSIZE(AstFieldDeclaration) * (field_count + 1));
INC(field_count);
REALLOCATE(field_declarations, TSIZE(AstFieldDeclaration) * field_count);
DEC(field_count);
current_field := field_declarations;
INC(current_field , TSIZE(AstFieldDeclaration) * (field_count - 1));
@ -131,7 +134,9 @@ BEGIN
token := transpiler_lex(lexer);
INC(case_count);
REALLOCATE(result^.cases, TSIZE(Identifier) * (case_count + 1));
INC(case_count);
REALLOCATE(result^.cases, TSIZE(Identifier) * case_count);
DEC(case_count);
current_case := result^.cases;
INC(current_case, TSIZE(Identifier) * (case_count - 1));
current_case^ := token.identifierKind;
@ -174,7 +179,9 @@ BEGIN
WHILE token.kind <> lexerKindRightParen DO
INC(parameter_count);
REALLOCATE(result^.parameters, TSIZE(PAstTypeExpression) * (parameter_count + 1));
INC(parameter_count);
REALLOCATE(result^.parameters, TSIZE(PAstTypeExpression) * parameter_count);
DEC(parameter_count);
current_parameter := result^.parameters;
INC(current_parameter, TSIZE(PAstTypeExpression) * (parameter_count - 1));
@ -459,7 +466,7 @@ BEGIN
literal^.kind := astLiteralKindInteger;
literal^.integer := token.integerKind;
END;
IF token.kind = lexerKindCharacter THEN
IF (token.kind = lexerKindCharacter) OR (token.kind = lexerKindString) THEN
NEW(literal);
literal^.kind := astLiteralKindString;
@ -470,6 +477,12 @@ BEGIN
literal^.kind := astLiteralKindNull;
END;
IF token.kind = lexerKindBoolean THEN
NEW(literal);
literal^.kind := astLiteralKindBoolean;
literal^.boolean := token.booleanKind
END;
IF literal <> NIL THEN
token := transpiler_lex(lexer)
END;
@ -509,6 +522,13 @@ BEGIN
result^.unary_operator := astUnaryOperatorNot;
result^.unary_operand := parse_factor(lexer)
END;
IF (result = NIL) AND (next_token.kind = lexerKindLeftParen) THEN
next_token := transpiler_lex(lexer);
result := parse_expression(lexer);
IF result <> NIL THEN
next_token := transpiler_lex(lexer)
END
END;
IF (result = NIL) AND (next_token.kind = lexerKindIdentifier) THEN
NEW(result);
@ -525,6 +545,7 @@ VAR
next_token: LexerToken;
inner_expression: PAstExpression;
designator: PAstExpression;
arguments: PPAstExpression;
handled: BOOLEAN;
BEGIN
designator := parse_factor(lexer);
@ -550,7 +571,7 @@ BEGIN
designator^.kind := astExpressionKindArrayAccess;
designator^.array := inner_expression;
designator^.index := parse_designator(lexer);
designator^.index := parse_expression(lexer);
next_token := transpiler_lex(lexer);
handled := TRUE
@ -563,6 +584,38 @@ BEGIN
designator^.aggregate := inner_expression;
designator^.field := next_token.identifierKind;
next_token := transpiler_lex(lexer);
handled := TRUE
END;
IF ~handled AND (next_token.kind = lexerKindLeftParen) THEN
NEW(designator);
next_token := transpiler_lex(lexer);
designator^.kind := astExpressionKindCall;
designator^.callable := inner_expression;
designator^.argument_count := 0;
designator^.arguments := NIL;
IF next_token.kind <> lexerKindRightParen THEN
ALLOCATE(designator^.arguments, TSIZE(PAstExpression));
designator^.argument_count := 1;
designator^.arguments^ := parse_expression(lexer);
next_token := lexer_current(lexer);
WHILE next_token.kind = lexerKindComma DO
next_token := transpiler_lex(lexer);
designator^.argument_count := designator^.argument_count + 1;
REALLOCATE(designator^.arguments, TSIZE(PAstExpression) * designator^.argument_count);
arguments := designator^.arguments;
INC(arguments, TSIZE(PAstExpression) * (designator^.argument_count - 1));
arguments^ := parse_expression(lexer);
next_token := lexer_current(lexer)
END
END;
next_token := transpiler_lex(lexer);
handled := TRUE
END
@ -570,4 +623,113 @@ BEGIN
RETURN designator
END parse_designator;
PROCEDURE parse_binary_expression(lexer: PLexer; left: PAstExpression; operator: AstBinaryOperator): PAstExpression;
VAR
next_token: LexerToken;
result: PAstExpression;
right: PAstExpression;
BEGIN
next_token := transpiler_lex(lexer);
right := parse_designator(lexer);
result := NIL;
IF right <> NIL THEN
NEW(result);
result^.kind := astExpressionKindBinary;
result^.binary_operator := operator;
result^.lhs := left;
result^.rhs := right;
END;
RETURN result
END parse_binary_expression;
PROCEDURE parse_expression(lexer: PLexer): PAstExpression;
VAR
next_token: LexerToken;
left: PAstExpression;
result: PAstExpression;
written_bytes: CARDINAL;
BEGIN
left := parse_designator(lexer);
result := NIL;
next_token := lexer_current(lexer);
IF left <> NIL THEN
IF (result = NIL) AND (next_token.kind = lexerKindNotEqual) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorNotEquals)
END;
IF (result = NIL) AND (next_token.kind = lexerKindEqual) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorEquals)
END;
IF (result = NIL) AND (next_token.kind = lexerKindGreaterThan) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorGreater)
END;
IF (result = NIL) AND (next_token.kind = lexerKindLessThan) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorLess)
END;
IF (result = NIL) AND (next_token.kind = lexerKindGreaterEqual) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorGreaterEqual)
END;
IF (result = NIL) AND (next_token.kind = lexerKindLessEqual) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorLessEqual)
END;
IF (result = NIL) AND (next_token.kind = lexerKindAnd) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorConjunction)
END;
IF (result = NIL) AND (next_token.kind = lexerKindOr) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorDisjunction)
END;
IF (result = NIL) AND (next_token.kind = lexerKindMinus) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorSubtraction)
END;
IF (result = NIL) AND (next_token.kind = lexerKindPlus) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorSum)
END;
IF (result = NIL) AND (next_token.kind = lexerKindAsterisk) THEN
result := parse_binary_expression(lexer, left, astBinaryOperatorMultiplication)
END
END;
IF (result = NIL) AND (left <> NIL) THEN
result := left
END;
RETURN result
END parse_expression;
PROCEDURE parse_return_statement(lexer: PLexer): PAstStatement;
VAR
token: LexerToken;
result: PAstStatement;
BEGIN
NEW(result);
result^.kind := astStatementKindReturn;
token := transpiler_lex(lexer);
result^.returned := parse_expression(lexer);
RETURN result
END parse_return_statement;
PROCEDURE parse_assignment_statement(lexer: PLexer; assignee: PAstExpression): PAstStatement;
VAR
token: LexerToken;
result: PAstStatement;
BEGIN
NEW(result);
result^.kind := astStatementKindAssignment;
result^.assignee := assignee;
token := transpiler_lex(lexer);
result^.assignment := parse_expression(lexer);
RETURN result
END parse_assignment_statement;
PROCEDURE parse_call_statement(lexer: PLexer; call: PAstExpression): PAstStatement;
VAR
result: PAstStatement;
BEGIN
NEW(result);
result^.kind := astStatementKindCall;
result^.call := call;
RETURN result
END parse_call_statement;
END Parser.