Repository: sigasi/SigasiProjectCreator

Issue:
Support .f files
EDA tools may take a list of command line options from a file. Typically, `-f <options_file>` is used to specify the file, and the options file has a `.f` extension. In their simplest form, `.f` files contain a list of design files, but other command line options may be present as well. 

The goal is to use .f files to create a Sigasi project.

Discussion:
felix-sigasi: Am I correct in observing everything in `src/SigasiProjectCreator/DotF` is generated?
wmeeus: @felix-sigasi most of those files are generated, but `DotFfileParser.py`, `DotF.g4` and `parseFile.py` are not generated.
felix-sigasi: Could you link me to the standardized grammar of this "DotF" language? I'm finding Forth and Forthran but that's what this is parsing.
tivervac: > Could you link me to the standardized grammar of this "DotF" language? I'm finding Forth and Forthran but that's what this is parsing.

That's the fun part. `.f` has no standard, yet it is used very often in the industry. Sadly it's thus standard-by-implementation
felix-sigasi: I see. Grammer changes LGTM then.

Patch:
diff --git a/src/SigasiProjectCreator/DotF/DotF.g4 b/src/SigasiProjectCreator/DotF/DotF.g4
index bfa5be2..b41f9d4 100644
--- a/src/SigasiProjectCreator/DotF/DotF.g4
+++ b/src/SigasiProjectCreator/DotF/DotF.g4
@@ -13,12 +13,9 @@ cmd_options
 	;
 
 cmd_option
-	: filename NL
-	| filename filecont cmd_option
-	| plus_option plus_option_arg* NL
-	| plus_option plus_option_arg* continuation cmd_option
-	| dash_option NL
-	| dash_option continuation cmd_option
+	: plus_option plus_option_arg?
+	| dash_option filename?
+	| filename
 	| NL
 	;
 
@@ -27,11 +24,11 @@ plus_option_arg: PLUS_OPTION;
 dash_option: DASH_OPTION;
 
 PLUS_OPTION
-	: '+' ~[+\\\n]+
+	: '+' ~[ +\\\n]+
 	;
 
 DASH_OPTION
-	: '-' ~[\\\n]+
+	: '-' ~[ \\\n]+
 	;
 
 filename
@@ -52,9 +49,9 @@ FILEPATH: FILEPATH_CHAR ('-' | FILEPATH_CHAR)* ;
 
 QUOTED_FILEPATH: '"' (':' | FILEPATH_CHAR) ('-' | ':' | ' ' | FILEPATH_CHAR)* '"' ;
 
-fragment FILEPATH_CHAR: [a-zA-Z0-9_/\\.${}*] ;
+fragment FILEPATH_CHAR: [a-zA-Z0-9_/\\.${}()*] ;
 
-CONT : WS '\\';
+CONT : WS '\\' -> skip;
 
 LT : [.,?!] ;
 
diff --git a/src/SigasiProjectCreator/DotF/DotF.interp b/src/SigasiProjectCreator/DotF/DotF.interp
index 8870dd8..26fcfd7 100644
--- a/src/SigasiProjectCreator/DotF/DotF.interp
+++ b/src/SigasiProjectCreator/DotF/DotF.interp
@@ -44,4 +44,4 @@ filecont
 
 
 atn:
-[4, 1, 14, 76, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 1, 0, 5, 0, 18, 8, 0, 10, 0, 12, 0, 21, 9, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 32, 8, 1, 10, 1, 12, 1, 35, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 5, 1, 41, 8, 1, 10, 1, 12, 1, 44, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 57, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 3, 6, 69, 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 0, 0, 8, 0, 2, 4, 6, 8, 10, 12, 14, 0, 1, 1, 0, 6, 7, 77, 0, 19, 1, 0, 0, 0, 2, 56, 1, 0, 0, 0, 4, 58, 1, 0, 0, 0, 6, 60, 1, 0, 0, 0, 8, 62, 1, 0, 0, 0, 10, 64, 1, 0, 0, 0, 12, 66, 1, 0, 0, 0, 14, 72, 1, 0, 0, 0, 16, 18, 3, 2, 1, 0, 17, 16, 1, 0, 0, 0, 18, 21, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 1, 1, 0, 0, 0, 21, 19, 1, 0, 0, 0, 22, 23, 3, 10, 5, 0, 23, 24, 5, 11, 0, 0, 24, 57, 1, 0, 0, 0, 25, 26, 3, 10, 5, 0, 26, 27, 3, 14, 7, 0, 27, 28, 3, 2, 1, 0, 28, 57, 1, 0, 0, 0, 29, 33, 3, 4, 2, 0, 30, 32, 3, 6, 3, 0, 31, 30, 1, 0, 0, 0, 32, 35, 1, 0, 0, 0, 33, 31, 1, 0, 0, 0, 33, 34, 1, 0, 0, 0, 34, 36, 1, 0, 0, 0, 35, 33, 1, 0, 0, 0, 36, 37, 5, 11, 0, 0, 37, 57, 1, 0, 0, 0, 38, 42, 3, 4, 2, 0, 39, 41, 3, 6, 3, 0, 40, 39, 1, 0, 0, 0, 41, 44, 1, 0, 0, 0, 42, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 45, 1, 0, 0, 0, 44, 42, 1, 0, 0, 0, 45, 46, 3, 12, 6, 0, 46, 47, 3, 2, 1, 0, 47, 57, 1, 0, 0, 0, 48, 49, 3, 8, 4, 0, 49, 50, 5, 11, 0, 0, 50, 57, 1, 0, 0, 0, 51, 52, 3, 8, 4, 0, 52, 53, 3, 12, 6, 0, 53, 54, 3, 2, 1, 0, 54, 57, 1, 0, 0, 0, 55, 57, 5, 11, 0, 0, 56, 22, 1, 0, 0, 0, 56, 25, 1, 0, 0, 0, 56, 29, 1, 0, 0, 0, 56, 38, 1, 0, 0, 0, 56, 48, 1, 0, 0, 0, 56, 51, 1, 0, 0, 0, 56, 55, 1, 0, 0, 0, 57, 3, 1, 0, 0, 0, 58, 59, 5, 2, 0, 0, 59, 5, 1, 0, 0, 0, 60, 61, 5, 2, 0, 0, 61, 7, 1, 0, 0, 0, 62, 63, 5, 3, 0, 0, 63, 9, 1, 0, 0, 0, 64, 65, 7, 0, 0, 0, 65, 11, 1, 0, 0, 0, 66, 68, 5, 1, 0, 0, 67, 69, 5, 10, 0, 0, 68, 67, 1, 0, 0, 0, 68, 69, 1, 0, 0, 0, 69, 70, 1, 0, 0, 0, 70, 71, 5, 11, 0, 0, 71, 13, 1, 0, 0, 0, 72, 73, 5, 8, 0, 0, 73, 74, 5, 11, 0, 0, 74, 15, 1, 0, 0, 0, 5, 19, 33, 42, 56, 68]
\ No newline at end of file
+[4, 1, 14, 52, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 1, 0, 5, 0, 18, 8, 0, 10, 0, 12, 0, 21, 9, 0, 1, 1, 1, 1, 3, 1, 25, 8, 1, 1, 1, 1, 1, 3, 1, 29, 8, 1, 1, 1, 1, 1, 3, 1, 33, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 3, 6, 45, 8, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 0, 0, 8, 0, 2, 4, 6, 8, 10, 12, 14, 0, 1, 1, 0, 6, 7, 50, 0, 19, 1, 0, 0, 0, 2, 32, 1, 0, 0, 0, 4, 34, 1, 0, 0, 0, 6, 36, 1, 0, 0, 0, 8, 38, 1, 0, 0, 0, 10, 40, 1, 0, 0, 0, 12, 42, 1, 0, 0, 0, 14, 48, 1, 0, 0, 0, 16, 18, 3, 2, 1, 0, 17, 16, 1, 0, 0, 0, 18, 21, 1, 0, 0, 0, 19, 17, 1, 0, 0, 0, 19, 20, 1, 0, 0, 0, 20, 1, 1, 0, 0, 0, 21, 19, 1, 0, 0, 0, 22, 24, 3, 4, 2, 0, 23, 25, 3, 6, 3, 0, 24, 23, 1, 0, 0, 0, 24, 25, 1, 0, 0, 0, 25, 33, 1, 0, 0, 0, 26, 28, 3, 8, 4, 0, 27, 29, 3, 10, 5, 0, 28, 27, 1, 0, 0, 0, 28, 29, 1, 0, 0, 0, 29, 33, 1, 0, 0, 0, 30, 33, 3, 10, 5, 0, 31, 33, 5, 11, 0, 0, 32, 22, 1, 0, 0, 0, 32, 26, 1, 0, 0, 0, 32, 30, 1, 0, 0, 0, 32, 31, 1, 0, 0, 0, 33, 3, 1, 0, 0, 0, 34, 35, 5, 2, 0, 0, 35, 5, 1, 0, 0, 0, 36, 37, 5, 2, 0, 0, 37, 7, 1, 0, 0, 0, 38, 39, 5, 3, 0, 0, 39, 9, 1, 0, 0, 0, 40, 41, 7, 0, 0, 0, 41, 11, 1, 0, 0, 0, 42, 44, 5, 1, 0, 0, 43, 45, 5, 10, 0, 0, 44, 43, 1, 0, 0, 0, 44, 45, 1, 0, 0, 0, 45, 46, 1, 0, 0, 0, 46, 47, 5, 11, 0, 0, 47, 13, 1, 0, 0, 0, 48, 49, 5, 8, 0, 0, 49, 50, 5, 11, 0, 0, 50, 15, 1, 0, 0, 0, 5, 19, 24, 28, 32, 44]
\ No newline at end of file
diff --git a/src/SigasiProjectCreator/DotF/DotFLexer.interp b/src/SigasiProjectCreator/DotF/DotFLexer.interp
index f5d4886..f33b43e 100644
--- a/src/SigasiProjectCreator/DotF/DotFLexer.interp
+++ b/src/SigasiProjectCreator/DotF/DotFLexer.interp
@@ -57,4 +57,4 @@ mode names:
 DEFAULT_MODE
 
 atn:
