| 146 | } |
| 147 | |
| 148 | void FinalizeAttr(StringPiece spec, OpDef* op_def, |
| 149 | std::vector<string>* errors) { |
| 150 | OpDef::AttrDef* attr = op_def->add_attr(); |
| 151 | StringPiece orig(spec); |
| 152 | |
| 153 | // Parse "<name>:" at the beginning. |
| 154 | StringPiece tmp_name; |
| 155 | VERIFY(ConsumeAttrName(&spec, &tmp_name), "Trouble parsing '<name>:'"); |
| 156 | attr->set_name(tmp_name.data(), tmp_name.size()); |
| 157 | |
| 158 | // Read "<type>" or "list(<type>)". |
| 159 | bool is_list = ConsumeListPrefix(&spec); |
| 160 | string type; |
| 161 | StringPiece type_string; // Used if type == "type" |
| 162 | if (absl::ConsumePrefix(&spec, "string")) { |
| 163 | type = "string"; |
| 164 | } else if (absl::ConsumePrefix(&spec, "int")) { |
| 165 | type = "int"; |
| 166 | } else if (absl::ConsumePrefix(&spec, "float")) { |
| 167 | type = "float"; |
| 168 | } else if (absl::ConsumePrefix(&spec, "bool")) { |
| 169 | type = "bool"; |
| 170 | } else if (absl::ConsumePrefix(&spec, "type")) { |
| 171 | type = "type"; |
| 172 | } else if (absl::ConsumePrefix(&spec, "shape")) { |
| 173 | type = "shape"; |
| 174 | } else if (absl::ConsumePrefix(&spec, "tensor")) { |
| 175 | type = "tensor"; |
| 176 | } else if (absl::ConsumePrefix(&spec, "func")) { |
| 177 | type = "func"; |
| 178 | } else if (ConsumeCompoundAttrType(&spec, &type_string)) { |
| 179 | type = "type"; |
| 180 | AttrValue* allowed = attr->mutable_allowed_values(); |
| 181 | VERIFY(ProcessCompoundType(type_string, allowed), |
| 182 | "Expected to see a compound type, saw: ", type_string); |
| 183 | } else if (absl::ConsumePrefix(&spec, "{")) { |
| 184 | // e.g. "{ int32, float, bool }" or "{ \"foo\", \"bar\" }" |
| 185 | AttrValue* allowed = attr->mutable_allowed_values(); |
| 186 | str_util::RemoveLeadingWhitespace(&spec); |
| 187 | if (absl::StartsWith(spec, "\"") || absl::StartsWith(spec, "'")) { |
| 188 | type = "string"; // "{ \"foo\", \"bar\" }" or "{ 'foo', 'bar' }" |
| 189 | while (true) { |
| 190 | StringPiece escaped_string; |
| 191 | VERIFY(ConsumeQuotedString('"', &spec, &escaped_string) || |
| 192 | ConsumeQuotedString('\'', &spec, &escaped_string), |
| 193 | "Trouble parsing allowed string at '", spec, "'"); |
| 194 | string unescaped; |
| 195 | string error; |
| 196 | VERIFY(absl::CUnescape(escaped_string, &unescaped, &error), |
| 197 | "Trouble unescaping \"", escaped_string, |
| 198 | "\", got error: ", error); |
| 199 | allowed->mutable_list()->add_s(unescaped); |
| 200 | if (absl::ConsumePrefix(&spec, ",")) { |
| 201 | str_util::RemoveLeadingWhitespace(&spec); |
| 202 | if (absl::ConsumePrefix(&spec, "}")) |
| 203 | break; // Allow ending with ", }". |
| 204 | } else { |
| 205 | VERIFY(absl::ConsumePrefix(&spec, "}"), |
no test coverage detected