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 }