-[4, 0, 14, 128, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 1, 0, 1, 1, 1, 1, 4, 1, 36, 8, 1, 11, 1, 12, 1, 37, 1, 2, 1, 2, 4, 2, 42, 8, 2, 11, 2, 12, 2, 43, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 50, 8, 3, 10, 3, 12, 3, 53, 9, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 64, 8, 4, 10, 4, 12, 4, 67, 9, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 5, 5, 74, 8, 5, 10, 5, 12, 5, 77, 9, 5, 1, 6, 1, 6, 1, 6, 3, 6, 82, 8, 6, 1, 6, 1, 6, 5, 6, 86, 8, 6, 10, 6, 12, 6, 89, 9, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 4, 10, 101, 8, 10, 11, 10, 12, 10, 102, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 5, 13, 113, 8, 13, 10, 13, 12, 13, 116, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 122, 8, 14, 10, 14, 12, 14, 125, 9, 14, 1, 14, 1, 14, 1, 51, 0, 15, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 0, 17, 8, 19, 9, 21, 10, 23, 11, 25, 12, 27, 13, 29, 14, 1, 0, 8, 3, 0, 10, 10, 43, 43, 92, 92, 2, 0, 10, 10, 92, 92, 1, 0, 10, 10, 3, 0, 32, 32, 45, 45, 58, 58, 8, 0, 36, 36, 42, 42, 46, 57, 65, 90, 92, 92, 95, 95, 97, 123, 125, 125, 4, 0, 33, 33, 44, 44, 46, 46, 63, 63, 3, 0, 9, 9, 13, 13, 32, 32, 1, 0, 92, 92, 138, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 1, 31, 1, 0, 0, 0, 3, 33, 1, 0, 0, 0, 5, 39, 1, 0, 0, 0, 7, 45, 1, 0, 0, 0, 9, 59, 1, 0, 0, 0, 11, 70, 1, 0, 0, 0, 13, 78, 1, 0, 0, 0, 15, 92, 1, 0, 0, 0, 17, 94, 1, 0, 0, 0, 19, 97, 1, 0, 0, 0, 21, 100, 1, 0, 0, 0, 23, 106, 1, 0, 0, 0, 25, 108, 1, 0, 0, 0, 27, 110, 1, 0, 0, 0, 29, 119, 1, 0, 0, 0, 31, 32, 5, 92, 0, 0, 32, 2, 1, 0, 0, 0, 33, 35, 5, 43, 0, 0, 34, 36, 8, 0, 0, 0, 35, 34, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 4, 1, 0, 0, 0, 39, 41, 5, 45, 0, 0, 40, 42, 8, 1, 0, 0, 41, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 6, 1, 0, 0, 0, 45, 46, 5, 47, 0, 0, 46, 47, 5, 42, 0, 0, 47, 51, 1, 0, 0, 0, 48, 50, 9, 0, 0, 0, 49, 48, 1, 0, 0, 0, 50, 53, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 51, 49, 1, 0, 0, 0, 52, 54, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 54, 55, 5, 42, 0, 0, 55, 56, 5, 47, 0, 0, 56, 57, 1, 0, 0, 0, 57, 58, 6, 3, 0, 0, 58, 8, 1, 0, 0, 0, 59, 60, 5, 47, 0, 0, 60, 61, 5, 47, 0, 0, 61, 65, 1, 0, 0, 0, 62, 64, 8, 2, 0, 0, 63, 62, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 68, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 69, 6, 4, 0, 0, 69, 10, 1, 0, 0, 0, 70, 75, 3, 15, 7, 0, 71, 74, 5, 45, 0, 0, 72, 74, 3, 15, 7, 0, 73, 71, 1, 0, 0, 0, 73, 72, 1, 0, 0, 0, 74, 77, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 12, 1, 0, 0, 0, 77, 75, 1, 0, 0, 0, 78, 81, 5, 34, 0, 0, 79, 82, 5, 58, 0, 0, 80, 82, 3, 15, 7, 0, 81, 79, 1, 0, 0, 0, 81, 80, 1, 0, 0, 0, 82, 87, 1, 0, 0, 0, 83, 86, 7, 3, 0, 0, 84, 86, 3, 15, 7, 0, 85, 83, 1, 0, 0, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 90, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 91, 5, 34, 0, 0, 91, 14, 1, 0, 0, 0, 92, 93, 7, 4, 0, 0, 93, 16, 1, 0, 0, 0, 94, 95, 3, 21, 10, 0, 95, 96, 5, 92, 0, 0, 96, 18, 1, 0, 0, 0, 97, 98, 7, 5, 0, 0, 98, 20, 1, 0, 0, 0, 99, 101, 7, 6, 0, 0, 100, 99, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 100, 1, 0, 0, 0, 102, 103, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 105, 6, 10, 0, 0, 105, 22, 1, 0, 0, 0, 106, 107, 7, 2, 0, 0, 107, 24, 1, 0, 0, 0, 108, 109, 7, 7, 0, 0, 109, 26, 1, 0, 0, 0, 110, 114, 5, 35, 0, 0, 111, 113, 8, 2, 0, 0, 112, 111, 1, 0, 0, 0, 113, 116, 1, 0, 0, 0, 114, 112, 1, 0, 0, 0, 114, 115, 1, 0, 0, 0, 115, 117, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 117, 118, 6, 13, 0, 0, 118, 28, 1, 0, 0, 0, 119, 123, 5, 33, 0, 0, 120, 122, 8, 2, 0, 0, 121, 120, 1, 0, 0, 0, 122, 125, 1, 0, 0, 0, 123, 121, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 126, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 126, 127, 6, 14, 0, 0, 127, 30, 1, 0, 0, 0, 13, 0, 37, 43, 51, 65, 73, 75, 81, 85, 87, 102, 114, 123, 1, 6, 0, 0]
\ No newline at end of file
+[4, 0, 14, 130, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 1, 0, 1, 0, 1, 1, 1, 1, 4, 1, 36, 8, 1, 11, 1, 12, 1, 37, 1, 2, 1, 2, 4, 2, 42, 8, 2, 11, 2, 12, 2, 43, 1, 3, 1, 3, 1, 3, 1, 3, 5, 3, 50, 8, 3, 10, 3, 12, 3, 53, 9, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 4, 5, 4, 64, 8, 4, 10, 4, 12, 4, 67, 9, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 5, 5, 74, 8, 5, 10, 5, 12, 5, 77, 9, 5, 1, 6, 1, 6, 1, 6, 3, 6, 82, 8, 6, 1, 6, 1, 6, 5, 6, 86, 8, 6, 10, 6, 12, 6, 89, 9, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 4, 10, 103, 8, 10, 11, 10, 12, 10, 104, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 5, 13, 115, 8, 13, 10, 13, 12, 13, 118, 9, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 124, 8, 14, 10, 14, 12, 14, 127, 9, 14, 1, 14, 1, 14, 1, 51, 0, 15, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 0, 17, 8, 19, 9, 21, 10, 23, 11, 25, 12, 27, 13, 29, 14, 1, 0, 8, 4, 0, 10, 10, 32, 32, 43, 43, 92, 92, 3, 0, 10, 10, 32, 32, 92, 92, 1, 0, 10, 10, 3, 0, 32, 32, 45, 45, 58, 58, 8, 0, 36, 36, 40, 42, 46, 57, 65, 90, 92, 92, 95, 95, 97, 123, 125, 125, 4, 0, 33, 33, 44, 44, 46, 46, 63, 63, 3, 0, 9, 9, 13, 13, 32, 32, 1, 0, 92, 92, 140, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 1, 31, 1, 0, 0, 0, 3, 33, 1, 0, 0, 0, 5, 39, 1, 0, 0, 0, 7, 45, 1, 0, 0, 0, 9, 59, 1, 0, 0, 0, 11, 70, 1, 0, 0, 0, 13, 78, 1, 0, 0, 0, 15, 92, 1, 0, 0, 0, 17, 94, 1, 0, 0, 0, 19, 99, 1, 0, 0, 0, 21, 102, 1, 0, 0, 0, 23, 108, 1, 0, 0, 0, 25, 110, 1, 0, 0, 0, 27, 112, 1, 0, 0, 0, 29, 121, 1, 0, 0, 0, 31, 32, 5, 92, 0, 0, 32, 2, 1, 0, 0, 0, 33, 35, 5, 43, 0, 0, 34, 36, 8, 0, 0, 0, 35, 34, 1, 0, 0, 0, 36, 37, 1, 0, 0, 0, 37, 35, 1, 0, 0, 0, 37, 38, 1, 0, 0, 0, 38, 4, 1, 0, 0, 0, 39, 41, 5, 45, 0, 0, 40, 42, 8, 1, 0, 0, 41, 40, 1, 0, 0, 0, 42, 43, 1, 0, 0, 0, 43, 41, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 6, 1, 0, 0, 0, 45, 46, 5, 47, 0, 0, 46, 47, 5, 42, 0, 0, 47, 51, 1, 0, 0, 0, 48, 50, 9, 0, 0, 0, 49, 48, 1, 0, 0, 0, 50, 53, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 51, 49, 1, 0, 0, 0, 52, 54, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 54, 55, 5, 42, 0, 0, 55, 56, 5, 47, 0, 0, 56, 57, 1, 0, 0, 0, 57, 58, 6, 3, 0, 0, 58, 8, 1, 0, 0, 0, 59, 60, 5, 47, 0, 0, 60, 61, 5, 47, 0, 0, 61, 65, 1, 0, 0, 0, 62, 64, 8, 2, 0, 0, 63, 62, 1, 0, 0, 0, 64, 67, 1, 0, 0, 0, 65, 63, 1, 0, 0, 0, 65, 66, 1, 0, 0, 0, 66, 68, 1, 0, 0, 0, 67, 65, 1, 0, 0, 0, 68, 69, 6, 4, 0, 0, 69, 10, 1, 0, 0, 0, 70, 75, 3, 15, 7, 0, 71, 74, 5, 45, 0, 0, 72, 74, 3, 15, 7, 0, 73, 71, 1, 0, 0, 0, 73, 72, 1, 0, 0, 0, 74, 77, 1, 0, 0, 0, 75, 73, 1, 0, 0, 0, 75, 76, 1, 0, 0, 0, 76, 12, 1, 0, 0, 0, 77, 75, 1, 0, 0, 0, 78, 81, 5, 34, 0, 0, 79, 82, 5, 58, 0, 0, 80, 82, 3, 15, 7, 0, 81, 79, 1, 0, 0, 0, 81, 80, 1, 0, 0, 0, 82, 87, 1, 0, 0, 0, 83, 86, 7, 3, 0, 0, 84, 86, 3, 15, 7, 0, 85, 83, 1, 0, 0, 0, 85, 84, 1, 0, 0, 0, 86, 89, 1, 0, 0, 0, 87, 85, 1, 0, 0, 0, 87, 88, 1, 0, 0, 0, 88, 90, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 90, 91, 5, 34, 0, 0, 91, 14, 1, 0, 0, 0, 92, 93, 7, 4, 0, 0, 93, 16, 1, 0, 0, 0, 94, 95, 3, 21, 10, 0, 95, 96, 5, 92, 0, 0, 96, 97, 1, 0, 0, 0, 97, 98, 6, 8, 0, 0, 98, 18, 1, 0, 0, 0, 99, 100, 7, 5, 0, 0, 100, 20, 1, 0, 0, 0, 101, 103, 7, 6, 0, 0, 102, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 102, 1, 0, 0, 0, 104, 105, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 107, 6, 10, 0, 0, 107, 22, 1, 0, 0, 0, 108, 109, 7, 2, 0, 0, 109, 24, 1, 0, 0, 0, 110, 111, 7, 7, 0, 0, 111, 26, 1, 0, 0, 0, 112, 116, 5, 35, 0, 0, 113, 115, 8, 2, 0, 0, 114, 113, 1, 0, 0, 0, 115, 118, 1, 0, 0, 0, 116, 114, 1, 0, 0, 0, 116, 117, 1, 0, 0, 0, 117, 119, 1, 0, 0, 0, 118, 116, 1, 0, 0, 0, 119, 120, 6, 13, 0, 0, 120, 28, 1, 0, 0, 0, 121, 125, 5, 33, 0, 0, 122, 124, 8, 2, 0, 0, 123, 122, 1, 0, 0, 0, 124, 127, 1, 0, 0, 0, 125, 123, 1, 0, 0, 0, 125, 126, 1, 0, 0, 0, 126, 128, 1, 0, 0, 0, 127, 125, 1, 0, 0, 0, 128, 129, 6, 14, 0, 0, 129, 30, 1, 0, 0, 0, 13, 0, 37, 43, 51, 65, 73, 75, 81, 85, 87, 104, 116, 125, 1, 6, 0, 0]
\ No newline at end of file
diff --git a/src/SigasiProjectCreator/DotF/DotFLexer.py b/src/SigasiProjectCreator/DotF/DotFLexer.py
index 7bfdc24..b72990e 100644
--- a/src/SigasiProjectCreator/DotF/DotFLexer.py
+++ b/src/SigasiProjectCreator/DotF/DotFLexer.py
@@ -1,4 +1,4 @@
-# Generated from DotF.g4 by ANTLR 4.11.1
+# Generated from DotF.g4 by ANTLR 4.13.0
 from antlr4 import *
 from io import StringIO
 import sys
