dopp.d 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import toml;
  2. public{
  3. import std.stdio : writeln;
  4. import std.file : read;
  5. import std.array;
  6. import std.string;
  7. import std.uni : isWhite, isAlpha, isAlphaNum;
  8. import std.ascii : isDigit;
  9. import std.conv : to;
  10. import std.algorithm;
  11. import std.sumtype : SumType;
  12. }
  13. import dopp_lexer : tokenize, isKeyword;
  14. import dopp_parser : parse;
  15. TOMLDocument toml_s;
  16. export enum TokenType{
  17. Identifier,
  18. Keyword,
  19. Integer,
  20. Float,
  21. String,
  22. Symbol,
  23. Whitespace
  24. }
  25. export struct Token{
  26. TokenType type;
  27. string lexeme;
  28. // for debug
  29. string toString(){
  30. import std.format : format;
  31. //return "Token(type: %d, lexeme: %s)".format(type, lexeme);
  32. return "Token = type: %d, lexeme: %s\n".format(type, lexeme);
  33. }
  34. }
  35. // ./dopp -t == shortened for test (onto single .de -> .d module)
  36. // ./dopp -d "/test" -o "/test2" == input dir path + output dir path (default output dir = input dir)
  37. // ./dopp -f test.de -o test.d == input file name + output file name (default output file name = input file name [but .d instead .de] )
  38. // ./dopp -f "/test/test.de" -o "/result/test.d" == input file path + output file path (default output file name and path = input file name and path [but .d instead .de] )
  39. bool is_valid_argv(ref string[] argv){
  40. ulong num = argv.length; // uint64
  41. if(num != 1 && num != 2 && num != 4){
  42. return false;
  43. }else if(num == 1){ // one argument only (just filename or /path/filename) == shortened ./dopp -f test.de = ./dopp test.de; or -t == shortened for test (onto single .de -> .d module)
  44. if( (argv[0] == "-t") || (argv[0].length >= 4 && argv[0][$-3 .. $] == ".de") ){
  45. return true;
  46. }else{
  47. return false;
  48. }
  49. }else if(num == 2){ // two arguments = input file name/path or input dir path
  50. if(argv[0] != "-d" && argv[0] != "-f"){
  51. return false;
  52. }else if(argv[0] == "-f"){ // must be file
  53. if(argv[1].length >= 4 && argv[1][$-3 .. $] == ".de"){
  54. return true;
  55. }else{
  56. return false;
  57. }
  58. }else{ // dir
  59. if(argv[1].length > 0){
  60. return true;
  61. }else{
  62. return false;
  63. }
  64. }
  65. }else{ // num == 4
  66. string[] argv2 = argv[0 .. 2];
  67. if( is_valid_argv(argv2) ){ // valid first 2
  68. string[] argv4 = argv[2 .. $];
  69. if( argv[2] != "-o" ){ // valid next - last 2
  70. return false;
  71. }else if(argv[0] == "-f"){ // must be file
  72. if(argv[3].length >= 3 && argv[3][$-2 .. $] == ".d"){
  73. return true;
  74. }else{
  75. return false;
  76. }
  77. }else{ // dir
  78. if(argv[3].length > 0){
  79. return true;
  80. }else{
  81. return false;
  82. }
  83. }
  84. }else{
  85. return false;
  86. }
  87. }
  88. }
  89. //alias Config_Value = SumType!(string, int, ubyte, bool);
  90. alias Config_Value = SumType!(string, ubyte, bool);
  91. Config_Value get_config_value(ref TOMLDocument toml_s, string key){
  92. if(key == "indent_matter"){
  93. ubyte default_indent_matter = 4;
  94. if(("indent_matter" in toml_s) != null){
  95. if(toml_s[key].type == TOMLType.INTEGER){
  96. ubyte indent_matter = cast(ubyte) toml_s[key].integer; // long (int64) -> ubyte (uint8) // todo add alias
  97. if(indent_matter > 0){
  98. return Config_Value(indent_matter);
  99. }
  100. }
  101. }
  102. writeln("Warning: use default indent_matter = ", default_indent_matter); // todo add config key-value "no_warn" = false | true for silence
  103. return Config_Value(default_indent_matter);
  104. }else if(key == "indent_out"){
  105. ubyte default_indent_out = 2;
  106. if(("indent_out" in toml_s) != null){
  107. if(toml_s[key].type == TOMLType.INTEGER){
  108. ubyte indent_out = cast(ubyte) toml_s[key].integer; // long (int64) -> ubyte (uint8)
  109. if(indent_out > 0){
  110. return Config_Value(indent_out);
  111. }
  112. }
  113. }
  114. writeln("Warning: use default indent_out = ", default_indent_out);
  115. return Config_Value(default_indent_out);
  116. }else if(key == "indent_type"){ // 0 = whitespaces, 1 = tabs
  117. ubyte default_indent_type = 0;
  118. if(("indent_type" in toml_s) != null){
  119. if(toml_s[key].type == TOMLType.INTEGER){
  120. ubyte indent_type = cast(ubyte) toml_s[key].integer; // long (int64) -> ubyte (uint8)
  121. if(indent_type < 2){ // 0 | 1
  122. return Config_Value(indent_type);
  123. }
  124. }
  125. }
  126. writeln("Warning: use default indent_type = ", default_indent_type);
  127. return Config_Value(default_indent_type);
  128. //}else{}
  129. }
  130. return Config_Value(0);
  131. }
  132. //void main(string[] argv){
  133. int main(string[] argv){
  134. toml_s = parseTOML(cast(string)read("dopp.toml"));
  135. /*
  136. writeln("indent_matter: ", toml_s["indent_matter"]); // 4
  137. //writeln("xyz: ", toml_s["xyz"]); // Address boundary error || Segmentation fault (core dumped)
  138. writeln("indent_matter in: ", "indent_matter" in toml_s); // hex like 7F27C2992040
  139. writeln("indent_matter is null: ", ("indent_matter" in toml_s) == null); // fasle
  140. writeln("indent_matter is TOMLType.INTEGER: ", (toml_s["indent_matter"].type == TOMLType.INTEGER)); // true
  141. writeln("xyz in: ", "xyz" in toml_s); // null
  142. writeln("xyz is null: ", ("xyz" in toml_s) == null); // true
  143. */
  144. auto indent_type = get_config_value(toml_s, "indent_type");
  145. //writeln("config: indent_type = ", indent_type); // 0 // todo add config key-value "no_warn" = false | true for silence
  146. auto indent_matter = get_config_value(toml_s, "indent_matter");
  147. //writeln("config: indent_matter = ", indent_matter); // 4
  148. auto indent_out = get_config_value(toml_s, "indent_out");
  149. //writeln("config: indent_out = ", indent_out); // 2
  150. /*
  151. int i = 0;
  152. foreach(string s; argv[1 .. $]){
  153. writeln(s);
  154. i++;
  155. }
  156. writeln("i = ", i);
  157. */
  158. string[] argv1 = argv[1 .. $]; // argv[0] always = program name ( ./dopp in my case in linux )
  159. bool valid_argv = is_valid_argv(argv1);
  160. // writeln("valid_argv = ", valid_argv); // todo add config key-value "no_warn" = false | true for silence
  161. if(!valid_argv){
  162. return 0;
  163. }
  164. //string source = `if (x > 0) { writeln("Positive"); }`;
  165. string source = q"[
  166. if (x > 0) {
  167. writeln("Positive");
  168. }
  169. ]";
  170. auto tokens = tokenize(source);
  171. writeln(tokens);
  172. parse(tokens);
  173. return 1;
  174. }
  175. unittest{
  176. assert( is_valid_argv([]) == false );
  177. assert( is_valid_argv([""]) == false );
  178. assert( is_valid_argv(["-t"]) == true );
  179. assert( is_valid_argv(["-d"]) == false );
  180. assert( is_valid_argv(["-d", ""]) == false );
  181. assert( is_valid_argv(["-d", "/test"]) == true );
  182. assert( is_valid_argv(["-d", "/test", "-o", "/test2"]) == true );
  183. assert( is_valid_argv(["test.de"]) == true );
  184. assert( is_valid_argv(["-f", "test.de"]) == true );
  185. assert( is_valid_argv(["-f", "test.de", "-o", "test.d"]) == true );
  186. assert( is_valid_argv(["test.txt"]) == false );
  187. assert( is_valid_argv(["-f", "test.txt"]) == false );
  188. assert( is_valid_argv(["-f", "test.txt", "-o", "test.d"]) == false );
  189. assert( is_valid_argv(["-f", "test.de", "-o", "test.txt"]) == false );
  190. }
  191. // ./dopp -t == shortened for test (onto single .de -> .d module)
  192. // ./dopp -d "/test" -o "/test2" == input dir path + output dir path (default output dir = input dir)
  193. // ./dopp -f test.de -o test.d == input file name + output file name (default output file name = input file name [but .d instead .de] )
  194. // ./dopp -f "/test/test.de" -o "/result/test.d" == input file path + output file path (default output file name and path = input file name and path [but .d instead .de] )