Change source file extension
This commit is contained in:
160
source/Transpiler.elna
Normal file
160
source/Transpiler.elna
Normal file
@ -0,0 +1,160 @@
|
||||
IMPLEMENTATION MODULE Transpiler;
|
||||
|
||||
FROM FIO IMPORT WriteNBytes, StdOut;
|
||||
FROM SYSTEM IMPORT ADR, ADDRESS;
|
||||
|
||||
FROM Terminal IMPORT Write, WriteLn, WriteString;
|
||||
FROM Lexer IMPORT Lexer, LexerToken, LexerCurrent, LexerLex, LexerKind;
|
||||
|
||||
TYPE
|
||||
TranspilerContext = RECORD
|
||||
END;
|
||||
PTranspilerContext = POINTER TO TranspilerContext;
|
||||
|
||||
(* Calls LexerLex() but skips the comments. *)
|
||||
PROCEDURE TranspilerLex(ALexer: PLexer): LexerToken;
|
||||
VAR
|
||||
Result: LexerToken;
|
||||
BEGIN
|
||||
Result := LexerLex(ALexer);
|
||||
|
||||
WHILE Result.Kind = lexerKindComment DO
|
||||
Result := LexerLex(ALexer)
|
||||
END;
|
||||
|
||||
RETURN Result
|
||||
END TranspilerLex;
|
||||
|
||||
(* Write a semicolon followed by a newline. *)
|
||||
PROCEDURE WriteSemicolon();
|
||||
BEGIN
|
||||
WriteString(';');
|
||||
WriteLn()
|
||||
END WriteSemicolon;
|
||||
|
||||
PROCEDURE TranspileImport(AContext: PTranspilerContext; ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
WrittenBytes: CARDINAL;
|
||||
BEGIN
|
||||
WriteString('FROM ');
|
||||
Token := TranspilerLex(ALexer);
|
||||
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WriteString(' IMPORT ');
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WHILE Token.Kind <> lexerKindSemicolon DO
|
||||
WriteString(', ');
|
||||
Token := TranspilerLex(ALexer);
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
Token := TranspilerLex(ALexer)
|
||||
END;
|
||||
WriteSemicolon();
|
||||
Token := TranspilerLex(ALexer)
|
||||
END TranspileImport;
|
||||
|
||||
PROCEDURE TranspileImportPart(AContext: PTranspilerContext; ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
BEGIN
|
||||
Token := LexerCurrent(ALexer);
|
||||
|
||||
WHILE Token.Kind = lexerKindFrom DO
|
||||
TranspileImport(AContext, ALexer);
|
||||
Token := LexerCurrent(ALexer)
|
||||
END;
|
||||
WriteLn()
|
||||
END TranspileImportPart;
|
||||
|
||||
PROCEDURE TranspileConstant(AContext: PTranspilerContext; ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
WrittenBytes: CARDINAL;
|
||||
BEGIN
|
||||
WriteString(' ');
|
||||
Token := LexerCurrent(ALexer);
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WriteString(' = ');
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WriteSemicolon()
|
||||
END TranspileConstant;
|
||||
|
||||
PROCEDURE TranspileConstantPart(AContext: PTranspilerContext; ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
BEGIN
|
||||
Token := LexerCurrent(ALexer);
|
||||
|
||||
IF Token.Kind = lexerKindConst THEN
|
||||
WriteString('CONST');
|
||||
WriteLn();
|
||||
Token := TranspilerLex(ALexer);
|
||||
|
||||
WHILE Token.Kind = lexerKindIdentifier DO
|
||||
TranspileConstant(AContext, ALexer);
|
||||
Token := TranspilerLex(ALexer)
|
||||
END;
|
||||
WriteLn()
|
||||
END
|
||||
END TranspileConstantPart;
|
||||
|
||||
PROCEDURE TranspileModule(AContext: PTranspilerContext; ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
WrittenBytes: CARDINAL;
|
||||
BEGIN
|
||||
Token := TranspilerLex(ALexer);
|
||||
|
||||
IF Token.Kind = lexerKindDefinition THEN
|
||||
WriteString('DEFINITION ');
|
||||
Token := TranspilerLex(ALexer);
|
||||
ELSIF Token.Kind = lexerKindImplementation THEN
|
||||
WriteString('IMPLEMENTATION ');
|
||||
Token := TranspilerLex(ALexer)
|
||||
END;
|
||||
WriteString('MODULE ');
|
||||
|
||||
(* Write the module name and end the line with a semicolon and newline. *)
|
||||
Token := TranspilerLex(ALexer);
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
|
||||
Token := TranspilerLex(ALexer);
|
||||
WriteSemicolon();
|
||||
WriteLn();
|
||||
|
||||
(* Write the module body. *)
|
||||
Token := TranspilerLex(ALexer);
|
||||
TranspileImportPart(AContext, ALexer);
|
||||
TranspileConstantPart(AContext, ALexer);
|
||||
|
||||
Token := LexerCurrent(ALexer);
|
||||
WHILE Token.Kind <> lexerKindEof DO
|
||||
WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start);
|
||||
WriteLn();
|
||||
|
||||
Token := TranspilerLex(ALexer)
|
||||
END
|
||||
END TranspileModule;
|
||||
|
||||
PROCEDURE Transpile(ALexer: PLexer);
|
||||
VAR
|
||||
Token: LexerToken;
|
||||
WrittenBytes: CARDINAL;
|
||||
Context: TranspilerContext;
|
||||
BEGIN
|
||||
TranspileModule(ADR(Context), ALexer)
|
||||
END Transpile;
|
||||
|
||||
END Transpiler.
|
Reference in New Issue
Block a user