@@ -10,52 +10,53 @@ else:
 
 def serializedATN():
     return [
-        4,0,14,128,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
+        4,0,14,130,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,
         2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,
         13,7,13,2,14,7,14,1,0,1,0,1,1,1,1,4,1,36,8,1,11,1,12,1,37,1,2,1,
         2,4,2,42,8,2,11,2,12,2,43,1,3,1,3,1,3,1,3,5,3,50,8,3,10,3,12,3,53,
         9,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,4,5,4,64,8,4,10,4,12,4,67,
         9,4,1,4,1,4,1,5,1,5,1,5,5,5,74,8,5,10,5,12,5,77,9,5,1,6,1,6,1,6,
         3,6,82,8,6,1,6,1,6,5,6,86,8,6,10,6,12,6,89,9,6,1,6,1,6,1,7,1,7,1,
-        8,1,8,1,8,1,9,1,9,1,10,4,10,101,8,10,11,10,12,10,102,1,10,1,10,1,
-        11,1,11,1,12,1,12,1,13,1,13,5,13,113,8,13,10,13,12,13,116,9,13,1,
-        13,1,13,1,14,1,14,5,14,122,8,14,10,14,12,14,125,9,14,1,14,1,14,1,
-        51,0,15,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,0,17,8,19,9,21,10,23,11,
-        25,12,27,13,29,14,1,0,8,3,0,10,10,43,43,92,92,2,0,10,10,92,92,1,
-        0,10,10,3,0,32,32,45,45,58,58,8,0,36,36,42,42,46,57,65,90,92,92,
-        95,95,97,123,125,125,4,0,33,33,44,44,46,46,63,63,3,0,9,9,13,13,32,
-        32,1,0,92,92,138,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,
-        0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,
-        0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,
-        1,31,1,0,0,0,3,33,1,0,0,0,5,39,1,0,0,0,7,45,1,0,0,0,9,59,1,0,0,0,
-        11,70,1,0,0,0,13,78,1,0,0,0,15,92,1,0,0,0,17,94,1,0,0,0,19,97,1,
-        0,0,0,21,100,1,0,0,0,23,106,1,0,0,0,25,108,1,0,0,0,27,110,1,0,0,
-        0,29,119,1,0,0,0,31,32,5,92,0,0,32,2,1,0,0,0,33,35,5,43,0,0,34,36,
-        8,0,0,0,35,34,1,0,0,0,36,37,1,0,0,0,37,35,1,0,0,0,37,38,1,0,0,0,
-        38,4,1,0,0,0,39,41,5,45,0,0,40,42,8,1,0,0,41,40,1,0,0,0,42,43,1,
-        0,0,0,43,41,1,0,0,0,43,44,1,0,0,0,44,6,1,0,0,0,45,46,5,47,0,0,46,
-        47,5,42,0,0,47,51,1,0,0,0,48,50,9,0,0,0,49,48,1,0,0,0,50,53,1,0,
-        0,0,51,52,1,0,0,0,51,49,1,0,0,0,52,54,1,0,0,0,53,51,1,0,0,0,54,55,
-        5,42,0,0,55,56,5,47,0,0,56,57,1,0,0,0,57,58,6,3,0,0,58,8,1,0,0,0,
-        59,60,5,47,0,0,60,61,5,47,0,0,61,65,1,0,0,0,62,64,8,2,0,0,63,62,
-        1,0,0,0,64,67,1,0,0,0,65,63,1,0,0,0,65,66,1,0,0,0,66,68,1,0,0,0,
-        67,65,1,0,0,0,68,69,6,4,0,0,69,10,1,0,0,0,70,75,3,15,7,0,71,74,5,
-        45,0,0,72,74,3,15,7,0,73,71,1,0,0,0,73,72,1,0,0,0,74,77,1,0,0,0,
-        75,73,1,0,0,0,75,76,1,0,0,0,76,12,1,0,0,0,77,75,1,0,0,0,78,81,5,
-        34,0,0,79,82,5,58,0,0,80,82,3,15,7,0,81,79,1,0,0,0,81,80,1,0,0,0,
-        82,87,1,0,0,0,83,86,7,3,0,0,84,86,3,15,7,0,85,83,1,0,0,0,85,84,1,
-        0,0,0,86,89,1,0,0,0,87,85,1,0,0,0,87,88,1,0,0,0,88,90,1,0,0,0,89,
-        87,1,0,0,0,90,91,5,34,0,0,91,14,1,0,0,0,92,93,7,4,0,0,93,16,1,0,
-        0,0,94,95,3,21,10,0,95,96,5,92,0,0,96,18,1,0,0,0,97,98,7,5,0,0,98,
-        20,1,0,0,0,99,101,7,6,0,0,100,99,1,0,0,0,101,102,1,0,0,0,102,100,
-        1,0,0,0,102,103,1,0,0,0,103,104,1,0,0,0,104,105,6,10,0,0,105,22,
-        1,0,0,0,106,107,7,2,0,0,107,24,1,0,0,0,108,109,7,7,0,0,109,26,1,
-        0,0,0,110,114,5,35,0,0,111,113,8,2,0,0,112,111,1,0,0,0,113,116,1,
-        0,0,0,114,112,1,0,0,0,114,115,1,0,0,0,115,117,1,0,0,0,116,114,1,
-        0,0,0,117,118,6,13,0,0,118,28,1,0,0,0,119,123,5,33,0,0,120,122,8,
-        2,0,0,121,120,1,0,0,0,122,125,1,0,0,0,123,121,1,0,0,0,123,124,1,
-        0,0,0,124,126,1,0,0,0,125,123,1,0,0,0,126,127,6,14,0,0,127,30,1,
-        0,0,0,13,0,37,43,51,65,73,75,81,85,87,102,114,123,1,6,0,0
+        8,1,8,1,8,1,8,1,8,1,9,1,9,1,10,4,10,103,8,10,11,10,12,10,104,1,10,
+        1,10,1,11,1,11,1,12,1,12,1,13,1,13,5,13,115,8,13,10,13,12,13,118,
+        9,13,1,13,1,13,1,14,1,14,5,14,124,8,14,10,14,12,14,127,9,14,1,14,
+        1,14,1,51,0,15,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,0,17,8,19,9,21,10,
+        23,11,25,12,27,13,29,14,1,0,8,4,0,10,10,32,32,43,43,92,92,3,0,10,
+        10,32,32,92,92,1,0,10,10,3,0,32,32,45,45,58,58,8,0,36,36,40,42,46,
+        57,65,90,92,92,95,95,97,123,125,125,4,0,33,33,44,44,46,46,63,63,
+        3,0,9,9,13,13,32,32,1,0,92,92,140,0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,
+        0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,17,1,0,
+        0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0,0,27,1,0,
+        0,0,0,29,1,0,0,0,1,31,1,0,0,0,3,33,1,0,0,0,5,39,1,0,0,0,7,45,1,0,
+        0,0,9,59,1,0,0,0,11,70,1,0,0,0,13,78,1,0,0,0,15,92,1,0,0,0,17,94,
+        1,0,0,0,19,99,1,0,0,0,21,102,1,0,0,0,23,108,1,0,0,0,25,110,1,0,0,
+        0,27,112,1,0,0,0,29,121,1,0,0,0,31,32,5,92,0,0,32,2,1,0,0,0,33,35,
+        5,43,0,0,34,36,8,0,0,0,35,34,1,0,0,0,36,37,1,0,0,0,37,35,1,0,0,0,
+        37,38,1,0,0,0,38,4,1,0,0,0,39,41,5,45,0,0,40,42,8,1,0,0,41,40,1,
+        0,0,0,42,43,1,0,0,0,43,41,1,0,0,0,43,44,1,0,0,0,44,6,1,0,0,0,45,
+        46,5,47,0,0,46,47,5,42,0,0,47,51,1,0,0,0,48,50,9,0,0,0,49,48,1,0,
+        0,0,50,53,1,0,0,0,51,52,1,0,0,0,51,49,1,0,0,0,52,54,1,0,0,0,53,51,
+        1,0,0,0,54,55,5,42,0,0,55,56,5,47,0,0,56,57,1,0,0,0,57,58,6,3,0,
+        0,58,8,1,0,0,0,59,60,5,47,0,0,60,61,5,47,0,0,61,65,1,0,0,0,62,64,
+        8,2,0,0,63,62,1,0,0,0,64,67,1,0,0,0,65,63,1,0,0,0,65,66,1,0,0,0,
+        66,68,1,0,0,0,67,65,1,0,0,0,68,69,6,4,0,0,69,10,1,0,0,0,70,75,3,
+        15,7,0,71,74,5,45,0,0,72,74,3,15,7,0,73,71,1,0,0,0,73,72,1,0,0,0,
+        74,77,1,0,0,0,75,73,1,0,0,0,75,76,1,0,0,0,76,12,1,0,0,0,77,75,1,
+        0,0,0,78,81,5,34,0,0,79,82,5,58,0,0,80,82,3,15,7,0,81,79,1,0,0,0,
+        81,80,1,0,0,0,82,87,1,0,0,0,83,86,7,3,0,0,84,86,3,15,7,0,85,83,1,
+        0,0,0,85,84,1,0,0,0,86,89,1,0,0,0,87,85,1,0,0,0,87,88,1,0,0,0,88,
+        90,1,0,0,0,89,87,1,0,0,0,90,91,5,34,0,0,91,14,1,0,0,0,92,93,7,4,
+        0,0,93,16,1,0,0,0,94,95,3,21,10,0,95,96,5,92,0,0,96,97,1,0,0,0,97,
+        98,6,8,0,0,98,18,1,0,0,0,99,100,7,5,0,0,100,20,1,0,0,0,101,103,7,
+        6,0,0,102,101,1,0,0,0,103,104,1,0,0,0,104,102,1,0,0,0,104,105,1,
+        0,0,0,105,106,1,0,0,0,106,107,6,10,0,0,107,22,1,0,0,0,108,109,7,
+        2,0,0,109,24,1,0,0,0,110,111,7,7,0,0,111,26,1,0,0,0,112,116,5,35,
+        0,0,113,115,8,2,0,0,114,113,1,0,0,0,115,118,1,0,0,0,116,114,1,0,
+        0,0,116,117,1,0,0,0,117,119,1,0,0,0,118,116,1,0,0,0,119,120,6,13,
+        0,0,120,28,1,0,0,0,121,125,5,33,0,0,122,124,8,2,0,0,123,122,1,0,
+        0,0,124,127,1,0,0,0,125,123,1,0,0,0,125,126,1,0,0,0,126,128,1,0,
+        0,0,127,125,1,0,0,0,128,129,6,14,0,0,129,30,1,0,0,0,13,0,37,43,51,
+        65,73,75,81,85,87,104,116,125,1,6,0,0
     ]
 
 class DotFLexer(Lexer):
