Trace the source code position in the lexer

This commit is contained in:
2025-06-12 18:45:17 +02:00
parent e3f094c8a5
commit 9341017103
7 changed files with 251 additions and 231 deletions

View File

@ -4,5 +4,9 @@ TYPE
ShortString = ARRAY[1..256] OF CHAR; ShortString = ARRAY[1..256] OF CHAR;
Identifier = ARRAY[1..256] OF CHAR; Identifier = ARRAY[1..256] OF CHAR;
PIdentifier = POINTER TO Identifier; PIdentifier = POINTER TO Identifier;
TextLocation = RECORD
line: CARDINAL;
column: CARDINAL
END;
END Common. END Common.

View File

@ -2,17 +2,22 @@ DEFINITION MODULE Lexer;
FROM FIO IMPORT File; FROM FIO IMPORT File;
FROM Common IMPORT Identifier, ShortString; FROM Common IMPORT Identifier, ShortString, TextLocation;
TYPE TYPE
PLexerBuffer = POINTER TO CHAR; PLexerBuffer = POINTER TO CHAR;
BufferPosition = RECORD
iterator: PLexerBuffer;
location: TextLocation
END;
PBufferPosition = POINTER TO BufferPosition;
Lexer = RECORD Lexer = RECORD
input: File; input: File;
buffer: PLexerBuffer; buffer: PLexerBuffer;
size: CARDINAL; size: CARDINAL;
length: CARDINAL; length: CARDINAL;
start: PLexerBuffer; start: BufferPosition;
current: PLexerBuffer current: BufferPosition
END; END;
PLexer = POINTER TO Lexer; PLexer = POINTER TO Lexer;
LexerKind = ( LexerKind = (
@ -86,7 +91,9 @@ TYPE
lexerKindIdentifier: identifierKind: Identifier | lexerKindIdentifier: identifierKind: Identifier |
lexerKindInteger: integerKind: INTEGER | lexerKindInteger: integerKind: INTEGER |
lexerKindString: stringKind: ShortString lexerKindString: stringKind: ShortString
END END;
start_location: TextLocation;
end_location: TextLocation
END; END;
PLexerToken = POINTER TO LexerToken; PLexerToken = POINTER TO LexerToken;

View File

@ -213,7 +213,7 @@ begin
end end
end; end;
proc compare_keyword(keyword: ARRAY OF CHAR, token_start: PLexerBuffer, token_end: PLexerBuffer) -> BOOLEAN; proc compare_keyword(keyword: ARRAY OF CHAR, token_start: BufferPosition, token_end: PLexerBuffer) -> BOOLEAN;
var var
result: BOOLEAN; result: BOOLEAN;
index: CARDINAL; index: CARDINAL;
@ -223,17 +223,17 @@ begin
index := 0; index := 0;
result := true; result := true;
keyword_length := Length(keyword); keyword_length := Length(keyword);
continue := (index < keyword_length) & (token_start <> token_end); continue := (index < keyword_length) & (token_start.iterator <> token_end);
while continue & result do while continue & result do
result := (keyword[index] = token_start^) or (Lower(keyword[index]) = token_start^); result := (keyword[index] = token_start.iterator^) or (Lower(keyword[index]) = token_start.iterator^);
INC(token_start); INC(token_start.iterator);
INC(index); INC(index);
continue := (index < keyword_length) & (token_start <> token_end) continue := (index < keyword_length) & (token_start.iterator <> token_end)
end; end;
result := result & (index = Length(keyword)); result := result & (index = Length(keyword));
return result & (token_start = token_end) return result & (token_start.iterator = token_end)
end; end;
(* Reached the end of file. *) (* Reached the end of file. *)
@ -242,32 +242,37 @@ begin
token^.kind := lexerKindEof token^.kind := lexerKindEof
end; end;
proc increment(position: PBufferPosition);
begin
INC(position^.iterator)
end;
(* Add the character to the token currently read and advance to the next character. *) (* Add the character to the token currently read and advance to the next character. *)
proc transition_action_accumulate(lexer: PLexer, token: PLexerToken); proc transition_action_accumulate(lexer: PLexer, token: PLexerToken);
begin begin
INC(lexer^.current) increment(ADR(lexer^.current))
end; end;
(* The current character is not a part of the token. Finish the token already (* The current character is not a part of the token. Finish the token already
* read. Don't advance to the next character. *) * read. Don't advance to the next character. *)
proc transition_action_finalize(lexer: PLexer, token: PLexerToken); proc transition_action_finalize(lexer: PLexer, token: PLexerToken);
begin begin
if lexer^.start^ = ':' then if lexer^.start.iterator^ = ':' then
token^.kind := lexerKindColon token^.kind := lexerKindColon
end; end;
if lexer^.start^ = '>' then if lexer^.start.iterator^ = '>' then
token^.kind := lexerKindGreaterThan token^.kind := lexerKindGreaterThan
end; end;
if lexer^.start^ = '<' then if lexer^.start.iterator^ = '<' then
token^.kind := lexerKindLessThan token^.kind := lexerKindLessThan
end; end;
if lexer^.start^ = '(' then if lexer^.start.iterator^ = '(' then
token^.kind := lexerKindLeftParen token^.kind := lexerKindLeftParen
end; end;
if lexer^.start^ = '-' then if lexer^.start.iterator^ = '-' then
token^.kind := lexerKindMinus token^.kind := lexerKindMinus
end; end;
if lexer^.start^ = '.' then if lexer^.start.iterator^ = '.' then
token^.kind := lexerKindDot token^.kind := lexerKindDot
end end
end; end;
@ -275,34 +280,39 @@ end;
(* An action for tokens containing multiple characters. *) (* An action for tokens containing multiple characters. *)
proc transition_action_composite(lexer: PLexer, token: PLexerToken); proc transition_action_composite(lexer: PLexer, token: PLexerToken);
begin begin
if lexer^.start^ = '<' then if lexer^.start.iterator^ = '<' then
if lexer^.current^ = '>' then if lexer^.current.iterator^ = '>' then
token^.kind := lexerKindNotEqual token^.kind := lexerKindNotEqual
end; end;
if lexer^.current^ = '=' then if lexer^.current.iterator^ = '=' then
token^.kind := lexerKindLessEqual token^.kind := lexerKindLessEqual
end end
end; end;
if (lexer^.start^ = '>') & (lexer^.current^ = '=') then if (lexer^.start.iterator^ = '>') & (lexer^.current.iterator^ = '=') then
token^.kind := lexerKindGreaterEqual token^.kind := lexerKindGreaterEqual
end; end;
if (lexer^.start^ = '.') & (lexer^.current^ = '.') then if (lexer^.start.iterator^ = '.') & (lexer^.current.iterator^ = '.') then
token^.kind := lexerKindRange token^.kind := lexerKindRange
end; end;
if (lexer^.start^ = ':') & (lexer^.current^ = '=') then if (lexer^.start.iterator^ = ':') & (lexer^.current.iterator^ = '=') then
token^.kind := lexerKindAssignment token^.kind := lexerKindAssignment
end; end;
if (lexer^.start^ = '-') & (lexer^.current^ = '>') then if (lexer^.start.iterator^ = '-') & (lexer^.current.iterator^ = '>') then
token^.kind := lexerKindArrow token^.kind := lexerKindArrow
end; end;
INC(lexer^.current) increment(ADR(lexer^.current))
end; end;
(* Skip a space. *) (* Skip a space. *)
proc transition_action_skip(lexer: PLexer, token: PLexerToken); proc transition_action_skip(lexer: PLexer, token: PLexerToken);
begin begin
INC(lexer^.current); increment(ADR(lexer^.start));
INC(lexer^.start)
if ORD(lexer^.start.iterator^) = 10 then
INC(lexer^.start.location.line);
lexer^.start.location.column := 1
end;
lexer^.current := lexer^.start
end; end;
(* Delimited string action. *) (* Delimited string action. *)
@ -310,30 +320,30 @@ proc transition_action_delimited(lexer: PLexer, token: PLexerToken);
var var
text_length: CARDINAL; text_length: CARDINAL;
begin begin
if lexer^.start^ = '(' then if lexer^.start.iterator^ = '(' then
token^.kind := lexerKindComment token^.kind := lexerKindComment
end; end;
if lexer^.start^ = '"' then if lexer^.start.iterator^ = '"' then
text_length := lexer^.current; text_length := lexer^.current.iterator;
DEC(text_length, lexer^.start); DEC(text_length, lexer^.start.iterator);
INC(text_length); INC(text_length);
MemZero(ADR(token^.stringKind), TSIZE(ShortString)); MemZero(ADR(token^.stringKind), TSIZE(ShortString));
MemCopy(lexer^.start, text_length, ADR(token^.stringKind)); MemCopy(lexer^.start.iterator, text_length, ADR(token^.stringKind));
token^.kind := lexerKindCharacter token^.kind := lexerKindCharacter
end; end;
if lexer^.start^ = "'" then if lexer^.start.iterator^ = "'" then
text_length := lexer^.current; text_length := lexer^.current.iterator;
DEC(text_length, lexer^.start); DEC(text_length, lexer^.start.iterator);
INC(text_length); INC(text_length);
MemZero(ADR(token^.stringKind), TSIZE(ShortString)); MemZero(ADR(token^.stringKind), TSIZE(ShortString));
MemCopy(lexer^.start, text_length, ADR(token^.stringKind)); MemCopy(lexer^.start.iterator, text_length, ADR(token^.stringKind));
token^.kind := lexerKindString token^.kind := lexerKindString
end; end;
INC(lexer^.current) increment(ADR(lexer^.current))
end; end;
(* Finalize keyword or identifier. *) (* Finalize keyword or identifier. *)
@ -341,102 +351,102 @@ proc transition_action_key_id(lexer: PLexer, token: PLexerToken);
begin begin
token^.kind := lexerKindIdentifier; token^.kind := lexerKindIdentifier;
token^.identifierKind[1] := lexer^.current; token^.identifierKind[1] := lexer^.current.iterator;
DEC(token^.identifierKind[1], lexer^.start); DEC(token^.identifierKind[1], lexer^.start.iterator);
MemCopy(lexer^.start, ORD(token^.identifierKind[1]), ADR(token^.identifierKind[2])); MemCopy(lexer^.start.iterator, ORD(token^.identifierKind[1]), ADR(token^.identifierKind[2]));
if compare_keyword('PROGRAM', lexer^.start, lexer^.current) then if compare_keyword('PROGRAM', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindProgram token^.kind := lexerKindProgram
end; end;
if compare_keyword('IMPORT', lexer^.start, lexer^.current) then if compare_keyword('IMPORT', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindImport token^.kind := lexerKindImport
end; end;
if compare_keyword('CONST', lexer^.start, lexer^.current) then if compare_keyword('CONST', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindConst token^.kind := lexerKindConst
end; end;
if compare_keyword('VAR', lexer^.start, lexer^.current) then if compare_keyword('VAR', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindVar token^.kind := lexerKindVar
end; end;
if compare_keyword('IF', lexer^.start, lexer^.current) then if compare_keyword('IF', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindIf token^.kind := lexerKindIf
end; end;
if compare_keyword('THEN', lexer^.start, lexer^.current) then if compare_keyword('THEN', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindThen token^.kind := lexerKindThen
end; end;
if compare_keyword('ELSIF', lexer^.start, lexer^.current) then if compare_keyword('ELSIF', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindElsif token^.kind := lexerKindElsif
end; end;
if compare_keyword('ELSE', lexer^.start, lexer^.current) then if compare_keyword('ELSE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindElse token^.kind := lexerKindElse
end; end;
if compare_keyword('WHILE', lexer^.start, lexer^.current) then if compare_keyword('WHILE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindWhile token^.kind := lexerKindWhile
end; end;
if compare_keyword('DO', lexer^.start, lexer^.current) then if compare_keyword('DO', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindDo token^.kind := lexerKindDo
end; end;
if compare_keyword('proc', lexer^.start, lexer^.current) then if compare_keyword('proc', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindProc token^.kind := lexerKindProc
end; end;
if compare_keyword('BEGIN', lexer^.start, lexer^.current) then if compare_keyword('BEGIN', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindBegin token^.kind := lexerKindBegin
end; end;
if compare_keyword('END', lexer^.start, lexer^.current) then if compare_keyword('END', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindEnd token^.kind := lexerKindEnd
end; end;
if compare_keyword('TYPE', lexer^.start, lexer^.current) then if compare_keyword('TYPE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindType token^.kind := lexerKindType
end; end;
if compare_keyword('RECORD', lexer^.start, lexer^.current) then if compare_keyword('RECORD', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindRecord token^.kind := lexerKindRecord
end; end;
if compare_keyword('UNION', lexer^.start, lexer^.current) then if compare_keyword('UNION', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindUnion token^.kind := lexerKindUnion
end; end;
if compare_keyword('NIL', lexer^.start, lexer^.current) then if compare_keyword('NIL', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindNull token^.kind := lexerKindNull
end; end;
if compare_keyword('AND', lexer^.start, lexer^.current) then if compare_keyword('AND', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindAnd token^.kind := lexerKindAnd
end; end;
if compare_keyword('OR', lexer^.start, lexer^.current) then if compare_keyword('OR', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindOr token^.kind := lexerKindOr
end; end;
if compare_keyword('RETURN', lexer^.start, lexer^.current) then if compare_keyword('RETURN', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindReturn token^.kind := lexerKindReturn
end; end;
if compare_keyword('DEFINITION', lexer^.start, lexer^.current) then if compare_keyword('DEFINITION', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindDefinition token^.kind := lexerKindDefinition
end; end;
if compare_keyword('TO', lexer^.start, lexer^.current) then if compare_keyword('TO', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindTo token^.kind := lexerKindTo
end; end;
if compare_keyword('CASE', lexer^.start, lexer^.current) then if compare_keyword('CASE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindCase token^.kind := lexerKindCase
end; end;
if compare_keyword('OF', lexer^.start, lexer^.current) then if compare_keyword('OF', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindOf token^.kind := lexerKindOf
end; end;
if compare_keyword('FROM', lexer^.start, lexer^.current) then if compare_keyword('FROM', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindFrom token^.kind := lexerKindFrom
end; end;
if compare_keyword('MODULE', lexer^.start, lexer^.current) then if compare_keyword('MODULE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindModule token^.kind := lexerKindModule
end; end;
if compare_keyword('IMPLEMENTATION', lexer^.start, lexer^.current) then if compare_keyword('IMPLEMENTATION', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindImplementation token^.kind := lexerKindImplementation
end; end;
if compare_keyword('POINTER', lexer^.start, lexer^.current) then if compare_keyword('POINTER', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindPointer token^.kind := lexerKindPointer
end; end;
if compare_keyword('ARRAY', lexer^.start, lexer^.current) then if compare_keyword('ARRAY', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindArray token^.kind := lexerKindArray
end; end;
if compare_keyword('TRUE', lexer^.start, lexer^.current) then if compare_keyword('TRUE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindBoolean; token^.kind := lexerKindBoolean;
token^.booleanKind := true token^.booleanKind := true
end; end;
if compare_keyword('FALSE', lexer^.start, lexer^.current) then if compare_keyword('FALSE', lexer^.start, lexer^.current.iterator) then
token^.kind := lexerKindBoolean; token^.kind := lexerKindBoolean;
token^.booleanKind := false token^.booleanKind := false
end end
@ -446,52 +456,52 @@ end;
* followed by other characters forming a composite token. *) * followed by other characters forming a composite token. *)
proc transition_action_single(lexer: PLexer, token: PLexerToken); proc transition_action_single(lexer: PLexer, token: PLexerToken);
begin begin
if lexer^.current^ = '&' then if lexer^.current.iterator^ = '&' then
token^.kind := lexerKindAnd token^.kind := lexerKindAnd
end; end;
if lexer^.current^ = ';' then if lexer^.current.iterator^ = ';' then
token^.kind := lexerKindSemicolon token^.kind := lexerKindSemicolon
end; end;
if lexer^.current^ = ',' then if lexer^.current.iterator^ = ',' then
token^.kind := lexerKindComma token^.kind := lexerKindComma
end; end;
if lexer^.current^ = '~' then if lexer^.current.iterator^ = '~' then
token^.kind := lexerKindTilde token^.kind := lexerKindTilde
end; end;
if lexer^.current^ = ')' then if lexer^.current.iterator^ = ')' then
token^.kind := lexerKindRightParen token^.kind := lexerKindRightParen
end; end;
if lexer^.current^ = '[' then if lexer^.current.iterator^ = '[' then
token^.kind := lexerKindLeftSquare token^.kind := lexerKindLeftSquare
end; end;
if lexer^.current^ = ']' then if lexer^.current.iterator^ = ']' then
token^.kind := lexerKindRightSquare token^.kind := lexerKindRightSquare
end; end;
if lexer^.current^ = '^' then if lexer^.current.iterator^ = '^' then
token^.kind := lexerKindHat token^.kind := lexerKindHat
end; end;
if lexer^.current^ = '=' then if lexer^.current.iterator^ = '=' then
token^.kind := lexerKindEqual token^.kind := lexerKindEqual
end; end;
if lexer^.current^ = '+' then if lexer^.current.iterator^ = '+' then
token^.kind := lexerKindPlus token^.kind := lexerKindPlus
end; end;
if lexer^.current^ = '*' then if lexer^.current.iterator^ = '*' then
token^.kind := lexerKindAsterisk token^.kind := lexerKindAsterisk
end; end;
if lexer^.current^ = '/' then if lexer^.current.iterator^ = '/' then
token^.kind := lexerKindDivision token^.kind := lexerKindDivision
end; end;
if lexer^.current^ = '%' then if lexer^.current.iterator^ = '%' then
token^.kind := lexerKindRemainder token^.kind := lexerKindRemainder
end; end;
if lexer^.current^ = '@' then if lexer^.current.iterator^ = '@' then
token^.kind := lexerKindAt token^.kind := lexerKindAt
end; end;
if lexer^.current^ = '|' then if lexer^.current.iterator^ = '|' then
token^.kind := lexerKindPipe token^.kind := lexerKindPipe
end; end;
INC(lexer^.current) increment(ADR(lexer^.current.iterator))
end; end;
(* Handle an integer literal. *) (* Handle an integer literal. *)
@ -503,21 +513,21 @@ var
begin begin
token^.kind := lexerKindInteger; token^.kind := lexerKindInteger;
integer_length := lexer^.current; integer_length := lexer^.current.iterator;
DEC(integer_length, lexer^.start); DEC(integer_length, lexer^.start.iterator);
MemZero(ADR(token^.identifierKind), TSIZE(Identifier)); MemZero(ADR(token^.identifierKind), TSIZE(Identifier));
MemCopy(lexer^.start, integer_length, ADR(token^.identifierKind[1])); MemCopy(lexer^.start.iterator, integer_length, ADR(token^.identifierKind[1]));
buffer := InitStringCharStar(ADR(token^.identifierKind[1])); buffer := InitStringCharStar(ADR(token^.identifierKind[1]));
token^.integerKind := StringToInteger(buffer, 10, found); token^.integerKind := StringToInteger(buffer, 10, found);
buffer := KillString(buffer) buffer := KillString(buffer)
end; end;
proc set_default_transition(current_state: TransitionState, DefaultAction: TransitionAction, next_state: TransitionState); proc set_default_transition(current_state: TransitionState, default_action: TransitionAction, next_state: TransitionState);
var var
default_transition: Transition; default_transition: Transition;
begin begin
default_transition.action := DefaultAction; default_transition.action := default_action;
default_transition.next_state := next_state; default_transition.next_state := next_state;
transitions[ORD(current_state) + 1][ORD(transitionClassInvalid) + 1] := default_transition; transitions[ORD(current_state) + 1][ORD(transitionClassInvalid) + 1] := default_transition;
@ -821,7 +831,7 @@ begin
current_state := transitionStateStart; current_state := transitionStateStart;
while current_state <> transitionStateEnd DO while current_state <> transitionStateEnd DO
index1 := ORD(lexer^.current^); index1 := ORD(lexer^.current.iterator^);
INC(index1); INC(index1);
current_class := classification[index1]; current_class := classification[index1];
@ -836,6 +846,9 @@ begin
end; end;
current_state := current_transition.next_state current_state := current_transition.next_state
end; end;
result.start_location := lexer^.start.location;
result.end_location := lexer^.current.location;
return result return result
end; end;
@ -845,7 +858,9 @@ var
begin begin
if lexer^.length = 0 then if lexer^.length = 0 then
lexer^.length := ReadNBytes(lexer^.input, CHUNK_SIZE, lexer^.buffer); lexer^.length := ReadNBytes(lexer^.input, CHUNK_SIZE, lexer^.buffer);
lexer^.current := lexer^.buffer lexer^.current.location.column := 1;
lexer^.current.location.line := 1;
lexer^.current.iterator := lexer^.buffer
end; end;
lexer^.start := lexer^.current; lexer^.start := lexer^.current;

View File

@ -4,6 +4,11 @@ FROM Common IMPORT Identifier, PIdentifier, ShortString;
FROM Lexer IMPORT PLexer; FROM Lexer IMPORT PLexer;
TYPE TYPE
Parser = RECORD
lexer: PLexer
END;
PParser = POINTER TO Parser;
AstLiteralKind = ( AstLiteralKind = (
astLiteralKindInteger, astLiteralKindInteger,
astLiteralKindString, astLiteralKindString,

View File

@ -9,7 +9,7 @@ from Storage import ALLOCATE, REALLOCATE;
from Lexer import Lexer, LexerKind, LexerToken, lexer_current, lexer_lex; from Lexer import Lexer, LexerKind, LexerToken, lexer_current, lexer_lex;
(* Calls lexer_lex() but skips the comments. *) (* Calls lexer_lex() but skips the comments. *)
proc transpiler_lex(lexer: PLexer) -> LexerToken; proc parser_lex(lexer: PLexer) -> LexerToken;
var var
result: LexerToken; result: LexerToken;
begin begin
@ -30,7 +30,7 @@ var
current_field: PAstFieldDeclaration; current_field: PAstFieldDeclaration;
begin begin
ALLOCATE(field_declarations, TSIZE(AstFieldDeclaration)); ALLOCATE(field_declarations, TSIZE(AstFieldDeclaration));
token := transpiler_lex(lexer); token := parser_lex(lexer);
field_count := 0; field_count := 0;
while token.kind <> lexerKindEnd do while token.kind <> lexerKindEnd do
@ -41,16 +41,16 @@ begin
current_field := field_declarations; current_field := field_declarations;
INC(current_field , TSIZE(AstFieldDeclaration) * (field_count - 1)); INC(current_field , TSIZE(AstFieldDeclaration) * (field_count - 1));
token := transpiler_lex(lexer); token := parser_lex(lexer);
current_field^.field_name := token.identifierKind; current_field^.field_name := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
current_field^.field_type := parse_type_expression(lexer); current_field^.field_type := parse_type_expression(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
if token.kind = lexerKindSemicolon then if token.kind = lexerKindSemicolon then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
INC(current_field, TSIZE(AstFieldDeclaration)); INC(current_field, TSIZE(AstFieldDeclaration));
@ -81,7 +81,7 @@ begin
token := lexer_current(lexer); token := lexer_current(lexer);
if token.kind = lexerKindPointer then if token.kind = lexerKindPointer then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
token := lexer_current(lexer); token := lexer_current(lexer);
result^.target := parse_type_expression(lexer); result^.target := parse_type_expression(lexer);
@ -102,16 +102,16 @@ begin
token := lexer_current(lexer); token := lexer_current(lexer);
if token.kind = lexerKindArray then if token.kind = lexerKindArray then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
if token.kind <> lexerKindOf then if token.kind <> lexerKindOf then
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.length := token.integerKind; result^.length := token.integerKind;
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.base := parse_type_expression(lexer); result^.base := parse_type_expression(lexer);
return result return result
@ -129,14 +129,14 @@ begin
case_count := 1; case_count := 1;
ALLOCATE(result^.cases, TSIZE(Identifier) * 2); ALLOCATE(result^.cases, TSIZE(Identifier) * 2);
token := transpiler_lex(lexer); token := parser_lex(lexer);
current_case := result^.cases; current_case := result^.cases;
current_case^ := token.identifierKind; current_case^ := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind = lexerKindComma do while token.kind = lexerKindComma do
token := transpiler_lex(lexer); token := parser_lex(lexer);
INC(case_count); INC(case_count);
INC(case_count); INC(case_count);
@ -146,7 +146,7 @@ begin
INC(current_case, TSIZE(Identifier) * (case_count - 1)); INC(current_case, TSIZE(Identifier) * (case_count - 1));
current_case^ := token.identifierKind; current_case^ := token.identifierKind;
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
INC(current_case, TSIZE(Identifier)); INC(current_case, TSIZE(Identifier));
MemZero(current_case, TSIZE(Identifier)); MemZero(current_case, TSIZE(Identifier));
@ -181,8 +181,8 @@ begin
ALLOCATE(result^.parameters, 1); ALLOCATE(result^.parameters, 1);
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind <> lexerKindRightParen do while token.kind <> lexerKindRightParen do
INC(parameter_count); INC(parameter_count);
@ -194,9 +194,9 @@ begin
current_parameter^ := parse_type_expression(lexer); current_parameter^ := parse_type_expression(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
if token.kind = lexerKindComma then if token.kind = lexerKindComma then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
current_parameter := result^.parameters; current_parameter := result^.parameters;
@ -245,11 +245,11 @@ begin
NEW(result); NEW(result);
result^.identifier := token.identifierKind; result^.identifier := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.type_expression := parse_type_expression(lexer); result^.type_expression := parse_type_expression(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -268,7 +268,7 @@ begin
declaration_count := 0; declaration_count := 0;
if token.kind = lexerKindType then if token.kind = lexerKindType then
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind = lexerKindIdentifier do while token.kind = lexerKindIdentifier do
INC(declaration_count); INC(declaration_count);
@ -278,7 +278,7 @@ begin
INC(current_declaration, TSIZE(PAstTypedDeclaration) * (declaration_count - 1)); INC(current_declaration, TSIZE(PAstTypedDeclaration) * (declaration_count - 1));
current_declaration^ := parse_type_declaration(lexer); current_declaration^ := parse_type_declaration(lexer);
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
if declaration_count <> 0 then if declaration_count <> 0 then
@ -299,12 +299,12 @@ begin
token := lexer_current(lexer); token := lexer_current(lexer);
result^.variable_name := token.identifierKind; result^.variable_name := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.variable_type := parse_type_expression(lexer); result^.variable_type := parse_type_expression(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -322,7 +322,7 @@ begin
declaration_count := 0; declaration_count := 0;
if token.kind = lexerKindVar then if token.kind = lexerKindVar then
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind = lexerKindIdentifier do while token.kind = lexerKindIdentifier do
INC(declaration_count); INC(declaration_count);
@ -332,7 +332,7 @@ begin
INC(current_declaration, TSIZE(PAstVariableDeclaration) * (declaration_count - 1)); INC(current_declaration, TSIZE(PAstVariableDeclaration) * (declaration_count - 1));
current_declaration^ := parse_variable_declaration(lexer); current_declaration^ := parse_variable_declaration(lexer);
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
if declaration_count <> 0 then if declaration_count <> 0 then
@ -353,12 +353,12 @@ begin
token := lexer_current(lexer); token := lexer_current(lexer);
result^.constant_name := token.identifierKind; result^.constant_name := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.constant_value := token.integerKind; result^.constant_value := token.integerKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -377,7 +377,7 @@ begin
declaration_count := 0; declaration_count := 0;
if token.kind = lexerKindConst then if token.kind = lexerKindConst then
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind = lexerKindIdentifier do while token.kind = lexerKindIdentifier do
INC(declaration_count); INC(declaration_count);
@ -387,7 +387,7 @@ begin
INC(current_declaration, TSIZE(PAstConstantDeclaration) * (declaration_count - 1)); INC(current_declaration, TSIZE(PAstConstantDeclaration) * (declaration_count - 1));
current_declaration^ := parse_constant_declaration(lexer); current_declaration^ := parse_constant_declaration(lexer);
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
if declaration_count <> 0 then if declaration_count <> 0 then
@ -408,20 +408,20 @@ begin
NEW(result); NEW(result);
symbol_count := 1; symbol_count := 1;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.package := token.identifierKind; result^.package := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
ALLOCATE(result^.symbols, TSIZE(Identifier) * 2); ALLOCATE(result^.symbols, TSIZE(Identifier) * 2);
current_symbol := result^.symbols; current_symbol := result^.symbols;
token := transpiler_lex(lexer); token := parser_lex(lexer);
current_symbol^ := token.identifierKind; current_symbol^ := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind <> lexerKindSemicolon do while token.kind <> lexerKindSemicolon do
token := transpiler_lex(lexer); token := parser_lex(lexer);
INC(symbol_count); INC(symbol_count);
REALLOCATE(result^.symbols, TSIZE(Identifier) * (symbol_count + 1)); REALLOCATE(result^.symbols, TSIZE(Identifier) * (symbol_count + 1));
@ -429,12 +429,12 @@ begin
INC(current_symbol, TSIZE(Identifier) * (symbol_count - 1)); INC(current_symbol, TSIZE(Identifier) * (symbol_count - 1));
current_symbol^ := token.identifierKind; current_symbol^ := token.identifierKind;
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
INC(current_symbol, TSIZE(Identifier)); INC(current_symbol, TSIZE(Identifier));
MemZero(current_symbol, TSIZE(Identifier)); MemZero(current_symbol, TSIZE(Identifier));
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -501,7 +501,7 @@ begin
literal^.boolean := token.booleanKind literal^.boolean := token.booleanKind
end; end;
if literal <> nil then if literal <> nil then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
return literal return literal
@ -526,7 +526,7 @@ begin
end; end;
if (result = nil) & (next_token.kind = lexerKindMinus) then if (result = nil) & (next_token.kind = lexerKindMinus) then
NEW(result); NEW(result);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
result^.kind := astExpressionKindUnary; result^.kind := astExpressionKindUnary;
result^.unary_operator := astUnaryOperatorMinus; result^.unary_operator := astUnaryOperatorMinus;
@ -534,17 +534,17 @@ begin
end; end;
if (result = nil) & (next_token.kind = lexerKindTilde) then if (result = nil) & (next_token.kind = lexerKindTilde) then
NEW(result); NEW(result);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
result^.kind := astExpressionKindUnary; result^.kind := astExpressionKindUnary;
result^.unary_operator := astUnaryOperatorNot; result^.unary_operator := astUnaryOperatorNot;
result^.unary_operand := parse_factor(lexer) result^.unary_operand := parse_factor(lexer)
end; end;
if (result = nil) & (next_token.kind = lexerKindLeftParen) then if (result = nil) & (next_token.kind = lexerKindLeftParen) then
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
result := parse_expression(lexer); result := parse_expression(lexer);
if result <> nil then if result <> nil then
next_token := transpiler_lex(lexer) next_token := parser_lex(lexer)
end end
end; end;
if (result = nil) & (next_token.kind = lexerKindIdentifier) then if (result = nil) & (next_token.kind = lexerKindIdentifier) then
@ -553,7 +553,7 @@ begin
result^.kind := astExpressionKindIdentifier; result^.kind := astExpressionKindIdentifier;
result^.identifier := next_token.identifierKind; result^.identifier := next_token.identifierKind;
next_token := transpiler_lex(lexer) next_token := parser_lex(lexer)
end; end;
return result return result
@ -581,34 +581,34 @@ begin
designator^.kind := astExpressionKindDereference; designator^.kind := astExpressionKindDereference;
designator^.reference := inner_expression; designator^.reference := inner_expression;
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
handled := true handled := true
end; end;
if ~handled & (next_token.kind = lexerKindLeftSquare) then if ~handled & (next_token.kind = lexerKindLeftSquare) then
NEW(designator); NEW(designator);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
designator^.kind := astExpressionKindArrayAccess; designator^.kind := astExpressionKindArrayAccess;
designator^.array := inner_expression; designator^.array := inner_expression;
designator^.index := parse_expression(lexer); designator^.index := parse_expression(lexer);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
handled := true handled := true
end; end;
if ~handled & (next_token.kind = lexerKindDot) then if ~handled & (next_token.kind = lexerKindDot) then
NEW(designator); NEW(designator);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
designator^.kind := astExpressionKindFieldAccess; designator^.kind := astExpressionKindFieldAccess;
designator^.aggregate := inner_expression; designator^.aggregate := inner_expression;
designator^.field := next_token.identifierKind; designator^.field := next_token.identifierKind;
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
handled := true handled := true
end; end;
if ~handled & (next_token.kind = lexerKindLeftParen) then if ~handled & (next_token.kind = lexerKindLeftParen) then
NEW(designator); NEW(designator);
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
designator^.kind := astExpressionKindCall; designator^.kind := astExpressionKindCall;
designator^.callable := inner_expression; designator^.callable := inner_expression;
@ -623,7 +623,7 @@ begin
next_token := lexer_current(lexer); next_token := lexer_current(lexer);
while next_token.kind = lexerKindComma do while next_token.kind = lexerKindComma do
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
designator^.argument_count := designator^.argument_count + 1; designator^.argument_count := designator^.argument_count + 1;
REALLOCATE(designator^.arguments, TSIZE(PAstExpression) * designator^.argument_count); REALLOCATE(designator^.arguments, TSIZE(PAstExpression) * designator^.argument_count);
@ -635,7 +635,7 @@ begin
end end
end; end;
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
handled := true handled := true
end end
end; end;
@ -649,7 +649,7 @@ var
result: PAstExpression; result: PAstExpression;
right: PAstExpression; right: PAstExpression;
begin begin
next_token := transpiler_lex(lexer); next_token := parser_lex(lexer);
right := parse_designator(lexer); right := parse_designator(lexer);
result := nil; result := nil;
@ -725,7 +725,7 @@ begin
NEW(result); NEW(result);
result^.kind := astStatementKindReturn; result^.kind := astStatementKindReturn;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.returned := parse_expression(lexer); result^.returned := parse_expression(lexer);
return result return result
@ -740,7 +740,7 @@ begin
result^.kind := astStatementKindAssignment; result^.kind := astStatementKindAssignment;
result^.assignee := assignee; result^.assignee := assignee;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.assignment := parse_expression(lexer); result^.assignment := parse_expression(lexer);
return result return result
@ -792,7 +792,7 @@ var
designator: PAstExpression; designator: PAstExpression;
begin begin
statement := nil; statement := nil;
token := transpiler_lex(lexer); token := parser_lex(lexer);
if token.kind = lexerKindIf then if token.kind = lexerKindIf then
statement := parse_if_statement(lexer) statement := parse_if_statement(lexer)
@ -825,11 +825,11 @@ begin
NEW(result); NEW(result);
result^.kind := astStatementKindIf; result^.kind := astStatementKindIf;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.if_condition := parse_expression(lexer); result^.if_condition := parse_expression(lexer);
result^.if_branch := parse_compound_statement(lexer); result^.if_branch := parse_compound_statement(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -841,11 +841,11 @@ begin
NEW(result); NEW(result);
result^.kind := astStatementKindWhile; result^.kind := astStatementKindWhile;
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.while_condition := parse_expression(lexer); result^.while_condition := parse_expression(lexer);
result^.while_body := parse_compound_statement(lexer); result^.while_body := parse_compound_statement(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;
@ -874,15 +874,15 @@ var
begin begin
NEW(declaration); NEW(declaration);
token := transpiler_lex(lexer); token := parser_lex(lexer);
declaration^.name := token.identifierKind; declaration^.name := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
declaration^.parameters := nil; declaration^.parameters := nil;
declaration^.parameter_count := 0; declaration^.parameter_count := 0;
token := transpiler_lex(lexer); token := parser_lex(lexer);
while token.kind <> lexerKindRightParen do while token.kind <> lexerKindRightParen do
parameter_index := declaration^.parameter_count; parameter_index := declaration^.parameter_count;
INC(declaration^.parameter_count); INC(declaration^.parameter_count);
@ -893,26 +893,26 @@ begin
current_parameter^.identifier := token.identifierKind; current_parameter^.identifier := token.identifierKind;
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
current_parameter^.type_expression := parse_type_expression(lexer); current_parameter^.type_expression := parse_type_expression(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
if token.kind = lexerKindComma then if token.kind = lexerKindComma then
token := transpiler_lex(lexer) token := parser_lex(lexer)
end end
end; end;
token := transpiler_lex(lexer); token := parser_lex(lexer);
declaration^.return_type := nil; declaration^.return_type := nil;
(* Check for the return type and write it. *) (* Check for the return type and write it. *)
if token.kind = lexerKindArrow then if token.kind = lexerKindArrow then
token := transpiler_lex(lexer); token := parser_lex(lexer);
declaration^.return_type := parse_type_expression(lexer); declaration^.return_type := parse_type_expression(lexer);
token := transpiler_lex(lexer) token := parser_lex(lexer)
end; end;
token := transpiler_lex(lexer); token := parser_lex(lexer);
return declaration return declaration
end; end;
@ -928,8 +928,8 @@ begin
declaration^.variables := parse_variable_part(lexer); declaration^.variables := parse_variable_part(lexer);
declaration^.statements := parse_statement_part(lexer); declaration^.statements := parse_statement_part(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return declaration return declaration
end; end;
@ -971,16 +971,16 @@ var
result: PAstModule; result: PAstModule;
begin begin
NEW(result); NEW(result);
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.main := true; result^.main := true;
if token.kind = lexerKindModule then if token.kind = lexerKindModule then
result^.main := false result^.main := false
end; end;
token := transpiler_lex(lexer); token := parser_lex(lexer);
(* Write the module body. *) (* Write the module body. *)
token := transpiler_lex(lexer); token := parser_lex(lexer);
result^.imports := parse_import_part(lexer); result^.imports := parse_import_part(lexer);
result^.constants := parse_constant_part(lexer); result^.constants := parse_constant_part(lexer);
@ -990,8 +990,8 @@ begin
result^.procedures := parse_procedure_part(lexer); result^.procedures := parse_procedure_part(lexer);
result^.statements := parse_statement_part(lexer); result^.statements := parse_statement_part(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
token := transpiler_lex(lexer); token := parser_lex(lexer);
return result return result
end; end;

View File

@ -9,7 +9,8 @@ FROM Parser IMPORT PAstModule;
TYPE TYPE
TranspilerContext = RECORD TranspilerContext = RECORD
input_name: ShortString; input_name: ShortString;
output: File output: File;
indentation: CARDINAL
END; END;
PTranspilerContext = POINTER TO TranspilerContext; PTranspilerContext = POINTER TO TranspilerContext;

View File

@ -1,33 +1,28 @@
module; module;
from FIO import WriteNBytes, WriteLine, WriteChar, WriteString; from FIO import WriteNBytes, WriteLine, WriteChar, WriteString;
from SYSTEM import ADR, ADDRESS, TSIZE; from SYSTEM import ADR, TSIZE;
from NumberIO import IntToStr; from NumberIO import IntToStr;
from Storage import ALLOCATE, REALLOCATE;
from MemUtils import MemCopy, MemZero;
from Common import Identifier, PIdentifier, ShortString; from Common import Identifier, PIdentifier, ShortString;
from Lexer import Lexer, LexerToken, lexer_current, lexer_lex, LexerKind;
from Parser import AstTypeExpressionKind, AstExpressionKind, AstLiteralKind, AstUnaryOperator, AstBinaryOperator, 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, PAstConstantDeclaration, PPAstConstantDeclaration, PPAstStatement, PAstStatement, AstStatementKind,
AstTypedDeclaration, PAstTypedDeclaration, PPAstTypedDeclaration, AstCompoundStatement, PAstProcedureDeclaration, AstTypedDeclaration, PAstTypedDeclaration, PPAstTypedDeclaration, AstCompoundStatement, PAstProcedureDeclaration,
PAstVariableDeclaration, PPAstVariableDeclaration, PAstImportStatement, PPAstImportStatement, PAstVariableDeclaration, PPAstVariableDeclaration, PAstImportStatement, PPAstImportStatement,
PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration; PAstTypeExpression, PPAstTypeExpression, AstFieldDeclaration, PAstFieldDeclaration;
(* Calls lexer_lex() but skips the comments. *) proc indent(context: PTranspilerContext);
proc transpiler_lex(lexer: PLexer) -> LexerToken;
var var
result: LexerToken; count: CARDINAL;
begin begin
result := lexer_lex(lexer); count := 0;
while result.kind = lexerKindComment do while count < context^.indentation do
result := lexer_lex(lexer) WriteString(context^.output, ' ');
end; INC(count)
end
return result
end; end;
(* Write a semicolon followed by a newline. *) (* Write a semicolon followed by a newline. *)
@ -37,20 +32,8 @@ begin
WriteLine(output) WriteLine(output)
end; end;
proc 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;
proc transpile_import_statement(context: PTranspilerContext, import_statement: PAstImportStatement); proc transpile_import_statement(context: PTranspilerContext, import_statement: PAstImportStatement);
var var
token: LexerToken;
written_bytes: CARDINAL; written_bytes: CARDINAL;
current_symbol: PIdentifier; current_symbol: PIdentifier;
begin begin
@ -98,7 +81,7 @@ begin
write_semicolon(context^.output) write_semicolon(context^.output)
end; end;
proc transpile_constant_part(context: PTranspilerContext, declarations: PPAstConstantDeclaration); proc transpile_constant_part(context: PTranspilerContext, declarations: PPAstConstantDeclaration, extra_newline: BOOLEAN);
var var
current_declaration: PPAstConstantDeclaration; current_declaration: PPAstConstantDeclaration;
begin begin
@ -112,13 +95,13 @@ begin
INC(current_declaration, TSIZE(PAstConstantDeclaration)) INC(current_declaration, TSIZE(PAstConstantDeclaration))
end; end;
if extra_newline then
WriteLine(context^.output) WriteLine(context^.output)
end end
end
end; end;
proc transpile_module(context: PTranspilerContext, result: PAstModule); proc transpile_module(context: PTranspilerContext, result: PAstModule);
var
token: LexerToken;
begin begin
if result^.main = false then if result^.main = false then
WriteString(context^.output, 'IMPLEMENTATION ') WriteString(context^.output, 'IMPLEMENTATION ')
@ -134,9 +117,9 @@ begin
(* Write the module body. *) (* Write the module body. *)
transpile_import_part(context, result^.imports); 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_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_procedure_part(context, result^.procedures);
transpile_statement_part(context, result^.statements); transpile_statement_part(context, result^.statements);
@ -179,8 +162,6 @@ begin
end; end;
proc transpile_pointer_type(context: PTranspilerContext, type_expression: PAstTypeExpression); proc transpile_pointer_type(context: PTranspilerContext, type_expression: PAstTypeExpression);
var
token: LexerToken;
begin begin
WriteString(context^.output, 'POINTER TO '); WriteString(context^.output, 'POINTER TO ');
@ -325,7 +306,7 @@ begin
write_semicolon(context^.output) write_semicolon(context^.output)
end; end;
proc transpile_variable_part(context: PTranspilerContext, declarations: PPAstVariableDeclaration); proc transpile_variable_part(context: PTranspilerContext, declarations: PPAstVariableDeclaration, extra_newline: BOOLEAN);
var var
current_declaration: PPAstVariableDeclaration; current_declaration: PPAstVariableDeclaration;
begin begin
@ -339,13 +320,14 @@ begin
INC(current_declaration, TSIZE(PAstVariableDeclaration)) INC(current_declaration, TSIZE(PAstVariableDeclaration))
end; end;
if extra_newline then
WriteLine(context^.output) WriteLine(context^.output)
end end
end
end; end;
proc transpile_procedure_heading(context: PTranspilerContext, declaration: PAstProcedureDeclaration); proc transpile_procedure_heading(context: PTranspilerContext, declaration: PAstProcedureDeclaration);
var var
token: LexerToken;
written_bytes: CARDINAL; written_bytes: CARDINAL;
parameter_index: CARDINAL; parameter_index: CARDINAL;
current_parameter: PAstTypedDeclaration; current_parameter: PAstTypedDeclaration;
@ -511,33 +493,33 @@ begin
end; end;
proc transpile_if_statement(context: PTranspilerContext, statement: PAstStatement); proc transpile_if_statement(context: PTranspilerContext, statement: PAstStatement);
var
token: LexerToken;
begin begin
if statement <> nil then WriteString(context^.output, 'IF ');
WriteString(context^.output, ' IF ');
transpile_expression(context, statement^.if_condition); transpile_expression(context, statement^.if_condition);
WriteString(context^.output, ' THEN'); WriteString(context^.output, ' THEN');
WriteLine(context^.output); WriteLine(context^.output);
INC(context^.indentation);
transpile_compound_statement(context, statement^.if_branch); transpile_compound_statement(context, statement^.if_branch);
WriteString(context^.output, ' END') DEC(context^.indentation);
end indent(context);
WriteString(context^.output, 'END')
end; end;
proc transpile_while_statement(context: PTranspilerContext, statement: PAstStatement); proc transpile_while_statement(context: PTranspilerContext, statement: PAstStatement);
var
token: LexerToken;
begin begin
WriteString(context^.output, ' WHILE '); WriteString(context^.output, 'WHILE ');
transpile_expression(context, statement^.while_condition); transpile_expression(context, statement^.while_condition);
WriteString(context^.output, ' DO'); WriteString(context^.output, ' DO');
WriteLine(context^.output); WriteLine(context^.output);
INC(context^.indentation);
transpile_compound_statement(context, statement^.while_body); transpile_compound_statement(context, statement^.while_body);
WriteString(context^.output, ' END') DEC(context^.indentation);
indent(context);
WriteString(context^.output, 'END')
end; end;
proc transpile_assignment_statement(context: PTranspilerContext, statement: PAstStatement); proc transpile_assignment_statement(context: PTranspilerContext, statement: PAstStatement);
@ -549,7 +531,7 @@ end;
proc transpile_return_statement(context: PTranspilerContext, statement: PAstStatement); proc transpile_return_statement(context: PTranspilerContext, statement: PAstStatement);
begin begin
WriteString(context^.output, ' RETURN '); WriteString(context^.output, 'RETURN ');
transpile_expression(context, statement^.returned) transpile_expression(context, statement^.returned)
end; end;
@ -577,6 +559,8 @@ end;
proc transpile_statement(context: PTranspilerContext, statement: PAstStatement); proc transpile_statement(context: PTranspilerContext, statement: PAstStatement);
begin begin
indent(context);
if statement^.kind = astStatementKindIf then if statement^.kind = astStatementKindIf then
transpile_if_statement(context, statement) transpile_if_statement(context, statement)
end; end;
@ -599,7 +583,10 @@ begin
if compound.count > 0 then if compound.count > 0 then
WriteString(context^.output, 'BEGIN'); WriteString(context^.output, 'BEGIN');
WriteLine(context^.output); WriteLine(context^.output);
transpile_compound_statement(context, compound)
INC(context^.indentation);
transpile_compound_statement(context, compound);
DEC(context^.indentation)
end end
end; end;
@ -609,8 +596,8 @@ var
begin begin
transpile_procedure_heading(context, declaration); transpile_procedure_heading(context, declaration);
transpile_constant_part(context, declaration^.constants); transpile_constant_part(context, declaration^.constants, false);
transpile_variable_part(context, declaration^.variables); transpile_variable_part(context, declaration^.variables, false);
transpile_statement_part(context, declaration^.statements); transpile_statement_part(context, declaration^.statements);
WriteString(context^.output, 'END '); WriteString(context^.output, 'END ');
@ -662,6 +649,7 @@ var
begin begin
context.input_name := input_name; context.input_name := input_name;
context.output := output; context.output := output;
context.indentation := 0;
transpile_module(ADR(context), ast_module) transpile_module(ADR(context), ast_module)
end; end;