Add a command line parsing procedure
This commit is contained in:
parent
6e415e474f
commit
b093994027
17
Rakefile
17
Rakefile
@ -44,11 +44,12 @@ end
|
|||||||
.partition { |f| f.end_with? '.elna' }
|
.partition { |f| f.end_with? '.elna' }
|
||||||
|
|
||||||
File.open t.name, 'w' do |output|
|
File.open t.name, 'w' do |output|
|
||||||
puts
|
compiler_command = compiler + sources
|
||||||
puts(compiler * ' ')
|
|
||||||
|
|
||||||
Open3.popen2(*compiler) do |cl_in, cl_out|
|
puts
|
||||||
cl_in.write File.read(*sources)
|
puts(compiler_command * ' ')
|
||||||
|
|
||||||
|
Open3.popen2(*compiler_command) do |cl_in, cl_out|
|
||||||
cl_in.close
|
cl_in.close
|
||||||
|
|
||||||
IO.copy_stream cl_out, output
|
IO.copy_stream cl_out, output
|
||||||
@ -87,11 +88,11 @@ task default: 'source/Compiler.elna'
|
|||||||
task :default do |t|
|
task :default do |t|
|
||||||
exe, previous_output, source = t.prerequisites
|
exe, previous_output, source = t.prerequisites
|
||||||
|
|
||||||
cat_arguments = ['cat', source]
|
exe_arguments = [exe, source]
|
||||||
diff_arguments = ['diff', '-Nur', '--text', previous_output, '-']
|
diff_arguments = ['diff', '-Nur', '--text', previous_output, '-']
|
||||||
|
|
||||||
puts [cat_arguments * ' ', exe, diff_arguments * ' '].join(' | ')
|
puts [exe, diff_arguments * ' '].join(' | ')
|
||||||
Open3.pipeline(cat_arguments, exe, diff_arguments)
|
Open3.pipeline exe_arguments, diff_arguments
|
||||||
end
|
end
|
||||||
|
|
||||||
task :backport do
|
task :backport do
|
||||||
@ -104,7 +105,7 @@ task :backport do
|
|||||||
source
|
source
|
||||||
.gsub(/^(var|type|const|begin)/) { |match| match.upcase }
|
.gsub(/^(var|type|const|begin)/) { |match| match.upcase }
|
||||||
.gsub(/^[[:alnum:]]* ?module/) { |match| match.upcase }
|
.gsub(/^[[:alnum:]]* ?module/) { |match| match.upcase }
|
||||||
.gsub(/\b(record|nil|or)\b/) { |match| match.upcase }
|
.gsub(/\b(record|nil|or|false|true)\b/) { |match| match.upcase }
|
||||||
.gsub(/proc\(/, 'PROCEDURE(')
|
.gsub(/proc\(/, 'PROCEDURE(')
|
||||||
.gsub(/ & /, ' AND ')
|
.gsub(/ & /, ' AND ')
|
||||||
.gsub(/ -> /, ': ')
|
.gsub(/ -> /, ': ')
|
||||||
|
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.
|
75
source/CommandLineInterface.elna
Normal file
75
source/CommandLineInterface.elna
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
proc 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()) & (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) & (Length(result^.input) = 0) then
|
||||||
|
WriteString(StdErr, 'Fatal error: no input files.');
|
||||||
|
WriteLine(StdErr);
|
||||||
|
result := nil
|
||||||
|
end;
|
||||||
|
|
||||||
|
return result
|
||||||
|
end;
|
||||||
|
|
||||||
|
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.elna
Normal file
3
source/Common.elna
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
implementation module Common;
|
||||||
|
|
||||||
|
end Common.
|
@ -1,18 +1,51 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
proc compile_from_stream();
|
||||||
var
|
var
|
||||||
lexer: Lexer;
|
lexer: Lexer;
|
||||||
|
source_input: File;
|
||||||
|
begin
|
||||||
|
source_input := OpenToRead(command_line^.input);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
lexer_initialize(ADR(lexer), StdIn);
|
ExitOnHalt(0);
|
||||||
|
command_line := parse_command_line();
|
||||||
|
|
||||||
transpile(ADR(lexer));
|
if command_line <> nil then
|
||||||
|
compile_from_stream()
|
||||||
lexer_destroy(ADR(lexer))
|
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,7 @@ 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
|
||||||
END
|
END
|
||||||
END;
|
END;
|
||||||
PLexerToken = POINTER TO LexerToken;
|
PLexerToken = POINTER TO LexerToken;
|
||||||
|
@ -217,7 +217,7 @@ var
|
|||||||
index: CARDINAL;
|
index: CARDINAL;
|
||||||
begin
|
begin
|
||||||
index := 0;
|
index := 0;
|
||||||
result := TRUE;
|
result := true;
|
||||||
|
|
||||||
while (index < Length(Keyword)) & (TokenStart <> TokenEnd) & result DO
|
while (index < Length(Keyword)) & (TokenStart <> TokenEnd) & result DO
|
||||||
result := (Keyword[index] = TokenStart^) or (Lower(Keyword[index]) = TokenStart^);
|
result := (Keyword[index] = TokenStart^) or (Lower(Keyword[index]) = TokenStart^);
|
||||||
@ -409,11 +409,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
if compare_keyword('TRUE', lexer^.Start, lexer^.Current) then
|
if compare_keyword('TRUE', lexer^.Start, lexer^.Current) then
|
||||||
token^.kind := lexerKindBoolean;
|
token^.kind := lexerKindBoolean;
|
||||||
token^.booleanKind := TRUE
|
token^.booleanKind := true
|
||||||
end;
|
end;
|
||||||
if compare_keyword('FALSE', lexer^.Start, lexer^.Current) then
|
if compare_keyword('FALSE', lexer^.Start, lexer^.Current) then
|
||||||
token^.kind := lexerKindBoolean;
|
token^.kind := lexerKindBoolean;
|
||||||
token^.booleanKind := FALSE
|
token^.booleanKind := false
|
||||||
end
|
end
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
46
source/Parser.def
Normal file
46
source/Parser.def
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
DEFINITION MODULE Parser;
|
||||||
|
|
||||||
|
FROM Common IMPORT Identifier, PIdentifier;
|
||||||
|
|
||||||
|
TYPE
|
||||||
|
AstConstantDeclaration = RECORD
|
||||||
|
END;
|
||||||
|
PAstConstantDeclaration = POINTER TO AstConstantDeclaration;
|
||||||
|
PPAstConstantDeclaration = POINTER TO PAstConstantDeclaration;
|
||||||
|
|
||||||
|
AstTypeExpressionKind = (
|
||||||
|
astTypeExpressionKindNamed,
|
||||||
|
astTypeExpressionKindRecord,
|
||||||
|
astTypeExpressionKindEnumeration,
|
||||||
|
astTypeExpressionKindArray,
|
||||||
|
astTypeExpressionKindPointer,
|
||||||
|
astTypeExpressionKindProcedure
|
||||||
|
);
|
||||||
|
AstTypeExpression = RECORD
|
||||||
|
CASE kind: AstTypeExpressionKind OF
|
||||||
|
astTypeExpressionKindNamed: name: Identifier |
|
||||||
|
astTypeExpressionKindEnumeration: cases: PIdentifier
|
||||||
|
END
|
||||||
|
END;
|
||||||
|
PAstTypeExpression = POINTER TO AstTypeExpression;
|
||||||
|
|
||||||
|
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.elna
Normal file
3
source/Parser.elna
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