@@ -99,7 +100,7 @@ class DotFLexer(Lexer):
 
     def __init__(self, input=None, output:TextIO = sys.stdout):
         super().__init__(input, output)
-        self.checkVersion("4.11.1")
+        self.checkVersion("4.13.0")
         self._interp = LexerATNSimulator(self, self.atn, self.decisionsToDFA, PredictionContextCache())
         self._actions = None
         self._predicates = None
diff --git a/src/SigasiProjectCreator/DotF/DotFListener.py b/src/SigasiProjectCreator/DotF/DotFListener.py
index 6342dd9..0558d43 100644
--- a/src/SigasiProjectCreator/DotF/DotFListener.py
+++ b/src/SigasiProjectCreator/DotF/DotFListener.py
@@ -1,6 +1,6 @@
-# Generated from DotF.g4 by ANTLR 4.11.1
+# Generated from DotF.g4 by ANTLR 4.13.0
 from antlr4 import *
-if __name__ is not None and "." in __name__:
+if "." in __name__:
     from .DotFParser import DotFParser
 else:
     from DotFParser import DotFParser
diff --git a/src/SigasiProjectCreator/DotF/DotFParser.py b/src/SigasiProjectCreator/DotF/DotFParser.py
index c3e3fc7..e097397 100644
--- a/src/SigasiProjectCreator/DotF/DotFParser.py
+++ b/src/SigasiProjectCreator/DotF/DotFParser.py
@@ -1,4 +1,4 @@
-# Generated from DotF.g4 by ANTLR 4.11.1
+# Generated from DotF.g4 by ANTLR 4.13.0
 # encoding: utf-8
 from antlr4 import *
 from io import StringIO
