1 module cfg_grammar_gen;
2 
3 /// PEG grammar for libconfig
4 enum configGrammar = r"
5 # Comments and include directive are not part of this grammar.
6 # They must be handled before the input is given to the PEG parser
7 
8 Config:
9     Document    <   eoi / Setting+
10 
11     Setting     <   Name (':' / '=') Value (';' / ',')?
12 
13     Value       <-  Scalar / Array / List / Group
14     Scalar      <-  Bool / Float / Integer / String    # Float MUST be before Integer
15     Array       <   '[' ( Scalar (',' Scalar)* )? ']'
16     List        <   '(' ( Value (',' Value)* )? ')'
17     Group       <   '{' Setting* '}'
18 
19     Name        <~  [A-Za-z] ( [-A-Za-z0-9_] )*
20 
21     Bool        <~  [Tt] [Rr] [Uu] [Ee] / [Ff] [Aa] [Ll] [Ss] [Ee]
22 
23     Integer     <-  (Hex / Dec) ('LL' / 'L')?
24     Hex         <~  :'0' :[Xx] hexDigit+
25     Dec         <~  [-+]? digits
26 
27     Float       <~  ( [-+]? digit* ^'.' digit* ( [eE] [-+]? digits )? ) /
28                     ( [-+]? digit+ (^'.' digit*)? [eE] [-+]? digits )
29 
30     StringQuot  <~  :doublequote (
31                         backslash backslash /
32                         backslash doublequote /
33                         backslash ^'f' /
34                         backslash ^'n' /
35                         backslash ^'r' /
36                         backslash ^'t' /
37                         !doublequote !backslash .
38                     )* :doublequote
39 
40     String      <~  (StringQuot spacing?)+
41 ";
42 
43 int main(string[] args) {
44     import pegged.grammar : asModule;
45     import std.stdio : stdout, stderr;
46     import std.format : format;
47 
48     if (args.length == 0) args = ["cfg_grammar_gen"];
49 
50     immutable usage = (
51         "usage:\n" ~
52         "    %1$s [Options]\n"  ~
53         "    Options:\n" ~
54         "        -h --help      print this help message\n" ~
55         "        -m --module    grammar module qualified name [mandatory]\n" ~
56         "        -o --output    grammar module filename without extension [mandatory]\n" ~
57         "    Example:\n" ~
58         "        %1$s -m config.grammar -o src/config/grammar\n")
59         .format(args[0]);
60 
61     int reportError(string msg) {
62         stderr.writeln(msg);
63         stderr.writeln(usage);
64         return 1;
65     }
66 
67     string modulefile;
68     string modulename;
69 
70     for (size_t i=0; i<args.length; ++i) {
71         if (args[i] == "-h" || args[i] == "--help") {
72             stdout.writeln(usage);
73             return 0;
74         }
75         if (args[i] == "-m" || args[i] == "--module") {
76             ++i;
77             if (i == args.length) return reportError("missing argument(s)");
78             modulename = args[i];
79         }
80         if (args[i] == "-o" || args[i] == "--output") {
81             ++i;
82             if (i == args.length) return reportError("missing argument(s)");
83             modulefile = args[i];
84         }
85     }
86 
87     if (!modulefile || !modulename) return reportError("missing argument(s)");
88 
89     asModule(modulename, modulefile, configGrammar);
90 
91     return 0;
92 }