1 /// pbtxt parser
2 module tfd.pbtxt;
3 
4 import pegged.grammar;
5 
6 mixin(grammar(`
7 PbTxt:
8     Root   < Dict*
9 
10     Dict   <  identifier :'{' (Pair / Dict)* :'}'
11 
12     Pair   <  identifier :':' Value
13 
14     Value  <  String
15             / Number
16             / True
17             / False
18             / Enum
19 
20     Enum   <- identifier
21 
22     True   <- "true"
23     False  <- "false"
24 
25     String <~ :doublequote Char* :doublequote
26     Char   <~ backslash doublequote
27             / backslash backslash
28             / backslash [bfnrt]
29             / (!doublequote .)
30 
31     Number <~ Sign? Integer "."? Integer? (("e" / "E") Sign? Integer)?
32     Integer <~ digit+
33     Sign <- "-" / "+"
34 `));
35 
36 
37 version (unittest)
38 enum exampleProto = `
39 op {
40   name: "AddN"
41   input_arg {
42     name: "inputs"
43     type_attr: "T"
44     number_attr: "N"
45   }
46   output_arg {
47     name: "sum"
48     type_attr: "T"
49   }
50   attr {
51     name: "N"
52     type: "int"
53     has_minimum: true
54     minimum: 1
55   }
56   attr {
57     name: "T"
58     type: "type"
59     allowed_values {
60       list {
61         type: DT_FLOAT
62         type: DT_DOUBLE
63         type: DT_INT32
64         type: DT_UINT8
65         type: DT_INT16
66         type: DT_INT8
67         type: DT_COMPLEX64
68         type: DT_INT64
69         type: DT_QINT8
70         type: DT_QUINT8
71         type: DT_QINT32
72         type: DT_BFLOAT16
73         type: DT_UINT16
74         type: DT_COMPLEX128
75         type: DT_HALF
76         type: DT_UINT32
77         type: DT_UINT64
78         type: DT_VARIANT
79       }
80     }
81   }
82   is_aggregate: true
83   is_commutative: true
84 }
85 op {
86   name: "Identity"
87   input_arg {
88     name: "input"
89     type_attr: "T"
90   }
91   output_arg {
92     name: "output"
93     type_attr: "T"
94   }
95   attr {
96     name: "T"
97     type: "type"
98   }
99 }
100 `;
101 
102 
103 unittest
104 {
105   auto tree = PbTxt(exampleProto);
106   assert(tree.successful);
107 
108   auto root = tree.children[0];
109   auto addN = root.children[0];
110   assert(addN.name == "PbTxt.Dict");
111   assert(addN.matches[0] == "op");
112   assert(addN.children[0].matches == ["name", "AddN"]);
113 
114   auto identity = root.children[1];
115   assert(identity.matches[0] == "op");
116   assert(identity.children[0].matches == ["name", "Identity"]);
117 }