@@ -10,29 +10,22 @@ else:
 
 def serializedATN():
     return [
-        4,1,14,76,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
-        6,2,7,7,7,1,0,5,0,18,8,0,10,0,12,0,21,9,0,1,1,1,1,1,1,1,1,1,1,1,
-        1,1,1,1,1,1,1,5,1,32,8,1,10,1,12,1,35,9,1,1,1,1,1,1,1,1,1,5,1,41,
-        8,1,10,1,12,1,44,9,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
-        3,1,57,8,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,6,1,6,3,6,69,8,6,1,
-        6,1,6,1,7,1,7,1,7,1,7,0,0,8,0,2,4,6,8,10,12,14,0,1,1,0,6,7,77,0,
-        19,1,0,0,0,2,56,1,0,0,0,4,58,1,0,0,0,6,60,1,0,0,0,8,62,1,0,0,0,10,
-        64,1,0,0,0,12,66,1,0,0,0,14,72,1,0,0,0,16,18,3,2,1,0,17,16,1,0,0,
-        0,18,21,1,0,0,0,19,17,1,0,0,0,19,20,1,0,0,0,20,1,1,0,0,0,21,19,1,
-        0,0,0,22,23,3,10,5,0,23,24,5,11,0,0,24,57,1,0,0,0,25,26,3,10,5,0,
-        26,27,3,14,7,0,27,28,3,2,1,0,28,57,1,0,0,0,29,33,3,4,2,0,30,32,3,
-        6,3,0,31,30,1,0,0,0,32,35,1,0,0,0,33,31,1,0,0,0,33,34,1,0,0,0,34,
-        36,1,0,0,0,35,33,1,0,0,0,36,37,5,11,0,0,37,57,1,0,0,0,38,42,3,4,
-        2,0,39,41,3,6,3,0,40,39,1,0,0,0,41,44,1,0,0,0,42,40,1,0,0,0,42,43,
-        1,0,0,0,43,45,1,0,0,0,44,42,1,0,0,0,45,46,3,12,6,0,46,47,3,2,1,0,
-        47,57,1,0,0,0,48,49,3,8,4,0,49,50,5,11,0,0,50,57,1,0,0,0,51,52,3,
-        8,4,0,52,53,3,12,6,0,53,54,3,2,1,0,54,57,1,0,0,0,55,57,5,11,0,0,
-        56,22,1,0,0,0,56,25,1,0,0,0,56,29,1,0,0,0,56,38,1,0,0,0,56,48,1,
-        0,0,0,56,51,1,0,0,0,56,55,1,0,0,0,57,3,1,0,0,0,58,59,5,2,0,0,59,
-        5,1,0,0,0,60,61,5,2,0,0,61,7,1,0,0,0,62,63,5,3,0,0,63,9,1,0,0,0,
-        64,65,7,0,0,0,65,11,1,0,0,0,66,68,5,1,0,0,67,69,5,10,0,0,68,67,1,
-        0,0,0,68,69,1,0,0,0,69,70,1,0,0,0,70,71,5,11,0,0,71,13,1,0,0,0,72,
-        73,5,8,0,0,73,74,5,11,0,0,74,15,1,0,0,0,5,19,33,42,56,68
+        4,1,14,52,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
+        6,2,7,7,7,1,0,5,0,18,8,0,10,0,12,0,21,9,0,1,1,1,1,3,1,25,8,1,1,1,
+        1,1,3,1,29,8,1,1,1,1,1,3,1,33,8,1,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,
+        5,1,6,1,6,3,6,45,8,6,1,6,1,6,1,7,1,7,1,7,1,7,0,0,8,0,2,4,6,8,10,
+        12,14,0,1,1,0,6,7,50,0,19,1,0,0,0,2,32,1,0,0,0,4,34,1,0,0,0,6,36,
+        1,0,0,0,8,38,1,0,0,0,10,40,1,0,0,0,12,42,1,0,0,0,14,48,1,0,0,0,16,
+        18,3,2,1,0,17,16,1,0,0,0,18,21,1,0,0,0,19,17,1,0,0,0,19,20,1,0,0,
+        0,20,1,1,0,0,0,21,19,1,0,0,0,22,24,3,4,2,0,23,25,3,6,3,0,24,23,1,
+        0,0,0,24,25,1,0,0,0,25,33,1,0,0,0,26,28,3,8,4,0,27,29,3,10,5,0,28,
+        27,1,0,0,0,28,29,1,0,0,0,29,33,1,0,0,0,30,33,3,10,5,0,31,33,5,11,
+        0,0,32,22,1,0,0,0,32,26,1,0,0,0,32,30,1,0,0,0,32,31,1,0,0,0,33,3,
+        1,0,0,0,34,35,5,2,0,0,35,5,1,0,0,0,36,37,5,2,0,0,37,7,1,0,0,0,38,
+        39,5,3,0,0,39,9,1,0,0,0,40,41,7,0,0,0,41,11,1,0,0,0,42,44,5,1,0,
+        0,43,45,5,10,0,0,44,43,1,0,0,0,44,45,1,0,0,0,45,46,1,0,0,0,46,47,
+        5,11,0,0,47,13,1,0,0,0,48,49,5,8,0,0,49,50,5,11,0,0,50,15,1,0,0,
+        0,5,19,24,28,32,44
     ]
 
 class DotFParser ( Parser ):
@@ -81,7 +74,7 @@ class DotFParser ( Parser ):
 
     def __init__(self, input:TokenStream, output:TextIO = sys.stdout):
         super().__init__(input, output)
