diff --git a/source/Compiler.elna b/source/Compiler.elna deleted file mode 100644 index 1cd98ab..0000000 --- a/source/Compiler.elna +++ /dev/null @@ -1,18 +0,0 @@ -MODULE Compiler; - -FROM FIO IMPORT StdIn; -FROM SYSTEM IMPORT ADR; - -FROM Lexer IMPORT Lexer, LexerDestroy, LexerInitialize; -FROM Transpiler IMPORT Transpile; - -VAR - ALexer: Lexer; - -BEGIN - LexerInitialize(ADR(ALexer), StdIn); - - Transpile(ADR(ALexer)); - - LexerDestroy(ADR(ALexer)) -END Compiler. diff --git a/source/Compiler.mod b/source/Compiler.mod new file mode 100644 index 0000000..54b5f38 --- /dev/null +++ b/source/Compiler.mod @@ -0,0 +1,18 @@ +MODULE Compiler; + +FROM FIO IMPORT StdIn; +FROM SYSTEM IMPORT ADR; + +FROM Lexer IMPORT Lexer, lexer_destroy, lexer_initialize; +FROM Transpiler IMPORT transpile; + +VAR + ALexer: Lexer; + +BEGIN + lexer_initialize(ADR(ALexer), StdIn); + + transpile(ADR(ALexer)); + + lexer_destroy(ADR(ALexer)) +END Compiler. diff --git a/source/Lexer.def b/source/Lexer.def index a6ba01f..6557849 100644 --- a/source/Lexer.def +++ b/source/Lexer.def @@ -80,16 +80,17 @@ TYPE ); LexerToken = RECORD CASE Kind: LexerKind OF - lexerKindBoolean: booleanKind: BOOLEAN + lexerKindBoolean: booleanKind: BOOLEAN | + lexerKindIdentifier: identifierKind: ARRAY[1..256] OF CHAR END END; PLexerToken = POINTER TO LexerToken; -PROCEDURE LexerInitialize(ALexer: PLexer; Input: File); -PROCEDURE LexerDestroy(ALexer: PLexer); +PROCEDURE lexer_initialize(ALexer: PLexer; Input: File); +PROCEDURE lexer_destroy(ALexer: PLexer); (* Returns the last read token. *) -PROCEDURE LexerCurrent(ALexer: PLexer): LexerToken; +PROCEDURE lexer_current(ALexer: PLexer): LexerToken; (* Read and return the next token. *) -PROCEDURE LexerLex(ALexer: PLexer): LexerToken; +PROCEDURE lexer_lex(ALexer: PLexer): LexerToken; END Lexer. diff --git a/source/Lexer.elna b/source/Lexer.mod similarity index 80% rename from source/Lexer.elna rename to source/Lexer.mod index 5cfae9d..09611ff 100644 --- a/source/Lexer.elna +++ b/source/Lexer.mod @@ -5,7 +5,7 @@ FROM SYSTEM IMPORT ADR; FROM Storage IMPORT DEALLOCATE, ALLOCATE; FROM Strings IMPORT Length; -FROM MemUtils IMPORT MemZero; +FROM MemUtils IMPORT MemCopy, MemZero; FROM StrCase IMPORT Lower; CONST @@ -70,7 +70,7 @@ VAR Classification: ARRAY[1..128] OF TransitionClass; Transitions: ARRAY[0..15] OF ARRAY[0..21] OF Transition; -PROCEDURE InitializeClassification(); +PROCEDURE initialize_classification(); BEGIN Classification[1] := transitionClassEof; (* NUL *) Classification[2] := transitionClassInvalid; (* SOH *) @@ -200,9 +200,8 @@ BEGIN Classification[126] := transitionClassOther; (* } *) Classification[127] := transitionClassSingle; (* ~ *) Classification[128] := transitionClassInvalid (* DEL *) -END InitializeClassification; - -PROCEDURE CompareKeyword(Keyword: ARRAY OF CHAR; TokenStart: PLexerBuffer; TokenEnd: PLexerBuffer): BOOLEAN; +END initialize_classification; +PROCEDURE compare_keyword(Keyword: ARRAY OF CHAR; TokenStart: PLexerBuffer; TokenEnd: PLexerBuffer): BOOLEAN; VAR Result: BOOLEAN; Index: CARDINAL; @@ -217,23 +216,20 @@ BEGIN END; Result := (Index = Length(Keyword)) AND (TokenStart = TokenEnd) AND Result; RETURN Result -END CompareKeyword; - +END compare_keyword; (* Reached the end of file. *) -PROCEDURE TransitionActionEof(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_eof(ALexer: PLexer; AToken: PLexerToken); BEGIN AToken^.Kind := lexerKindEof -END TransitionActionEof; - +END transition_action_eof; (* Add the character to the token currently read and advance to the next character. *) -PROCEDURE TransitionActionAccumulate(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_accumulate(ALexer: PLexer; AToken: PLexerToken); BEGIN INC(ALexer^.Current) -END TransitionActionAccumulate; - +END transition_action_accumulate; (* The current character is not a part of the token. Finish the token already * read. Don't advance to the next character. *) -PROCEDURE TransitionActionFinalize(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_finalize(ALexer: PLexer; AToken: PLexerToken); BEGIN IF ALexer^.Start^ = ':' THEN AToken^.Kind := lexerKindColon @@ -253,10 +249,9 @@ BEGIN IF ALexer^.Start^ = '.' THEN AToken^.Kind := lexerKindDot END -END TransitionActionFinalize; - +END transition_action_finalize; (* An action for tokens containing multiple characters. *) -PROCEDURE TransitionActionComposite(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_composite(ALexer: PLexer; AToken: PLexerToken); BEGIN IF ALexer^.Start^ = '<' THEN IF ALexer^.Current^ = '>' THEN @@ -276,17 +271,15 @@ BEGIN AToken^.Kind := lexerKindAssignment END; INC(ALexer^.Current) -END TransitionActionComposite; - +END transition_action_composite; (* Skip a space. *) -PROCEDURE TransitionActionSkip(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_skip(ALexer: PLexer; AToken: PLexerToken); BEGIN INC(ALexer^.Current); INC(ALexer^.Start) -END TransitionActionSkip; - +END transition_action_skip; (* Delimited string action. *) -PROCEDURE TransitionActionDelimited(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_delimited(ALexer: PLexer; AToken: PLexerToken); BEGIN IF ALexer^.Start^ = '(' THEN AToken^.Kind := lexerKindComment @@ -298,113 +291,114 @@ BEGIN AToken^.Kind := lexerKindString END; INC(ALexer^.Current) -END TransitionActionDelimited; - +END transition_action_delimited; (* Finalize keyword or identifier. *) -PROCEDURE TransitionActionKeyId(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_key_id(ALexer: PLexer; AToken: PLexerToken); BEGIN AToken^.Kind := lexerKindIdentifier; - IF CompareKeyword('PROGRAM', ALexer^.Start, ALexer^.Current) THEN + AToken^.identifierKind[1] := ALexer^.Current - ALexer^.Start; + MemCopy(ALexer^.Start, ORD(AToken^.identifierKind[1]), ADR(AToken^.identifierKind[2])); + + IF compare_keyword('PROGRAM', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindProgram END; - IF CompareKeyword('IMPORT', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('IMPORT', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindImport END; - IF CompareKeyword('CONST', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('CONST', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindConst END; - IF CompareKeyword('VAR', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('VAR', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindVar END; - IF CompareKeyword('IF', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('IF', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindIf END; - IF CompareKeyword('THEN', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('THEN', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindThen END; - IF CompareKeyword('ELSIF', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('ELSIF', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindElsif END; - IF CompareKeyword('ELSE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('ELSE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindElse END; - IF CompareKeyword('WHILE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('WHILE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindWhile END; - IF CompareKeyword('DO', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('DO', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindDo END; - IF CompareKeyword('proc', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('proc', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindProc END; - IF CompareKeyword('BEGIN', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('BEGIN', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindBegin END; - IF CompareKeyword('END', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('END', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindEnd END; - IF CompareKeyword('TYPE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('TYPE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindType END; - IF CompareKeyword('RECORD', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('RECORD', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindRecord END; - IF CompareKeyword('UNION', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('UNION', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindUnion END; - IF CompareKeyword('NIL', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('NIL', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindNull END; - IF CompareKeyword('AND', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('AND', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindAnd END; - IF CompareKeyword('OR', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('OR', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindOr END; - IF CompareKeyword('RETURN', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('RETURN', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindReturn END; - IF CompareKeyword('DEFINITION', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('DEFINITION', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindDefinition END; - IF CompareKeyword('TO', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('TO', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindTo END; - IF CompareKeyword('CASE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('CASE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindCase END; - IF CompareKeyword('OF', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('OF', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindOf END; - IF CompareKeyword('FROM', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('FROM', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindFrom END; - IF CompareKeyword('MODULE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('MODULE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindModule END; - IF CompareKeyword('IMPLEMENTATION', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('IMPLEMENTATION', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindImplementation END; - IF CompareKeyword('POINTER', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('POINTER', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindPointer END; - IF CompareKeyword('ARRAY', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('ARRAY', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindArray END; - IF CompareKeyword('TRUE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('TRUE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindBoolean; AToken^.booleanKind := TRUE END; - IF CompareKeyword('FALSE', ALexer^.Start, ALexer^.Current) THEN + IF compare_keyword('FALSE', ALexer^.Start, ALexer^.Current) THEN AToken^.Kind := lexerKindBoolean; AToken^.booleanKind := FALSE END -END TransitionActionKeyId; - +END transition_action_key_id; (* Action for tokens containing only one character. The character cannot be * followed by other characters forming a composite token. *) -PROCEDURE TransitionActionSingle(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_single(ALexer: PLexer; AToken: PLexerToken); BEGIN IF ALexer^.Current^ = '&' THEN AToken^.Kind := lexerKindAnd @@ -449,15 +443,13 @@ BEGIN AToken^.Kind := lexerKindPipe END; INC(ALexer^.Current) -END TransitionActionSingle; - +END transition_action_single; (* Handle an integer literal. *) -PROCEDURE TransitionActionInteger(ALexer: PLexer; AToken: PLexerToken); +PROCEDURE transition_action_integer(ALexer: PLexer; AToken: PLexerToken); BEGIN AToken^.Kind := lexerKindInteger -END TransitionActionInteger; - -PROCEDURE SetDefaultTransition(CurrentState: TransitionState; DefaultAction: TransitionAction; NextState: TransitionState); +END transition_action_integer; +PROCEDURE set_default_transition(CurrentState: TransitionState; DefaultAction: TransitionAction; NextState: TransitionState); VAR DefaultTransition: Transition; BEGIN @@ -486,8 +478,7 @@ BEGIN Transitions[ORD(CurrentState)][ORD(transitionClassGreater)] := DefaultTransition; Transitions[ORD(CurrentState)][ORD(transitionClassLess)] := DefaultTransition; Transitions[ORD(CurrentState)][ORD(transitionClassOther)] := DefaultTransition -END SetDefaultTransition; - +END set_default_transition; (* * The transition table describes transitions from one state to another, given * a symbol (character class). @@ -504,182 +495,182 @@ END SetDefaultTransition; * For the meaning of actions see labels in the lex_next function, which * handles each action. *) -PROCEDURE InitializeTransitions(); +PROCEDURE initialize_transitions(); BEGIN (* Start state. *) Transitions[ORD(transitionStateStart)][ORD(transitionClassInvalid)].Action := NIL; Transitions[ORD(transitionStateStart)][ORD(transitionClassInvalid)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassDigit)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassDigit)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassDigit)].NextState := transitionStateDecimal; - Transitions[ORD(transitionStateStart)][ORD(transitionClassAlpha)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassAlpha)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassAlpha)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateStart)][ORD(transitionClassSpace)].Action := TransitionActionSkip; + Transitions[ORD(transitionStateStart)][ORD(transitionClassSpace)].Action := transition_action_skip; Transitions[ORD(transitionStateStart)][ORD(transitionClassSpace)].NextState := transitionStateStart; - Transitions[ORD(transitionStateStart)][ORD(transitionClassColon)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassColon)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassColon)].NextState := transitionStateColon; - Transitions[ORD(transitionStateStart)][ORD(transitionClassEquals)].Action := TransitionActionSingle; + Transitions[ORD(transitionStateStart)][ORD(transitionClassEquals)].Action := transition_action_single; Transitions[ORD(transitionStateStart)][ORD(transitionClassEquals)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassLeftParen)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassLeftParen)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassLeftParen)].NextState := transitionStateLeftParen; - Transitions[ORD(transitionStateStart)][ORD(transitionClassRightParen)].Action := TransitionActionSingle; + Transitions[ORD(transitionStateStart)][ORD(transitionClassRightParen)].Action := transition_action_single; Transitions[ORD(transitionStateStart)][ORD(transitionClassRightParen)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassAsterisk)].Action := TransitionActionSingle; + Transitions[ORD(transitionStateStart)][ORD(transitionClassAsterisk)].Action := transition_action_single; Transitions[ORD(transitionStateStart)][ORD(transitionClassAsterisk)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassUnderscore)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassUnderscore)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassUnderscore)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateStart)][ORD(transitionClassSingle)].Action := TransitionActionSingle; + Transitions[ORD(transitionStateStart)][ORD(transitionClassSingle)].Action := transition_action_single; Transitions[ORD(transitionStateStart)][ORD(transitionClassSingle)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassHex)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassHex)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassHex)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateStart)][ORD(transitionClassZero)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassZero)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassZero)].NextState := transitionStateLeadingZero; - Transitions[ORD(transitionStateStart)][ORD(transitionClassX)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassX)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassX)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateStart)][ORD(transitionClassEof)].Action := TransitionActionEof; + Transitions[ORD(transitionStateStart)][ORD(transitionClassEof)].Action := transition_action_eof; Transitions[ORD(transitionStateStart)][ORD(transitionClassEof)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateStart)][ORD(transitionClassDot)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassDot)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassDot)].NextState := transitionStateDot; - Transitions[ORD(transitionStateStart)][ORD(transitionClassMinus)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassMinus)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassMinus)].NextState := transitionStateMinus; - Transitions[ORD(transitionStateStart)][ORD(transitionClassSingleQuote)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassSingleQuote)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassSingleQuote)].NextState := transitionStateCharacter; - Transitions[ORD(transitionStateStart)][ORD(transitionClassDoubleQuote)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassDoubleQuote)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassDoubleQuote)].NextState := transitionStateString; - Transitions[ORD(transitionStateStart)][ORD(transitionClassGreater)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassGreater)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassGreater)].NextState := transitionStateGreater; - Transitions[ORD(transitionStateStart)][ORD(transitionClassLess)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateStart)][ORD(transitionClassLess)].Action := transition_action_accumulate; Transitions[ORD(transitionStateStart)][ORD(transitionClassLess)].NextState := transitionStateLess; Transitions[ORD(transitionStateStart)][ORD(transitionClassOther)].Action := NIL; Transitions[ORD(transitionStateStart)][ORD(transitionClassOther)].NextState := transitionStateEnd; (* Colon state. *) - SetDefaultTransition(transitionStateColon, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateColon, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateColon)][ORD(transitionClassEquals)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateColon)][ORD(transitionClassEquals)].Action := transition_action_composite; Transitions[ORD(transitionStateColon)][ORD(transitionClassEquals)].NextState := transitionStateEnd; (* Identifier state. *) - SetDefaultTransition(transitionStateIdentifier, TransitionActionKeyId, transitionStateEnd); + set_default_transition(transitionStateIdentifier, transition_action_key_id, transitionStateEnd); - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassDigit)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassDigit)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassDigit)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassAlpha)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassAlpha)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassAlpha)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassUnderscore)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassUnderscore)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassUnderscore)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassHex)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassHex)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassHex)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassZero)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassZero)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassZero)].NextState := transitionStateIdentifier; - Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassX)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassX)].Action := transition_action_accumulate; Transitions[ORD(transitionStateIdentifier)][ORD(transitionClassX)].NextState := transitionStateIdentifier; (* Decimal state. *) - SetDefaultTransition(transitionStateDecimal, TransitionActionInteger, transitionStateEnd); + set_default_transition(transitionStateDecimal, transition_action_integer, transitionStateEnd); - Transitions[ORD(transitionStateDecimal)][ORD(transitionClassDigit)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateDecimal)][ORD(transitionClassDigit)].Action := transition_action_accumulate; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassDigit)].NextState := transitionStateDecimal; - Transitions[ORD(transitionStateDecimal)][ORD(transitionClassAlpha)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateDecimal)][ORD(transitionClassAlpha)].Action := transition_action_accumulate; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassAlpha)].NextState := transitionStateDecimalSuffix; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassUnderscore)].Action := NIL; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassUnderscore)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateDecimal)][ORD(transitionClassHex)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateDecimal)][ORD(transitionClassHex)].Action := transition_action_accumulate; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassHex)].NextState := transitionStateDecimalSuffix; - Transitions[ORD(transitionStateDecimal)][ORD(transitionClassZero)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateDecimal)][ORD(transitionClassZero)].Action := transition_action_accumulate; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassZero)].NextState := transitionStateDecimal; - Transitions[ORD(transitionStateDecimal)][ORD(transitionClassX)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateDecimal)][ORD(transitionClassX)].Action := transition_action_accumulate; Transitions[ORD(transitionStateDecimal)][ORD(transitionClassX)].NextState := transitionStateDecimalSuffix; (* Greater state. *) - SetDefaultTransition(transitionStateGreater, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateGreater, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateGreater)][ORD(transitionClassEquals)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateGreater)][ORD(transitionClassEquals)].Action := transition_action_composite; Transitions[ORD(transitionStateGreater)][ORD(transitionClassEquals)].NextState := transitionStateEnd; (* Minus state. *) - SetDefaultTransition(transitionStateMinus, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateMinus, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateMinus)][ORD(transitionClassGreater)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateMinus)][ORD(transitionClassGreater)].Action := transition_action_composite; Transitions[ORD(transitionStateMinus)][ORD(transitionClassGreater)].NextState := transitionStateEnd; (* Left paren state. *) - SetDefaultTransition(transitionStateLeftParen, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateLeftParen, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateLeftParen)][ORD(transitionClassAsterisk)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateLeftParen)][ORD(transitionClassAsterisk)].Action := transition_action_accumulate; Transitions[ORD(transitionStateLeftParen)][ORD(transitionClassAsterisk)].NextState := transitionStateComment; (* Less state. *) - SetDefaultTransition(transitionStateLess, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateLess, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateLess)][ORD(transitionClassEquals)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateLess)][ORD(transitionClassEquals)].Action := transition_action_composite; Transitions[ORD(transitionStateLess)][ORD(transitionClassEquals)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateLess)][ORD(transitionClassGreater)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateLess)][ORD(transitionClassGreater)].Action := transition_action_composite; Transitions[ORD(transitionStateLess)][ORD(transitionClassGreater)].NextState := transitionStateEnd; (* Hexadecimal after 0x. *) - SetDefaultTransition(transitionStateDot, TransitionActionFinalize, transitionStateEnd); + set_default_transition(transitionStateDot, transition_action_finalize, transitionStateEnd); - Transitions[ORD(transitionStateDot)][ORD(transitionClassDot)].Action := TransitionActionComposite; + Transitions[ORD(transitionStateDot)][ORD(transitionClassDot)].Action := transition_action_composite; Transitions[ORD(transitionStateDot)][ORD(transitionClassDot)].NextState := transitionStateEnd; (* Comment. *) - SetDefaultTransition(transitionStateComment, TransitionActionAccumulate, transitionStateComment); + set_default_transition(transitionStateComment, transition_action_accumulate, transitionStateComment); - Transitions[ORD(transitionStateComment)][ORD(transitionClassAsterisk)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateComment)][ORD(transitionClassAsterisk)].Action := transition_action_accumulate; Transitions[ORD(transitionStateComment)][ORD(transitionClassAsterisk)].NextState := transitionStateClosingComment; Transitions[ORD(transitionStateComment)][ORD(transitionClassEof)].Action := NIL; Transitions[ORD(transitionStateComment)][ORD(transitionClassEof)].NextState := transitionStateEnd; (* Closing comment. *) - SetDefaultTransition(transitionStateClosingComment, TransitionActionAccumulate, transitionStateComment); + set_default_transition(transitionStateClosingComment, transition_action_accumulate, transitionStateComment); Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassInvalid)].Action := NIL; Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassInvalid)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassRightParen)].Action := TransitionActionDelimited; + Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassRightParen)].Action := transition_action_delimited; Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassRightParen)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassAsterisk)].Action := TransitionActionAccumulate; + Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassAsterisk)].Action := transition_action_accumulate; Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassAsterisk)].NextState := transitionStateClosingComment; Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassEof)].Action := NIL; Transitions[ORD(transitionStateClosingComment)][ORD(transitionClassEof)].NextState := transitionStateEnd; (* Character. *) - SetDefaultTransition(transitionStateCharacter, TransitionActionAccumulate, transitionStateCharacter); + set_default_transition(transitionStateCharacter, transition_action_accumulate, transitionStateCharacter); Transitions[ORD(transitionStateCharacter)][ORD(transitionClassInvalid)].Action := NIL; Transitions[ORD(transitionStateCharacter)][ORD(transitionClassInvalid)].NextState := transitionStateEnd; @@ -687,11 +678,11 @@ BEGIN Transitions[ORD(transitionStateCharacter)][ORD(transitionClassEof)].Action := NIL; Transitions[ORD(transitionStateCharacter)][ORD(transitionClassEof)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateCharacter)][ORD(transitionClassSingleQuote)].Action := TransitionActionDelimited; + Transitions[ORD(transitionStateCharacter)][ORD(transitionClassSingleQuote)].Action := transition_action_delimited; Transitions[ORD(transitionStateCharacter)][ORD(transitionClassSingleQuote)].NextState := transitionStateEnd; (* String. *) - SetDefaultTransition(transitionStateString, TransitionActionAccumulate, transitionStateString); + set_default_transition(transitionStateString, transition_action_accumulate, transitionStateString); Transitions[ORD(transitionStateString)][ORD(transitionClassInvalid)].Action := NIL; Transitions[ORD(transitionStateString)][ORD(transitionClassInvalid)].NextState := transitionStateEnd; @@ -699,11 +690,11 @@ BEGIN Transitions[ORD(transitionStateString)][ORD(transitionClassEof)].Action := NIL; Transitions[ORD(transitionStateString)][ORD(transitionClassEof)].NextState := transitionStateEnd; - Transitions[ORD(transitionStateString)][ORD(transitionClassDoubleQuote)].Action := TransitionActionDelimited; + Transitions[ORD(transitionStateString)][ORD(transitionClassDoubleQuote)].Action := transition_action_delimited; Transitions[ORD(transitionStateString)][ORD(transitionClassDoubleQuote)].NextState := transitionStateEnd; (* Leading zero. *) - SetDefaultTransition(transitionStateLeadingZero, TransitionActionInteger, transitionStateEnd); + set_default_transition(transitionStateLeadingZero, transition_action_integer, transitionStateEnd); Transitions[ORD(transitionStateLeadingZero)][ORD(transitionClassDigit)].Action := NIL; Transitions[ORD(transitionStateLeadingZero)][ORD(transitionClassDigit)].NextState := transitionStateEnd; @@ -724,7 +715,7 @@ BEGIN Transitions[ORD(transitionStateLeadingZero)][ORD(transitionClassX)].NextState := transitionStateEnd; (* Digit with a character suffix. *) - SetDefaultTransition(transitionStateDecimalSuffix, TransitionActionInteger, transitionStateEnd); + set_default_transition(transitionStateDecimalSuffix, transition_action_integer, transitionStateEnd); Transitions[ORD(transitionStateDecimalSuffix)][ORD(transitionClassAlpha)].Action := NIL; Transitions[ORD(transitionStateDecimalSuffix)][ORD(transitionClassAlpha)].NextState := transitionStateEnd; @@ -740,9 +731,8 @@ BEGIN Transitions[ORD(transitionStateDecimalSuffix)][ORD(transitionClassX)].Action := NIL; Transitions[ORD(transitionStateDecimalSuffix)][ORD(transitionClassX)].NextState := transitionStateEnd -END InitializeTransitions; - -PROCEDURE LexerInitialize(ALexer: PLexer; Input: File); +END initialize_transitions; +PROCEDURE lexer_initialize(ALexer: PLexer; Input: File); BEGIN ALexer^.Input := Input; ALexer^.Length := 0; @@ -750,9 +740,8 @@ BEGIN ALLOCATE(ALexer^.Buffer, ChunkSize); MemZero(ALexer^.Buffer, ChunkSize); ALexer^.Size := ChunkSize -END LexerInitialize; - -PROCEDURE LexerCurrent(ALexer: PLexer): LexerToken; +END lexer_initialize; +PROCEDURE lexer_current(ALexer: PLexer): LexerToken; VAR CurrentClass: TransitionClass; CurrentState: TransitionState; @@ -772,9 +761,8 @@ BEGIN CurrentState := CurrentTransition.NextState END; RETURN Result -END LexerCurrent; - -PROCEDURE LexerLex(ALexer: PLexer): LexerToken; +END lexer_current; +PROCEDURE lexer_lex(ALexer: PLexer): LexerToken; VAR Result: LexerToken; BEGIN @@ -784,16 +772,14 @@ BEGIN END; ALexer^.Start := ALexer^.Current; - Result := LexerCurrent(ALexer); + Result := lexer_current(ALexer); RETURN Result -END LexerLex; - -PROCEDURE LexerDestroy(ALexer: PLexer); +END lexer_lex; +PROCEDURE lexer_destroy(ALexer: PLexer); BEGIN DEALLOCATE(ALexer^.Buffer, ALexer^.Size) -END LexerDestroy; - +END lexer_destroy; BEGIN - InitializeClassification(); - InitializeTransitions() + initialize_classification(); + initialize_transitions() END Lexer. diff --git a/source/Transpiler.def b/source/Transpiler.def index a19ad37..c3cd8a7 100644 --- a/source/Transpiler.def +++ b/source/Transpiler.def @@ -2,6 +2,6 @@ DEFINITION MODULE Transpiler; FROM Lexer IMPORT PLexer; -PROCEDURE Transpile(ALexer: PLexer); +PROCEDURE transpile(ALexer: PLexer); END Transpiler. diff --git a/source/Transpiler.elna b/source/Transpiler.elna deleted file mode 100644 index 1f50d43..0000000 --- a/source/Transpiler.elna +++ /dev/null @@ -1,630 +0,0 @@ -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 - PTranspilerContext = POINTER TO TranspilerContext; - TranspilerContext = RECORD - Indentation: CARDINAL - END; - -(* 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): BOOLEAN; -VAR - Token: LexerToken; - Result: BOOLEAN; -BEGIN - Token := LexerCurrent(ALexer); - Result := Token.Kind = lexerKindConst; - - IF Result THEN - WriteString('CONST'); - WriteLn(); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind = lexerKindIdentifier DO - TranspileConstant(AContext, ALexer); - Token := TranspilerLex(ALexer) - END - END; - RETURN Result -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) - END; - IF 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); - IF TranspileConstantPart(AContext, ALexer) THEN - WriteLn() - END; - TranspileTypePart(AContext, ALexer); - IF TranspileVariablePart(AContext, ALexer) THEN - WriteLn() - END; - TranspileProcedurePart(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 TranspileTypeFields(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - Token := TranspilerLex(ALexer); - - WHILE Token.Kind <> lexerKindEnd DO - WriteString(' '); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer); - WriteString(': '); - TranspileTypeExpression(AContext, ALexer); - Token := TranspilerLex(ALexer); - - IF Token.Kind = lexerKindSemicolon THEN - Token := TranspilerLex(ALexer); - Write(';') - END; - WriteLn() - END -END TranspileTypeFields; - -PROCEDURE TranspileRecordType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -BEGIN - WriteString('RECORD'); - WriteLn(); - TranspileTypeFields(AContext, ALexer); - WriteString(' END') -END TranspileRecordType; - -PROCEDURE TranspilePointerType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - Token := LexerCurrent(ALexer); - WriteString('POINTER TO '); - IF Token.Kind = lexerKindPointer THEN - Token := TranspilerLex(ALexer) - END; - TranspileTypeExpression(AContext, ALexer) -END TranspilePointerType; - -PROCEDURE TranspileArrayType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString('ARRAY'); - Token := TranspilerLex(ALexer); - - IF Token.Kind <> lexerKindOf THEN - Write('['); - Token := TranspilerLex(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); - Write(']'); - Token := TranspilerLex(ALexer) - END; - WriteString(' OF '); - TranspileTypeExpression(AContext, ALexer) -END TranspileArrayType; - -PROCEDURE TranspileEnumerationType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString('('); - WriteLn(); - WriteString(' '); - - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - - Token := TranspilerLex(ALexer); - - WHILE Token.Kind = lexerKindComma DO - Write(','); - WriteLn(); - WriteString(' '); - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - - Token := TranspilerLex(ALexer) - END; - WriteLn(); - WriteString(' )') -END TranspileEnumerationType; - -PROCEDURE TranspileUnionType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -END TranspileUnionType; - -PROCEDURE TranspileProcedureType(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - Token := TranspilerLex(ALexer); - WriteString('PROCEDURE('); - - Token := TranspilerLex(ALexer); - - WHILE Token.Kind <> lexerKindRightParen DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - - Token := TranspilerLex(ALexer); - IF Token.Kind = lexerKindComma THEN - Token := TranspilerLex(ALexer); - WriteString(', ') - END - END; - Write(')') -END TranspileProcedureType; - -PROCEDURE TranspileTypeExpression(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - Token := TranspilerLex(ALexer); - IF Token.Kind = lexerKindRecord THEN - TranspileRecordType(AContext, ALexer) - END; - IF Token.Kind = lexerKindLeftParen THEN - TranspileEnumerationType(AContext, ALexer) - END; - IF Token.Kind = lexerKindArray THEN - TranspileArrayType(AContext, ALexer) - END; - IF (Token.Kind = lexerKindPointer) OR (Token.Kind = lexerKindHat) THEN - TranspilePointerType(AContext, ALexer) - END; - IF Token.Kind = lexerKindProc THEN - TranspileProcedureType(AContext, ALexer) - END; - IF Token.Kind = lexerKindIdentifier THEN - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start) - END -END TranspileTypeExpression; - -PROCEDURE TranspileTypeDeclaration(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(' = '); - TranspileTypeExpression(AContext, ALexer); - Token := TranspilerLex(ALexer); - WriteSemicolon(); -END TranspileTypeDeclaration; - -PROCEDURE TranspileTypePart(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -BEGIN - Token := LexerCurrent(ALexer); - - IF Token.Kind = lexerKindType THEN - WriteString('TYPE'); - WriteLn(); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind = lexerKindIdentifier DO - TranspileTypeDeclaration(AContext, ALexer); - Token := TranspilerLex(ALexer) - END; - WriteLn() - END -END TranspileTypePart; - -PROCEDURE TranspileVariableDeclaration(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(': '); - TranspileTypeExpression(AContext, ALexer); - Token := TranspilerLex(ALexer); - WriteSemicolon() -END TranspileVariableDeclaration; - -PROCEDURE TranspileVariablePart(AContext: PTranspilerContext; ALexer: PLexer): BOOLEAN; -VAR - Token: LexerToken; - Result: BOOLEAN; -BEGIN - Token := LexerCurrent(ALexer); - Result := Token.Kind = lexerKindVar; - - IF Result THEN - WriteString('VAR'); - WriteLn(); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind = lexerKindIdentifier DO - TranspileVariableDeclaration(AContext, ALexer); - Token := TranspilerLex(ALexer) - END - END; - RETURN Result -END TranspileVariablePart; - -PROCEDURE TranspileProcedureHeading(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString('PROCEDURE '); - - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - - Token := TranspilerLex(ALexer); - Write('('); - - Token := TranspilerLex(ALexer); - WHILE Token.Kind <> lexerKindRightParen DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - - Token := TranspilerLex(ALexer); - WriteString(': '); - - TranspileTypeExpression(AContext, ALexer); - - Token := TranspilerLex(ALexer); - IF Token.Kind = lexerKindSemicolon THEN - WriteString('; '); - Token := TranspilerLex(ALexer) - END - END; - WriteString(')'); - Token := TranspilerLex(ALexer); - - (* Check for the return type and write it. *) - IF Token.Kind = lexerKindColon THEN - WriteString(': '); - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer) - END; - Token := TranspilerLex(ALexer); - WriteSemicolon() -END TranspileProcedureHeading; - -PROCEDURE TranspileIfStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString(' IF '); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind <> lexerKindThen DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Write(' '); - Token := TranspilerLex(ALexer) - END; - WriteString('THEN'); - WriteLn(); - TranspileStatements(AContext, ALexer); - WriteString(' END'); - Token := TranspilerLex(ALexer) -END TranspileIfStatement; - -PROCEDURE TranspileWhileStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString(' WHILE '); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind <> lexerKindDo DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Write(' '); - Token := TranspilerLex(ALexer) - END; - WriteString('DO'); - WriteLn(); - TranspileStatements(AContext, ALexer); - WriteString(' END'); - Token := TranspilerLex(ALexer) -END TranspileWhileStatement; - -PROCEDURE TranspileAssignmentStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString(' := '); - Token := TranspilerLex(ALexer); - - WHILE (Token.Kind <> lexerKindSemicolon) AND (Token.Kind <> lexerKindEnd) DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Write(' '); - Token := TranspilerLex(ALexer) - END -END TranspileAssignmentStatement; - -PROCEDURE TranspileCallStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString('('); - Token := TranspilerLex(ALexer); - - WHILE (Token.Kind <> lexerKindSemicolon) AND (Token.Kind <> lexerKindEnd) DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer) - END -END TranspileCallStatement; - -PROCEDURE TranspileReturnStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - WriteString(' RETURN '); - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer) -END TranspileReturnStatement; - -PROCEDURE TranspileStatement(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; -BEGIN - Token := TranspilerLex(ALexer); - - IF Token.Kind = lexerKindIf THEN - TranspileIfStatement(AContext, ALexer) - END; - IF Token.Kind = lexerKindWhile THEN - TranspileWhileStatement(AContext, ALexer) - END; - IF Token.Kind = lexerKindReturn THEN - TranspileReturnStatement(AContext, ALexer) - END; - IF Token.Kind = lexerKindIdentifier THEN - WriteString(' '); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer); - - WHILE Token.Kind = lexerKindLeftSquare DO - Write('['); - Token := TranspilerLex(ALexer); - WHILE Token.Kind <> lexerKindRightSquare DO - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer) - END; - Write(']'); - Token := TranspilerLex(ALexer); - END; - IF Token.Kind = lexerKindHat THEN - Write('^'); - Token := TranspilerLex(ALexer) - END; - IF Token.Kind = lexerKindDot THEN - Write('.'); - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer); - END; - IF Token.Kind = lexerKindHat THEN - Write('^'); - Token := TranspilerLex(ALexer) - END; - - IF Token.Kind = lexerKindAssignment THEN - TranspileAssignmentStatement(AContext, ALexer) - END; - IF Token.Kind = lexerKindLeftParen THEN - TranspileCallStatement(AContext, ALexer) - END - END -END TranspileStatement; - -PROCEDURE TranspileStatements(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -BEGIN - Token := LexerCurrent(ALexer); - - WHILE Token.Kind <> lexerKindEnd DO - TranspileStatement(AContext, ALexer); - Token := LexerCurrent(ALexer); - - IF Token.Kind = lexerKindSemicolon THEN - Write(';') - END; - WriteLn() - END -END TranspileStatements; - -PROCEDURE TranspileStatementPart(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -BEGIN - Token := LexerCurrent(ALexer); - IF Token.Kind = lexerKindBegin THEN - WriteString('BEGIN'); - WriteLn(); - TranspileStatements(AContext, ALexer) - END -END TranspileStatementPart; - -PROCEDURE TranspileProcedureDeclaration(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; - SeenPart: BOOLEAN; - WrittenBytes: CARDINAL; -BEGIN - TranspileProcedureHeading(AContext, ALexer); - SeenPart := TranspileConstantPart(AContext, ALexer); - SeenPart := TranspileVariablePart(AContext, ALexer); - TranspileStatementPart(AContext, ALexer); - WriteString('END '); - Token := TranspilerLex(ALexer); - WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); - Token := TranspilerLex(ALexer); - WriteSemicolon(); - Token := TranspilerLex(ALexer) -END TranspileProcedureDeclaration; - -PROCEDURE TranspileProcedurePart(AContext: PTranspilerContext; ALexer: PLexer); -VAR - Token: LexerToken; -BEGIN - Token := LexerCurrent(ALexer); - - WHILE Token.Kind = lexerKindProc DO - TranspileProcedureDeclaration(AContext, ALexer); - Token := LexerCurrent(ALexer); - WriteLn() - END -END TranspileProcedurePart; - -PROCEDURE Transpile(ALexer: PLexer); -VAR - Token: LexerToken; - WrittenBytes: CARDINAL; - Context: TranspilerContext; -BEGIN - TranspileModule(ADR(Context), ALexer) -END Transpile; - -END Transpiler. diff --git a/source/Transpiler.mod b/source/Transpiler.mod new file mode 100644 index 0000000..500b219 --- /dev/null +++ b/source/Transpiler.mod @@ -0,0 +1,611 @@ +IMPLEMENTATION MODULE Transpiler; + +FROM FIO IMPORT WriteNBytes, StdOut; +FROM SYSTEM IMPORT ADR, ADDRESS; + +FROM Terminal IMPORT Write, WriteLn, WriteString; +FROM Lexer IMPORT Lexer, LexerToken, lexer_current, lexer_lex, LexerKind; + +TYPE + PTranspilerContext = POINTER TO TranspilerContext; + TranspilerContext = RECORD + Indentation: CARDINAL + END; + +(* Calls lexer_lex() but skips the comments. *) +PROCEDURE transpiler_lex(ALexer: PLexer): LexerToken; +VAR + Result: LexerToken; +BEGIN + Result := lexer_lex(ALexer); + + WHILE Result.Kind = lexerKindComment DO + Result := lexer_lex(ALexer) + END; + + RETURN Result +END transpiler_lex; +(* Write a semicolon followed by a newline. *) +PROCEDURE write_semicolon(); +BEGIN + WriteString(';'); + WriteLn() +END write_semicolon; +PROCEDURE transpile_import(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString('FROM '); + Token := transpiler_lex(ALexer); + + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WriteString(' IMPORT '); + + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WHILE Token.Kind <> lexerKindSemicolon DO + WriteString(', '); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) + END; + write_semicolon(); + Token := transpiler_lex(ALexer) +END transpile_import; +PROCEDURE transpile_import_part(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + Token := lexer_current(ALexer); + + WHILE Token.Kind = lexerKindFrom DO + transpile_import(AContext, ALexer); + Token := lexer_current(ALexer) + END; + WriteLn() +END transpile_import_part; +PROCEDURE transpile_constant(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' '); + Token := lexer_current(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WriteString(' = '); + + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + write_semicolon() +END transpile_constant; +PROCEDURE transpile_constant_part(AContext: PTranspilerContext; ALexer: PLexer): BOOLEAN; +VAR + Token: LexerToken; + Result: BOOLEAN; +BEGIN + Token := lexer_current(ALexer); + Result := Token.Kind = lexerKindConst; + + IF Result THEN + WriteString('CONST'); + WriteLn(); + Token := transpiler_lex(ALexer); + + WHILE Token.Kind = lexerKindIdentifier DO + transpile_constant(AContext, ALexer); + Token := transpiler_lex(ALexer) + END + END; + RETURN Result +END transpile_constant_part; +PROCEDURE transpile_module(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + + IF Token.Kind = lexerKindDefinition THEN + WriteString('DEFINITION '); + Token := transpiler_lex(ALexer) + END; + IF Token.Kind = lexerKindImplementation THEN + WriteString('IMPLEMENTATION '); + Token := transpiler_lex(ALexer) + END; + WriteString('MODULE '); + + (* Write the module name and end the line with a semicolon and newline. *) + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + write_semicolon(); + WriteLn(); + + (* Write the module body. *) + Token := transpiler_lex(ALexer); + transpile_import_part(AContext, ALexer); + IF transpile_constant_part(AContext, ALexer) THEN + WriteLn() + END; + transpile_type_part(AContext, ALexer); + IF transpile_variable_part(AContext, ALexer) THEN + WriteLn() + END; + transpile_procedure_part(AContext, ALexer); + transpile_statement_part(AContext, ALexer); + + WriteString('END '); + + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + Write('.'); + + Token := transpiler_lex(ALexer); + WriteLn() +END transpile_module; +PROCEDURE transpile_type_fields(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + + WHILE Token.Kind <> lexerKindEnd DO + WriteString(' '); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer); + WriteString(': '); + transpile_type_expression(AContext, ALexer); + Token := transpiler_lex(ALexer); + + IF Token.Kind = lexerKindSemicolon THEN + Token := transpiler_lex(ALexer); + Write(';') + END; + WriteLn() + END +END transpile_type_fields; +PROCEDURE transpile_record_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + WriteString('RECORD'); + WriteLn(); + transpile_type_fields(AContext, ALexer); + WriteString(' END') +END transpile_record_type; +PROCEDURE transpile_pointer_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := lexer_current(ALexer); + WriteString('POINTER TO '); + IF Token.Kind = lexerKindPointer THEN + Token := transpiler_lex(ALexer) + END; + transpile_type_expression(AContext, ALexer) +END transpile_pointer_type; +PROCEDURE transpile_array_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString('ARRAY'); + Token := transpiler_lex(ALexer); + + IF Token.Kind <> lexerKindOf THEN + Write('['); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer); + WriteString('..'); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer); + Write(']'); + Token := transpiler_lex(ALexer) + END; + WriteString(' OF '); + transpile_type_expression(AContext, ALexer) +END transpile_array_type; +PROCEDURE transpile_enumeration_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString('('); + WriteLn(); + WriteString(' '); + + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + + WHILE Token.Kind = lexerKindComma DO + Write(','); + WriteLn(); + WriteString(' '); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer) + END; + WriteLn(); + WriteString(' )') +END transpile_enumeration_type; +PROCEDURE transpile_union_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +END transpile_union_type; +PROCEDURE transpile_procedure_type(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + WriteString('PROCEDURE('); + + Token := transpiler_lex(ALexer); + + WHILE Token.Kind <> lexerKindRightParen DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + IF Token.Kind = lexerKindComma THEN + Token := transpiler_lex(ALexer); + WriteString(', ') + END + END; + Write(')') +END transpile_procedure_type; +PROCEDURE transpile_type_expression(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + IF Token.Kind = lexerKindRecord THEN + transpile_record_type(AContext, ALexer) + END; + IF Token.Kind = lexerKindLeftParen THEN + transpile_enumeration_type(AContext, ALexer) + END; + IF Token.Kind = lexerKindArray THEN + transpile_array_type(AContext, ALexer) + END; + IF (Token.Kind = lexerKindPointer) OR (Token.Kind = lexerKindHat) THEN + transpile_pointer_type(AContext, ALexer) + END; + IF Token.Kind = lexerKindProc THEN + transpile_procedure_type(AContext, ALexer) + END; + IF Token.Kind = lexerKindIdentifier THEN + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start) + END +END transpile_type_expression; +PROCEDURE transpile_type_declaration(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' '); + Token := lexer_current(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WriteString(' = '); + transpile_type_expression(AContext, ALexer); + Token := transpiler_lex(ALexer); + write_semicolon(); +END transpile_type_declaration; +PROCEDURE transpile_type_part(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + Token := lexer_current(ALexer); + + IF Token.Kind = lexerKindType THEN + WriteString('TYPE'); + WriteLn(); + Token := transpiler_lex(ALexer); + + WHILE Token.Kind = lexerKindIdentifier DO + transpile_type_declaration(AContext, ALexer); + Token := transpiler_lex(ALexer) + END; + WriteLn() + END +END transpile_type_part; +PROCEDURE transpile_variable_declaration(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' '); + Token := lexer_current(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WriteString(': '); + transpile_type_expression(AContext, ALexer); + Token := transpiler_lex(ALexer); + write_semicolon() +END transpile_variable_declaration; +PROCEDURE transpile_variable_part(AContext: PTranspilerContext; ALexer: PLexer): BOOLEAN; +VAR + Token: LexerToken; + Result: BOOLEAN; +BEGIN + Token := lexer_current(ALexer); + Result := Token.Kind = lexerKindVar; + + IF Result THEN + WriteString('VAR'); + WriteLn(); + Token := transpiler_lex(ALexer); + + WHILE Token.Kind = lexerKindIdentifier DO + transpile_variable_declaration(AContext, ALexer); + Token := transpiler_lex(ALexer) + END + END; + RETURN Result +END transpile_variable_part; +PROCEDURE transpile_procedure_heading(AContext: PTranspilerContext; ALexer: PLexer): LexerToken; +VAR + Token: LexerToken; + Result: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString('PROCEDURE '); + + Result := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + Write('('); + + Token := transpiler_lex(ALexer); + WHILE Token.Kind <> lexerKindRightParen DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + + Token := transpiler_lex(ALexer); + WriteString(': '); + + transpile_type_expression(AContext, ALexer); + + Token := transpiler_lex(ALexer); + IF Token.Kind = lexerKindSemicolon THEN + WriteString('; '); + Token := transpiler_lex(ALexer) + END + END; + WriteString(')'); + Token := transpiler_lex(ALexer); + + (* Check for the return type and write it. *) + IF Token.Kind = lexerKindColon THEN + WriteString(': '); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) + END; + Token := transpiler_lex(ALexer); + write_semicolon(); + + RETURN Result +END transpile_procedure_heading; +PROCEDURE transpile_expression(AContext: PTranspilerContext; ALexer: PLexer; TrailingToken: LexerKind); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + + WHILE (Token.Kind <> TrailingToken) AND (Token.Kind <> lexerKindEnd) DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Write(' '); + Token := transpiler_lex(ALexer) + END +END transpile_expression; +PROCEDURE transpile_if_statement(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' IF '); + transpile_expression(AContext, ALexer, lexerKindThen); + + WriteString('THEN'); + WriteLn(); + transpile_statements(AContext, ALexer); + WriteString(' END'); + Token := transpiler_lex(ALexer) +END transpile_if_statement; +PROCEDURE transpile_while_statement(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' WHILE '); + transpile_expression(AContext, ALexer, lexerKindDo); + + WriteString('DO'); + WriteLn(); + transpile_statements(AContext, ALexer); + WriteString(' END'); + Token := transpiler_lex(ALexer) +END transpile_while_statement; +PROCEDURE transpile_assignment_statement(AContext: PTranspilerContext; ALexer: PLexer); +BEGIN + WriteString(' := '); + transpile_expression(AContext, ALexer, lexerKindSemicolon); +END transpile_assignment_statement; +PROCEDURE transpile_call_statement(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString('('); + Token := transpiler_lex(ALexer); + + WHILE (Token.Kind <> lexerKindSemicolon) AND (Token.Kind <> lexerKindEnd) DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) + END +END transpile_call_statement; +PROCEDURE transpile_return_statement(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + WriteString(' RETURN '); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) +END transpile_return_statement; +PROCEDURE transpile_statement(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; +BEGIN + Token := transpiler_lex(ALexer); + + IF Token.Kind = lexerKindIf THEN + transpile_if_statement(AContext, ALexer) + END; + IF Token.Kind = lexerKindWhile THEN + transpile_while_statement(AContext, ALexer) + END; + IF Token.Kind = lexerKindReturn THEN + transpile_return_statement(AContext, ALexer) + END; + IF Token.Kind = lexerKindIdentifier THEN + WriteString(' '); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer); + + WHILE Token.Kind = lexerKindLeftSquare DO + Write('['); + Token := transpiler_lex(ALexer); + WHILE Token.Kind <> lexerKindRightSquare DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) + END; + Write(']'); + Token := transpiler_lex(ALexer); + END; + IF Token.Kind = lexerKindHat THEN + Write('^'); + Token := transpiler_lex(ALexer) + END; + IF Token.Kind = lexerKindDot THEN + Write('.'); + Token := transpiler_lex(ALexer); + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer); + END; + IF Token.Kind = lexerKindHat THEN + Write('^'); + Token := transpiler_lex(ALexer) + END; + WHILE Token.Kind = lexerKindLeftSquare DO + Write('['); + Token := transpiler_lex(ALexer); + WHILE Token.Kind <> lexerKindRightSquare DO + WrittenBytes := WriteNBytes(StdOut, ADDRESS(ALexer^.Current - ALexer^.Start), ALexer^.Start); + Token := transpiler_lex(ALexer) + END; + Write(']'); + Token := transpiler_lex(ALexer); + END; + + IF Token.Kind = lexerKindAssignment THEN + transpile_assignment_statement(AContext, ALexer) + END; + IF Token.Kind = lexerKindLeftParen THEN + transpile_call_statement(AContext, ALexer) + END + END +END transpile_statement; +PROCEDURE transpile_statements(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + Token := lexer_current(ALexer); + + WHILE Token.Kind <> lexerKindEnd DO + transpile_statement(AContext, ALexer); + Token := lexer_current(ALexer); + + IF Token.Kind = lexerKindSemicolon THEN + Write(';') + END; + WriteLn() + END +END transpile_statements; +PROCEDURE transpile_statement_part(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + Token := lexer_current(ALexer); + IF Token.Kind = lexerKindBegin THEN + WriteString('BEGIN'); + WriteLn(); + transpile_statements(AContext, ALexer) + END +END transpile_statement_part; +PROCEDURE transpile_procedure_declaration(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; + SeenPart: BOOLEAN; + WrittenBytes: CARDINAL; +BEGIN + Token := transpile_procedure_heading(AContext, ALexer); + SeenPart := transpile_constant_part(AContext, ALexer); + SeenPart := transpile_variable_part(AContext, ALexer); + transpile_statement_part(AContext, ALexer); + + WriteString('END '); + WrittenBytes := WriteNBytes(StdOut, ORD(Token.identifierKind[1]), ADR(Token.identifierKind[2])); + + Token := transpiler_lex(ALexer); + write_semicolon(); + Token := transpiler_lex(ALexer) +END transpile_procedure_declaration; +PROCEDURE transpile_procedure_part(AContext: PTranspilerContext; ALexer: PLexer); +VAR + Token: LexerToken; +BEGIN + Token := lexer_current(ALexer); + + WHILE Token.Kind = lexerKindProc DO + transpile_procedure_declaration(AContext, ALexer); + Token := lexer_current(ALexer); + WriteLn() + END +END transpile_procedure_part; +PROCEDURE transpile(ALexer: PLexer); +VAR + Token: LexerToken; + WrittenBytes: CARDINAL; + Context: TranspilerContext; +BEGIN + transpile_module(ADR(Context), ALexer) +END transpile; +END Transpiler.