Add A command line parsing procedure
This commit is contained in:
parent
a93d12eb50
commit
23885e5b95
3
source/CommandLine.def
Normal file
3
source/CommandLine.def
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
DEFINITION MODULE CommandLine;
|
||||||
|
|
||||||
|
END CommandLine.
|
3
source/CommandLine.mod
Normal file
3
source/CommandLine.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE CommandLine;
|
||||||
|
|
||||||
|
END CommandLine.
|
15
source/CommandLineInterface.def
Normal file
15
source/CommandLineInterface.def
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
DEFINITION MODULE CommandLineInterface;
|
||||||
|
|
||||||
|
FROM Common IMPORT ShortString;
|
||||||
|
|
||||||
|
TYPE
|
||||||
|
CommandLine = RECORD
|
||||||
|
input: ShortString;
|
||||||
|
lex: BOOLEAN;
|
||||||
|
parse: BOOLEAN
|
||||||
|
END;
|
||||||
|
PCommandLine = POINTER TO CommandLine;
|
||||||
|
|
||||||
|
PROCEDURE parse_command_line(): PCommandLine;
|
||||||
|
|
||||||
|
END CommandLineInterface.
|
74
source/CommandLineInterface.mod
Normal file
74
source/CommandLineInterface.mod
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
IMPLEMENTATION MODULE CommandLineInterface;
|
||||||
|
|
||||||
|
FROM SYSTEM IMPORT ADR, TSIZE;
|
||||||
|
|
||||||
|
FROM Args IMPORT GetArg, Narg;
|
||||||
|
FROM FIO IMPORT WriteString, WriteChar, WriteLine, StdErr;
|
||||||
|
FROM Storage IMPORT ALLOCATE;
|
||||||
|
FROM Strings IMPORT CompareStr, Length;
|
||||||
|
FROM MemUtils IMPORT MemZero;
|
||||||
|
|
||||||
|
FROM Common IMPORT ShortString;
|
||||||
|
|
||||||
|
PROCEDURE parse_command_line(): PCommandLine;
|
||||||
|
VAR
|
||||||
|
parameter: ShortString;
|
||||||
|
i: CARDINAL;
|
||||||
|
result: PCommandLine;
|
||||||
|
parsed: BOOLEAN;
|
||||||
|
BEGIN
|
||||||
|
i := 1;
|
||||||
|
ALLOCATE(result, TSIZE(CommandLine));
|
||||||
|
result^.lex := FALSE;
|
||||||
|
result^.parse := FALSE;
|
||||||
|
MemZero(ADR(result^.input), 256);
|
||||||
|
|
||||||
|
WHILE (i < Narg()) AND (result <> NIL) DO
|
||||||
|
parsed := GetArg(parameter, i);
|
||||||
|
parsed := FALSE;
|
||||||
|
|
||||||
|
IF CompareStr(parameter, '--lex') = 0 THEN
|
||||||
|
parsed := TRUE;
|
||||||
|
result^.lex := TRUE
|
||||||
|
END;
|
||||||
|
IF CompareStr(parameter, '--parse') = 0 THEN
|
||||||
|
parsed := TRUE;
|
||||||
|
result^.parse := TRUE
|
||||||
|
END;
|
||||||
|
IF parameter[0] <> '-' THEN
|
||||||
|
parsed := TRUE;
|
||||||
|
|
||||||
|
IF Length(result^.input) > 0 THEN
|
||||||
|
WriteString(StdErr, 'Fatal error: only one source file can be compiled at once. First given "');
|
||||||
|
WriteString(StdErr, result^.input);
|
||||||
|
WriteString(StdErr, '", then "');
|
||||||
|
WriteString(StdErr, parameter);
|
||||||
|
WriteString(StdErr, '".');
|
||||||
|
WriteLine(StdErr);
|
||||||
|
result := NIL
|
||||||
|
END;
|
||||||
|
IF result <> NIL THEN
|
||||||
|
result^.input := parameter
|
||||||
|
END
|
||||||
|
END;
|
||||||
|
IF parsed = FALSE THEN
|
||||||
|
WriteString(StdErr, 'Fatal error: unknown command line options: ');
|
||||||
|
|
||||||
|
WriteString(StdErr, parameter);
|
||||||
|
WriteChar(StdErr, '.');
|
||||||
|
WriteLine(StdErr);
|
||||||
|
|
||||||
|
result := NIL
|
||||||
|
END;
|
||||||
|
|
||||||
|
i := i + 1
|
||||||
|
END;
|
||||||
|
IF (result <> NIL) AND (Length(result^.input) = 0) THEN
|
||||||
|
WriteString(StdErr, 'Fatal error: no input files.');
|
||||||
|
WriteLine(StdErr);
|
||||||
|
result := NIL
|
||||||
|
END;
|
||||||
|
|
||||||
|
RETURN result
|
||||||
|
END parse_command_line;
|
||||||
|
END CommandLineInterface.
|
8
source/Common.def
Normal file
8
source/Common.def
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
DEFINITION MODULE Common;
|
||||||
|
|
||||||
|
TYPE
|
||||||
|
ShortString = ARRAY[0..255] OF CHAR;
|
||||||
|
Identifier = ARRAY[1..256] OF CHAR;
|
||||||
|
PIdentifier = POINTER TO Identifier;
|
||||||
|
|
||||||
|
END Common.
|
3
source/Common.mod
Normal file
3
source/Common.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
IMPLEMENTATION MODULE Common;
|
||||||
|
|
||||||
|
END Common.
|
@ -1,18 +1,50 @@
|
|||||||
MODULE Compiler;
|
MODULE Compiler;
|
||||||
|
|
||||||
FROM FIO IMPORT StdIn;
|
FROM FIO IMPORT Close, IsNoError, File, OpenToRead, StdErr, StdOut, WriteLine, WriteString;
|
||||||
FROM SYSTEM IMPORT ADR;
|
FROM SYSTEM IMPORT ADR;
|
||||||
|
FROM M2RTS IMPORT HALT, ExitOnHalt;
|
||||||
|
|
||||||
FROM Lexer IMPORT Lexer, lexer_destroy, lexer_initialize;
|
FROM Lexer IMPORT Lexer, lexer_destroy, lexer_initialize;
|
||||||
FROM Transpiler IMPORT transpile;
|
FROM Transpiler IMPORT transpile;
|
||||||
|
FROM CommandLineInterface IMPORT PCommandLine, parse_command_line;
|
||||||
|
|
||||||
|
VAR
|
||||||
|
command_line: PCommandLine;
|
||||||
|
|
||||||
|
PROCEDURE compile_from_stream();
|
||||||
VAR
|
VAR
|
||||||
lexer: Lexer;
|
lexer: Lexer;
|
||||||
|
source_input: File;
|
||||||
BEGIN
|
BEGIN
|
||||||
lexer_initialize(ADR(lexer), StdIn);
|
source_input := OpenToRead(command_line^.input);
|
||||||
|
|
||||||
transpile(ADR(lexer));
|
IF IsNoError(source_input) = FALSE THEN
|
||||||
|
WriteString(StdErr, 'Fatal error: failed to read the input file "');
|
||||||
|
WriteString(StdErr, command_line^.input);
|
||||||
|
WriteString(StdErr, '".');
|
||||||
|
WriteLine(StdErr);
|
||||||
|
|
||||||
lexer_destroy(ADR(lexer))
|
ExitOnHalt(2)
|
||||||
|
END;
|
||||||
|
IF IsNoError(source_input) THEN
|
||||||
|
lexer_initialize(ADR(lexer), source_input);
|
||||||
|
|
||||||
|
transpile(ADR(lexer), StdOut);
|
||||||
|
|
||||||
|
lexer_destroy(ADR(lexer));
|
||||||
|
|
||||||
|
Close(source_input)
|
||||||
|
END
|
||||||
|
END compile_from_stream;
|
||||||
|
BEGIN
|
||||||
|
ExitOnHalt(0);
|
||||||
|
command_line := parse_command_line();
|
||||||
|
|
||||||
|
IF command_line <> NIL THEN
|
||||||
|
compile_from_stream()
|
||||||
|
END;
|
||||||
|
IF command_line = NIL THEN
|
||||||
|
ExitOnHalt(1)
|
||||||
|
END;
|
||||||
|
HALT()
|
||||||
END Compiler.
|
END Compiler.
|
||||||
|
@ -2,6 +2,8 @@ DEFINITION MODULE Lexer;
|
|||||||
|
|
||||||
FROM FIO IMPORT File;
|
FROM FIO IMPORT File;
|
||||||
|
|
||||||
|
FROM Common IMPORT Identifier;
|
||||||
|
|
||||||
TYPE
|
TYPE
|
||||||
PLexerBuffer = POINTER TO CHAR;
|
PLexerBuffer = POINTER TO CHAR;
|
||||||
Lexer = RECORD
|
Lexer = RECORD
|
||||||
@ -81,7 +83,8 @@ TYPE
|
|||||||
LexerToken = RECORD
|
LexerToken = RECORD
|
||||||
CASE kind: LexerKind OF
|
CASE kind: LexerKind OF
|
||||||
lexerKindBoolean: booleanKind: BOOLEAN |
|
lexerKindBoolean: booleanKind: BOOLEAN |
|
||||||
lexerKindIdentifier: identifierKind: ARRAY[1..256] OF CHAR
|
lexerKindIdentifier: identifierKind: Identifier |
|
||||||
|
lexerKindInteger: integerKind: INTEGER
|
||||||
END
|
END
|
||||||
END;
|
END;
|
||||||
PLexerToken = POINTER TO LexerToken;
|
PLexerToken = POINTER TO LexerToken;
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
IMPLEMENTATION MODULE Lexer;
|
IMPLEMENTATION MODULE Lexer;
|
||||||
|
|
||||||
FROM FIO IMPORT ReadNBytes;
|
FROM FIO IMPORT ReadNBytes, StdErr;
|
||||||
FROM SYSTEM IMPORT ADR;
|
FROM SYSTEM IMPORT ADR, TSIZE;
|
||||||
|
|
||||||
|
FROM DynamicStrings IMPORT String, InitStringCharStar, KillString;
|
||||||
|
FROM StringConvert IMPORT StringToInteger;
|
||||||
FROM Storage IMPORT DEALLOCATE, ALLOCATE;
|
FROM Storage IMPORT DEALLOCATE, ALLOCATE;
|
||||||
FROM Strings IMPORT Length;
|
FROM Strings IMPORT Length;
|
||||||
FROM MemUtils IMPORT MemCopy, MemZero;
|
FROM MemUtils IMPORT MemCopy, MemZero;
|
||||||
@ -210,7 +212,7 @@ BEGIN
|
|||||||
i := i + 1
|
i := i + 1
|
||||||
END
|
END
|
||||||
END initialize_classification;
|
END initialize_classification;
|
||||||
PROCEDURE compare_keyword(Keyword: ARRAY OF CHAR; TokenStart: PLexerBuffer; TokenEnd: PLexerBuffer): BOOLEAN;
|
PROCEDURE compare_keyword(Keyword: ARRAY OF CHAR; TokenStart: PLexerBuffer; TokenEnd: PLexerBuffer): BOOLEAN;
|
||||||
VAR
|
VAR
|
||||||
result: BOOLEAN;
|
result: BOOLEAN;
|
||||||
index: CARDINAL;
|
index: CARDINAL;
|
||||||
@ -227,18 +229,18 @@ BEGIN
|
|||||||
RETURN result
|
RETURN result
|
||||||
END compare_keyword;
|
END compare_keyword;
|
||||||
(* Reached the end of file. *)
|
(* Reached the end of file. *)
|
||||||
PROCEDURE transition_action_eof(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_eof(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
token^.kind := lexerKindEof
|
token^.kind := lexerKindEof
|
||||||
END transition_action_eof;
|
END transition_action_eof;
|
||||||
(* 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. *)
|
||||||
PROCEDURE transition_action_accumulate(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_accumulate(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
INC(lexer^.Current)
|
INC(lexer^.Current)
|
||||||
END transition_action_accumulate;
|
END transition_action_accumulate;
|
||||||
(* 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. *)
|
||||||
PROCEDURE transition_action_finalize(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_finalize(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
IF lexer^.Start^ = ':' THEN
|
IF lexer^.Start^ = ':' THEN
|
||||||
token^.kind := lexerKindColon
|
token^.kind := lexerKindColon
|
||||||
@ -260,7 +262,7 @@ BEGIN
|
|||||||
END
|
END
|
||||||
END transition_action_finalize;
|
END transition_action_finalize;
|
||||||
(* An action for tokens containing multiple characters. *)
|
(* An action for tokens containing multiple characters. *)
|
||||||
PROCEDURE transition_action_composite(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_composite(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
IF lexer^.Start^ = '<' THEN
|
IF lexer^.Start^ = '<' THEN
|
||||||
IF lexer^.Current^ = '>' THEN
|
IF lexer^.Current^ = '>' THEN
|
||||||
@ -285,13 +287,13 @@ BEGIN
|
|||||||
INC(lexer^.Current)
|
INC(lexer^.Current)
|
||||||
END transition_action_composite;
|
END transition_action_composite;
|
||||||
(* Skip a space. *)
|
(* Skip a space. *)
|
||||||
PROCEDURE transition_action_skip(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_skip(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
INC(lexer^.Current);
|
INC(lexer^.Current);
|
||||||
INC(lexer^.Start)
|
INC(lexer^.Start)
|
||||||
END transition_action_skip;
|
END transition_action_skip;
|
||||||
(* Delimited string action. *)
|
(* Delimited string action. *)
|
||||||
PROCEDURE transition_action_delimited(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_delimited(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
IF lexer^.Start^ = '(' THEN
|
IF lexer^.Start^ = '(' THEN
|
||||||
token^.kind := lexerKindComment
|
token^.kind := lexerKindComment
|
||||||
@ -305,7 +307,7 @@ BEGIN
|
|||||||
INC(lexer^.Current)
|
INC(lexer^.Current)
|
||||||
END transition_action_delimited;
|
END transition_action_delimited;
|
||||||
(* Finalize keyword OR identifier. *)
|
(* Finalize keyword OR identifier. *)
|
||||||
PROCEDURE transition_action_key_id(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_key_id(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
token^.kind := lexerKindIdentifier;
|
token^.kind := lexerKindIdentifier;
|
||||||
|
|
||||||
@ -410,7 +412,7 @@ BEGIN
|
|||||||
END transition_action_key_id;
|
END transition_action_key_id;
|
||||||
(* Action for tokens containing only one character. The character cannot be
|
(* Action for tokens containing only one character. The character cannot be
|
||||||
* followed by other characters forming a composite token. *)
|
* followed by other characters forming a composite token. *)
|
||||||
PROCEDURE transition_action_single(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_single(lexer: PLexer; token: PLexerToken);
|
||||||
BEGIN
|
BEGIN
|
||||||
IF lexer^.Current^ = '&' THEN
|
IF lexer^.Current^ = '&' THEN
|
||||||
token^.kind := lexerKindAnd
|
token^.kind := lexerKindAnd
|
||||||
@ -457,11 +459,23 @@ BEGIN
|
|||||||
INC(lexer^.Current)
|
INC(lexer^.Current)
|
||||||
END transition_action_single;
|
END transition_action_single;
|
||||||
(* Handle an integer literal. *)
|
(* Handle an integer literal. *)
|
||||||
PROCEDURE transition_action_integer(lexer: PLexer; token: PLexerToken);
|
PROCEDURE transition_action_integer(lexer: PLexer; token: PLexerToken);
|
||||||
|
VAR
|
||||||
|
buffer: String;
|
||||||
|
integer_length: CARDINAL;
|
||||||
|
found: BOOLEAN;
|
||||||
BEGIN
|
BEGIN
|
||||||
token^.kind := lexerKindInteger
|
token^.kind := lexerKindInteger;
|
||||||
|
|
||||||
|
integer_length := lexer^.Current - lexer^.Start;
|
||||||
|
MemZero(ADR(token^.identifierKind), TSIZE(Identifier));
|
||||||
|
MemCopy(lexer^.Start, integer_length, ADR(token^.identifierKind[1]));
|
||||||
|
|
||||||
|
buffer := InitStringCharStar(ADR(token^.identifierKind[1]));
|
||||||
|
token^.integerKind := StringToInteger(buffer, 10, found);
|
||||||
|
buffer := KillString(buffer)
|
||||||
END transition_action_integer;
|
END transition_action_integer;
|
||||||
PROCEDURE set_default_transition(CurrentState: TransitionState; DefaultAction: TransitionAction; NextState: TransitionState);
|
PROCEDURE set_default_transition(CurrentState: TransitionState; DefaultAction: TransitionAction; NextState: TransitionState);
|
||||||
VAR
|
VAR
|
||||||
DefaultTransition: Transition;
|
DefaultTransition: Transition;
|
||||||
BEGIN
|
BEGIN
|
||||||
@ -744,7 +758,7 @@ BEGIN
|
|||||||
transitions[ORD(transitionStateDecimalSuffix) + 1][ORD(transitionClassX) + 1].Action := NIL;
|
transitions[ORD(transitionStateDecimalSuffix) + 1][ORD(transitionClassX) + 1].Action := NIL;
|
||||||
transitions[ORD(transitionStateDecimalSuffix) + 1][ORD(transitionClassX) + 1].NextState := transitionStateEnd
|
transitions[ORD(transitionStateDecimalSuffix) + 1][ORD(transitionClassX) + 1].NextState := transitionStateEnd
|
||||||
END initialize_transitions;
|
END initialize_transitions;
|
||||||
PROCEDURE lexer_initialize(lexer: PLexer; Input: File);
|
PROCEDURE lexer_initialize(lexer: PLexer; Input: File);
|
||||||
BEGIN
|
BEGIN
|
||||||
lexer^.Input := Input;
|
lexer^.Input := Input;
|
||||||
lexer^.Length := 0;
|
lexer^.Length := 0;
|
||||||
|
59
source/Parser.def
Normal file
59
source/Parser.def
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
DEFINITION MODULE Parser;
|
||||||
|
|
||||||
|
FROM Common IMPORT Identifier, PIdentifier;
|
||||||
|
|
||||||
|
TYPE
|
||||||
|
AstConstantDeclaration = RECORD
|
||||||
|
END;
|
||||||
|
PAstConstantDeclaration = POINTER TO AstConstantDeclaration;
|
||||||
|
PPAstConstantDeclaration = POINTER TO PAstConstantDeclaration;
|
||||||
|
|
||||||
|
AstFieldDeclaration = RECORD
|
||||||
|
field_name: Identifier;
|
||||||
|
field_type: PAstTypeExpression
|
||||||
|
END;
|
||||||
|
PAstFieldDeclaration = POINTER TO AstFieldDeclaration;
|
||||||
|
|
||||||
|
AstTypeExpressionKind = (
|
||||||
|
astTypeExpressionKindNamed,
|
||||||
|
astTypeExpressionKindRecord,
|
||||||
|
astTypeExpressionKindEnumeration,
|
||||||
|
astTypeExpressionKindArray,
|
||||||
|
astTypeExpressionKindPointer,
|
||||||
|
astTypeExpressionKindProcedure
|
||||||
|
);
|
||||||
|
AstTypeExpression = RECORD
|
||||||
|
CASE kind: AstTypeExpressionKind OF
|
||||||
|
astTypeExpressionKindNamed: name: Identifier |
|
||||||
|
astTypeExpressionKindEnumeration: cases: PIdentifier |
|
||||||
|
astTypeExpressionKindPointer: target: PAstTypeExpression |
|
||||||
|
astTypeExpressionKindRecord: fields: PAstFieldDeclaration |
|
||||||
|
astTypeExpressionKindArray:
|
||||||
|
base: PAstTypeExpression;
|
||||||
|
length: CARDINAL |
|
||||||
|
astTypeExpressionKindProcedure: parameters: PPAstTypeExpression
|
||||||
|
END
|
||||||
|
END;
|
||||||
|
PAstTypeExpression = POINTER TO AstTypeExpression;
|
||||||
|
PPAstTypeExpression = POINTER TO PAstTypeExpression;
|
||||||
|
|
||||||
|
AstTypeDeclaration = RECORD
|
||||||
|
identifier: Identifier;
|
||||||
|
type_expression: PAstTypeExpression
|
||||||
|
END;
|
||||||
|
PAstTypeDeclaration = POINTER TO AstTypeDeclaration;
|
||||||
|
PPAstTypeDeclaration = POINTER TO PAstTypeDeclaration;
|
||||||
|
|
||||||
|
AstVariableDeclaration = RECORD
|
||||||
|
END;
|
||||||
|
PAstVariableDeclaration = POINTER TO AstVariableDeclaration;
|
||||||
|
PPAstVariableDeclaration = POINTER TO PAstVariableDeclaration;
|
||||||
|
|
||||||
|
AstModule = RECORD
|
||||||
|
constants: PPAstConstantDeclaration;
|
||||||
|
types: PPAstTypeDeclaration;
|
||||||
|
variables: PPAstVariableDeclaration
|
||||||
|
END;
|
||||||
|
PAstModule = POINTER TO AstModule;
|
||||||
|
|
||||||
|
END Parser.
|
3
source/Parser.mod
Normal file
3
source/Parser.mod
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
IMPLEMENTATION MODULE Parser;
|
||||||
|
|
||||||
|
END Parser.
|
@ -1,7 +1,17 @@
|
|||||||
DEFINITION MODULE Transpiler;
|
DEFINITION MODULE Transpiler;
|
||||||
|
|
||||||
FROM Lexer IMPORT PLexer;
|
FROM FIO IMPORT File;
|
||||||
|
|
||||||
PROCEDURE transpile(ALexer: PLexer);
|
FROM Lexer IMPORT PLexer, Lexer;
|
||||||
|
|
||||||
|
TYPE
|
||||||
|
TranspilerContext = RECORD
|
||||||
|
indentation: CARDINAL;
|
||||||
|
output: File;
|
||||||
|
lexer: PLexer
|
||||||
|
END;
|
||||||
|
PTranspilerContext = POINTER TO TranspilerContext;
|
||||||
|
|
||||||
|
PROCEDURE transpile(lexer: PLexer; output: File);
|
||||||
|
|
||||||
END Transpiler.
|
END Transpiler.
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user