-        self.checkVersion("4.11.1")
+        self.checkVersion("4.13.0")
         self._interp = ParserATNSimulator(self, self.atn, self.decisionsToDFA, self.sharedContextCache)
         self._predicates = None
 
@@ -126,7 +119,7 @@ class DotFParser ( Parser ):
             self.state = 19
             self._errHandler.sync(self)
             _la = self._input.LA(1)
-            while ((_la) & ~0x3f) == 0 and ((1 << _la) & 2252) != 0:
+            while (((_la) & ~0x3f) == 0 and ((1 << _la) & 2252) != 0):
                 self.state = 16
                 self.cmd_option()
                 self.state = 21
@@ -149,40 +142,25 @@ class DotFParser ( Parser ):
             super().__init__(parent, invokingState)
             self.parser = parser
 
-        def filename(self):
-            return self.getTypedRuleContext(DotFParser.FilenameContext,0)
-
-
-        def NL(self):
-            return self.getToken(DotFParser.NL, 0)
-
-        def filecont(self):
-            return self.getTypedRuleContext(DotFParser.FilecontContext,0)
-
-
-        def cmd_option(self):
-            return self.getTypedRuleContext(DotFParser.Cmd_optionContext,0)
-
-
         def plus_option(self):
             return self.getTypedRuleContext(DotFParser.Plus_optionContext,0)
 
 
-        def plus_option_arg(self, i:int=None):
-            if i is None:
-                return self.getTypedRuleContexts(DotFParser.Plus_option_argContext)
-            else:
-                return self.getTypedRuleContext(DotFParser.Plus_option_argContext,i)
-
-
-        def continuation(self):
-            return self.getTypedRuleContext(DotFParser.ContinuationContext,0)
+        def plus_option_arg(self):
+            return self.getTypedRuleContext(DotFParser.Plus_option_argContext,0)
 
 
         def dash_option(self):
             return self.getTypedRuleContext(DotFParser.Dash_optionContext,0)
 
 
+        def filename(self):
+            return self.getTypedRuleContext(DotFParser.FilenameContext,0)
+
+
+        def NL(self):
+            return self.getToken(DotFParser.NL, 0)
+
         def getRuleIndex(self):
             return DotFParser.RULE_cmd_option
 
@@ -201,91 +179,48 @@ class DotFParser ( Parser ):
 
         localctx = DotFParser.Cmd_optionContext(self, self._ctx, self.state)
         self.enterRule(localctx, 2, self.RULE_cmd_option)
-        self._la = 0 # Token type
         try:
-            self.state = 56
+            self.state = 32
             self._errHandler.sync(self)
-            la_ = self._interp.adaptivePredict(self._input,3,self._ctx)
-            if la_ == 1:
+            token = self._input.LA(1)
+            if token in [2]:
                 self.enterOuterAlt(localctx, 1)
                 self.state = 22
-                self.filename()
-                self.state = 23
-                self.match(DotFParser.NL)
-                pass
-
-            elif la_ == 2:
-                self.enterOuterAlt(localctx, 2)
-                self.state = 25
-                self.filename()
-                self.state = 26
-                self.filecont()
-                self.state = 27
-                self.cmd_option()
-                pass
-
-            elif la_ == 3:
-                self.enterOuterAlt(localctx, 3)
-                self.state = 29
                 self.plus_option()
-                self.state = 33
+                self.state = 24
                 self._errHandler.sync(self)
-                _la = self._input.LA(1)
-                while _la==2:
-                    self.state = 30
+                la_ = self._interp.adaptivePredict(self._input,1,self._ctx)
+                if la_ == 1:
+                    self.state = 23
                     self.plus_option_arg()
-                    self.state = 35
-                    self._errHandler.sync(self)
-                    _la = self._input.LA(1)
 
-                self.state = 36
-                self.match(DotFParser.NL)
-                pass
 
-            elif la_ == 4:
-                self.enterOuterAlt(localctx, 4)
-                self.state = 38
-                self.plus_option()
-                self.state = 42
+                pass
+            elif token in [3]:
+                self.enterOuterAlt(localctx, 2)
+                self.state = 26
+                self.dash_option()
+                self.state = 28
                 self._errHandler.sync(self)
-                _la = self._input.LA(1)
-                while _la==2:
-                    self.state = 39
-                    self.plus_option_arg()
-                    self.state = 44
-                    self._errHandler.sync(self)
-                    _la = self._input.LA(1)
+                la_ = self._interp.adaptivePredict(self._input,2,self._ctx)
+                if la_ == 1:
+                    self.state = 27
+                    self.filename()
 
-                self.state = 45
-                self.continuation()
-                self.state = 46
-                self.cmd_option()
-                pass
 
-            elif la_ == 5:
-                self.enterOuterAlt(localctx, 5)
-                self.state = 48
-                self.dash_option()
-                self.state = 49
-                self.match(DotFParser.NL)
                 pass
-
-            elif la_ == 6:
-                self.enterOuterAlt(localctx, 6)
-                self.state = 51
-                self.dash_option()
-                self.state = 52
-                self.continuation()
-                self.state = 53
-                self.cmd_option()
+            elif token in [6, 7]:
+                self.enterOuterAlt(localctx, 3)
+                self.state = 30
+                self.filename()
                 pass
-
-            elif la_ == 7:
-                self.enterOuterAlt(localctx, 7)
-                self.state = 55
+            elif token in [11]:
+                self.enterOuterAlt(localctx, 4)
+                self.state = 31
                 self.match(DotFParser.NL)
                 pass
-
+            else:
+                raise NoViableAltException(self)
 
         except RecognitionException as re:
             localctx.exception = re
@@ -326,7 +261,7 @@ class DotFParser ( Parser ):
         self.enterRule(localctx, 4, self.RULE_plus_option)
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 58
+            self.state = 34
             self.match(DotFParser.PLUS_OPTION)
         except RecognitionException as re:
             localctx.exception = re
@@ -367,7 +302,7 @@ class DotFParser ( Parser ):
         self.enterRule(localctx, 6, self.RULE_plus_option_arg)
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 60
+            self.state = 36
             self.match(DotFParser.PLUS_OPTION)
         except RecognitionException as re:
             localctx.exception = re
@@ -408,7 +343,7 @@ class DotFParser ( Parser ):
         self.enterRule(localctx, 8, self.RULE_dash_option)
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 62
+            self.state = 38
             self.match(DotFParser.DASH_OPTION)
         except RecognitionException as re:
             localctx.exception = re
@@ -453,7 +388,7 @@ class DotFParser ( Parser ):
         self._la = 0 # Token type
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 64
+            self.state = 40
             _la = self._input.LA(1)
             if not(_la==6 or _la==7):
                 self._errHandler.recoverInline(self)
@@ -503,17 +438,17 @@ class DotFParser ( Parser ):
         self._la = 0 # Token type
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 66
+            self.state = 42
             self.match(DotFParser.T__0)
-            self.state = 68
+            self.state = 44
             self._errHandler.sync(self)
             _la = self._input.LA(1)
             if _la==10:
-                self.state = 67
+                self.state = 43
                 self.match(DotFParser.WS)
 
 
-            self.state = 70
+            self.state = 46
             self.match(DotFParser.NL)
         except RecognitionException as re:
             localctx.exception = re
@@ -557,9 +492,9 @@ class DotFParser ( Parser ):
         self.enterRule(localctx, 14, self.RULE_filecont)
         try:
             self.enterOuterAlt(localctx, 1)
-            self.state = 72
+            self.state = 48
             self.match(DotFParser.CONT)
-            self.state = 73
+            self.state = 49
             self.match(DotFParser.NL)
         except RecognitionException as re:
             localctx.exception = re
diff --git a/src/SigasiProjectCreator/DotF/DotFfileParser.py b/src/SigasiProjectCreator/DotF/DotFfileParser.py
index db35b53..e706950 100644
--- a/src/SigasiProjectCreator/DotF/DotFfileParser.py
+++ b/src/SigasiProjectCreator/DotF/DotFfileParser.py
@@ -9,12 +9,25 @@
 import os
 import sys
 import glob
+import re
 
 from SigasiProjectCreator.ArgsAndFileParser import ArgsAndFileParser
 from .parseFile import parse_dotf
 from ..convertDotFtoCsv import rebase_file
 
 
+def abspath(path):
+    s_path = str(path)
+    if s_path.startswith('\\') or s_path.startswith('/') or s_path[1] == ':' or s_path.startswith('$'):
+        # this is an absolute path in Linux or Windows
+        return path
+    return os.path.abspath(path)
+
+
+def expandvars_plus(s):
+    return os.path.expandvars(re.sub(r'\$\((.*)\)', r'${\1}', s))
+
+
 class DotFfileParser:
 
     def __init__(self, filename):
@@ -41,20 +54,12 @@ class DotFfileParser:
         self.csvfname = str(os.path.splitext(self.dotfname)[0]) + ".csv"
 
         self.filecontent = parse_dotf(filename)
+        parser_expect_library = False
+        parser_expect_dot_f = False
+        newlib = 'work'
         for option in self.filecontent:
             if isinstance(option, list):
-                if option[0].startswith("-makelib"):
-                    newlib = option[0].split(' ')[1].split('/')[-1]
-                    for fn in option:
-                        if not (fn.startswith("+") or fn.startswith("-")):
-                            if "*" in fn:
-                                expanded_option = glob.glob(rebase_file(fn, self.dotfdir), recursive=True)
-                                for f in expanded_option:
-                                    self.add_to_library_mapping(f, newlib)
-                            else:
-                                f = rebase_file(fn, self.dotfdir)
-                                self.add_to_library_mapping(f, newlib)
-                elif option[0] == "+incdir":
+                if option[0] == "+incdir":
                     for fn in option[1:]:
                         self.includes.add(rebase_file(fn[1:], self.dotfdir))
                 elif option[0] == "+define":
@@ -64,45 +69,74 @@ class DotFfileParser:
                     print('Unknown multiline option (ignored) : ' + option[0])
             else:
                 bare_option = str(option).strip('"')
-                if bare_option.startswith("-endlib"):
-                    pass
-                elif bare_option.startswith("-f "):
+                if bare_option == "-makelib" or bare_option == "-work":
+                    parser_expect_library = True
+                elif bare_option == "-endlib":
+                    newlib = 'work'
+                elif bare_option == "-f":
+                    parser_expect_dot_f = True
+                elif bare_option.startswith("+") or bare_option.startswith("-"):
+                    print(f'*.f parse* unknown option (ignored) : {bare_option}')
+                elif parser_expect_dot_f:
+                    parser_expect_dot_f = False
                     # Parse included .f file
-                    subfile = os.path.expandvars(bare_option.split()[1])
+                    subfile = expandvars_plus(bare_option)
                     if not os.path.isabs(subfile):
                         subfile = os.path.join(self.dotfdir, subfile)
                     subparser = DotFfileParser(subfile)
                     self.library_mapping.update(subparser.library_mapping)
                     self.includes |= subparser.includes
                     self.defines.extend(subparser.defines)
-                elif bare_option.startswith("+") or bare_option.startswith("-"):
-                    print("Unknown option (ignored) : " + bare_option)
+                elif parser_expect_library:
+                    # new library name
+                    parser_expect_library = False
+                    newlib = bare_option.split('/')[-1]
                 else:
                     # Design file: add to library mapping
-                    if "*" in bare_option:
-                        expanded_option = glob.glob(rebase_file(bare_option, self.dotfdir), recursive=True)
-                        for f in expanded_option:
-                            self.add_to_library_mapping(f, 'work')
+                    if str(os.path.splitext(bare_option)[1]).lower() in ['.vhd', '.vhdl', '.v', '.sv']:
+                        self.add_to_library_mapping(bare_option, newlib)
                     else:
-                        self.add_to_library_mapping(rebase_file(bare_option, self.dotfdir), 'work')
+                        print(f'*.f parse* skipping {bare_option}')
 
     def add_to_library_mapping(self, file, library):
-        if str(ArgsAndFileParser.get_layout_option()) == 'default':
-            if file in self.library_mapping:
-                file_base, file_ext = os.path.splitext(file)
-                newfile = file_base + '_' + library + file_ext
-                if newfile in self.library_mapping:
-                    print('File already mapped to library: ' + file + ' => ' + library)
-                else:
-                    self.library_mapping[newfile] = library
-                    self.linked_file_mapping[newfile] = file
-            else:
-                self.library_mapping[file] = library
+        # For now, we'll return a dict of abs path => library
+        # TODO Problem (to be re-solved): files may be mapped to more than one library, in which case this
+        #  approach won't work
+        # Layout moves to ConverterHelper
+
+        # We need to expand environment variables here, before expanding wildcards
+        expanded_path = os.path.expandvars(file)
+        if "*" in expanded_path:
+            expanded_option = glob.glob(rebase_file(expanded_path, self.dotfdir), recursive=True)
+            if not expanded_option:
+                print(f'**warning** wildcard expression {expanded_option} does not match anything')
+                self.library_mapping[abspath(rebase_file(expanded_path, self.dotfdir))] = library
+            for f in expanded_option:
+                self.library_mapping[abspath(f)] = library
         else:
-            if library not in self.library_mapping:
-                self.library_mapping[library] = library
-            file_path, file_name = os.path.split(file)
-            self.linked_file_mapping[library + '/' + file_name] = file
+            self.library_mapping[abspath(rebase_file(expanded_path, self.dotfdir))] = library
+
+        # self.library_mapping[os.path.abspath(file)] = library
+        #
+        #
+        #
+        # if str(ArgsAndFileParser.get_layout_option()) == 'default':
+        #     if file in self.library_mapping:
+        #         file_base, file_ext = os.path.splitext(file)
+        #         newfile = file_base + '_' + library + file_ext
+        #         if newfile in self.library_mapping:
+        #             print('File already mapped to library: ' + file + ' => ' + library)
+        #         else:
+        #             self.library_mapping[newfile] = library
+        #             self.linked_file_mapping[newfile] = file
+        #     else:
+        #         self.library_mapping[file] = library
+        # else:
+        #     # non-default library mapping
+        #     if library not in self.library_mapping:
+        #         self.library_mapping[library] = library
+        #     file_path, file_name = os.path.split(file)
+        #     self.linked_file_mapping[library + '/' + file_name] = file
 
 
 def parse_file(filename):
diff --git a/src/SigasiProjectCreator/convertDotFtoCsv.py b/src/SigasiProjectCreator/convertDotFtoCsv.py
index fbb7d04..741d4df 100644
--- a/src/SigasiProjectCreator/convertDotFtoCsv.py
+++ b/src/SigasiProjectCreator/convertDotFtoCsv.py
@@ -12,9 +12,16 @@ import sys
 import os
 import csv
 
+def isabspath(path):
+    s_path = str(path)
+    if s_path.startswith('\\') or s_path.startswith('/') or s_path[1] == ':' or s_path.startswith('$'):
+        return True
+    return os.path.isabs(path)
+
+
 def rebase_file(filename, dotfdir):
     hdlpath = os.path.expandvars(filename)
-    if not os.path.isabs(hdlpath):
+    if not isabspath(hdlpath):
         hdlpath = os.path.join(dotfdir, hdlpath)
     hdlpath = os.path.normpath(hdlpath)
     return hdlpath
diff --git a/src/SigasiProjectCreator/createSigasiProjectFromListOfFiles.py b/src/SigasiProjectCreator/createSigasiProjectFromListOfFiles.py
index 774ffcb..259291b 100755
--- a/src/SigasiProjectCreator/createSigasiProjectFromListOfFiles.py
+++ b/src/SigasiProjectCreator/createSigasiProjectFromListOfFiles.py
@@ -23,9 +23,8 @@ example: %prog MyProjectName foo.vhdl bar.sv
 
 
 def main():
-    # TODO this is now officially broken, fit it!
     parser = argparse.ArgumentParser(prog='SigasiProjectCreator')
-    parser.add_argument('project_name', help='project name', required=True)
+    parser.add_argument('project_name', help='project name')
     parser.add_argument('input_files', help='input files', nargs='+')
     args = parser.parse_args()
     project_name = args.project_name


Test patch:
diff --git a/tests/DotFfileParserTest.py b/tests/DotFfileParserTest.py
new file mode 100644
index 0000000..8f8a3f1
--- /dev/null
+++ b/tests/DotFfileParserTest.py
@@ -0,0 +1,128 @@
+import os.path
+import unittest
+from SigasiProjectCreator.DotF.DotFfileParser import parse_file
+
+class DotFfileParserTest(unittest.TestCase):
+    def test_basic(self):
+        self.maxDiff = None
+        input_file = "tests/test-files/dotFparser/test1.f"
+        result = parse_file(input_file)
+        base_path = os.path.abspath(os.path.join(os.path.dirname(input_file), '../../../..'))
+        expected_library_mapping = {
+            f'{base_path}/bench/verilog/stainlesssteel/ram_d1.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/ram_d2.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/ram_dp.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/ram_p2.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/ram_sp.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/glbl.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/m_debug.sv': 'work',
+            f'{base_path}/bench/verilog/stainlesssteel/m_testbench.sv': 'work',
+            f'{base_path}/rtl/verilog/soc/m_soc.sv': 'work',
+            f'{base_path}/rtl/verilog/soc/m_io_cell.sv': 'work'
+        }
+        expected_includes = {
+            '../rtl/verilog/pkg',
+            '../bench/verilog/stainlesssteel'
+        }
+        expected_defines = []
+        self.assertDictEqual(result.library_mapping, expected_library_mapping, 'Library mapping mismatch')
+        self.assertSetEqual(result.includes, expected_includes, 'Includes list mismatch')
+        self.assertListEqual(result.defines, expected_defines, 'Defines list mismatch')
+
+    def test_continuation(self):
+        self.maxDiff = None
+        input_file = "tests/test-files/dotFparser/continuation.f"
+        result = parse_file(input_file)
+        expected_library_mapping = {
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_axi4streampc.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_axi4pc.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/xil_common_vip_pkg.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_pkg.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_pkg.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_if.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_if.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/clk_vip_if.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/rst_vip_if.sv": 'vendor_vip',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv": 'defaultlib',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv": 'defaultlib',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv": 'defaultlib',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_VCOMP.vhd": 'xpm'
+        }
+        expected_includes = set()
+        expected_defines = []
+        self.assertDictEqual(result.library_mapping, expected_library_mapping, 'Library mapping mismatch')
+        self.assertSetEqual(result.includes, expected_includes, 'Includes list mismatch')
+        self.assertListEqual(result.defines, expected_defines, 'Defines list mismatch')
+
+    def test_filelist(self):
+        self.maxDiff = None
+        input_file = "tests/test-files/dotFparser/filelist.f"
+        result = parse_file(input_file)
+        base_path = os.path.abspath(os.path.join(os.path.dirname(input_file), '../../..'))
+        expected_library_mapping = {
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_conv.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_lite_conv.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_r_conv.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_w_conv.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b_downsizer.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_decerr_slave.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_simple_fifo.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_wrap_cmd.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_incr_cmd.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_wr_cmd_fsm.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_rd_cmd_fsm.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_cmd_translator.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_b_channel.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_r_channel.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_aw_channel.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s_ar_channel.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_b2s.v': 'work',
+            f'{base_path}/ipstatic/some_protocol_converter_v2_1/hdl/verilog/some_protocol_converter_v2_1_some_protocol_converter.v': 'work',
+            f'{base_path}/bd/design_1/ip/design_1_auto_pc_0/sim/design_1_auto_pc_0.v': 'work',
+            f'{base_path}/bd/design_1/hdl/design_1.vhd': 'work',
+            f'{base_path}/tests/test-files/dotFparser/glbl.v': 'work'
+        }
+        expected_includes = set()
+        expected_defines = []
+        self.assertDictEqual(result.library_mapping, expected_library_mapping, 'Library mapping mismatch')
+        self.assertSetEqual(result.includes, expected_includes, 'Includes list mismatch')
+        self.assertListEqual(result.defines, expected_defines, 'Defines list mismatch')
+
+    def test_variable(self):
+        self.maxDiff = None
+        input_file = "tests/test-files/dotFparser/variable.f"
+        result = parse_file(input_file)
+        base_path = str(os.path.abspath(os.path.join(os.path.dirname(input_file), '.')))
+        expected_library_mapping = {
+            '${FUBAR_HOME}/src/fubar_pkg.sv': 'work',
+            f'{base_path}/vw_wd_g2u_if.sv': 'work',
+            f'{base_path}/vw_wd_g2u_test.sv': 'work',
+            f'{base_path}/vw_wd_g2u_top.sv': 'work',
+        }
+        expected_includes = {'$FUBAR_HOME/src'}
+        expected_defines = []
+        self.assertDictEqual(result.library_mapping, expected_library_mapping, 'Library mapping mismatch')
+        self.assertSetEqual(result.includes, expected_includes, 'Includes list mismatch')
+        self.assertListEqual(result.defines, expected_defines, 'Defines list mismatch')
+
+    def test_wildcard(self):
+        self.maxDiff = None
+        input_file = "tests/test-files/dotFparser/wildcard.f"
+        base_path1 = str(os.path.abspath(os.path.join(os.path.dirname(input_file), '..')))
+        base_path2 = str(os.path.abspath(os.path.join(os.path.dirname(input_file), '../..')))
+        result = parse_file(input_file)
+        expected_library_mapping = {
+            '/usr/eda/dk/vendor/tech/verilog/*.v': 'work',
+            f'{base_path2}/synthesis/image_average.v': 'work',
+            f'{base_path1}/tb/tb_image.vhd': 'work',
+            f'{base_path2}/rtl/image_ram.vhd': 'work'
+        }
+        expected_includes = set()
+        expected_defines = []
+        self.assertDictEqual(result.library_mapping, expected_library_mapping, 'Library mapping mismatch')
+        self.assertSetEqual(result.includes, expected_includes, 'Includes list mismatch')
+        self.assertListEqual(result.defines, expected_defines, 'Defines list mismatch')
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/parseFileTest.py b/tests/parseFileTest.py
index 3272d5a..b384405 100644
--- a/tests/parseFileTest.py
+++ b/tests/parseFileTest.py
@@ -23,10 +23,32 @@ class test_parseFile(unittest.TestCase):
     def test_continuation(self):
         result = parse_dotf("tests/test-files/dotFparser/continuation.f")
         expected = [
-            ['-makelib ies_lib/vendor_vip -sv', "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_axi4streampc.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_axi4pc.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/xil_common_vip_pkg.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_pkg.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_pkg.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_if.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_if.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/clk_vip_if.sv", "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/rst_vip_if.sv", '-endlib'],
-            ['-makelib ies_lib/defaultlib -sv',  "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv", "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv", "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv", '-endlib'],
-            ['-makelib ies_lib/xpm', "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_VCOMP.vhd", '-endlib' ]
+            '-makelib',
+            'ies_lib/vendor_vip',
+            '-sv',
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_axi4streampc.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_axi4pc.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/xil_common_vip_pkg.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_pkg.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_pkg.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi4stream_vip_if.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/axi_vip_if.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/clk_vip_if.sv",
+            "D:/Vendor/Tool/2018.2/data/vendor_vip/hdl/rst_vip_if.sv",
+            '-endlib',
+            '-makelib',
+            'ies_lib/defaultlib',
+            '-sv',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_cdc/hdl/xpm_cdc.sv",
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_fifo/hdl/xpm_fifo.sv",
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_memory/hdl/xpm_memory.sv",
+            '-endlib',
+            '-makelib',
+            'ies_lib/xpm',
+            "D:/Vendor/Tool/2018.2/data/ip/xpm/xpm_VCOMP.vhd",
+            '-endlib'
             ]
+        print('*debug* result = ' + str(result))
         self.maxDiff = None
         self.assertListEqual(result, expected)
 
@@ -73,7 +95,18 @@ class test_parseFile(unittest.TestCase):
     def test_wildcard(self):
         result = parse_dotf("tests/test-files/dotFparser/wildcard.f")
         expected = [
-            '-smartorder -work work -V93 -top tb_image -gui -access +rw -maxdelays -sdf_cmd_file ./sdf_cmd.cmd',
+            '-smartorder',
+            '-work',
+            'work',
+            '-V93',
+            '-top',
+            'tb_image',
+            '-gui',
+            '-access',
+            '+rw',
+            '-maxdelays',
+            '-sdf_cmd_file',
+            './sdf_cmd.cmd',
             '/usr/eda/dk/vendor/tech/verilog/*.v',
             '../../synthesis/image_average.v',
             '../tb/tb_image.vhd',