@@ -158,75 +158,153 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
158
158
static std::string nameToString(Name &&name) { return name.ToString(); }
159
159
160
160
TYPE_PARSER(sourced(construct<OmpTraitPropertyName>( //
161
- (space >> charLiteralConstantWithoutKind) ||
162
- applyFunction(nameToString, Parser<Name>{}))))
161
+ construct<OmpTraitPropertyName>(space >> charLiteralConstantWithoutKind) ||
162
+ construct<OmpTraitPropertyName>(
163
+ applyFunction(nameToString, Parser<Name>{})))))
163
164
164
165
TYPE_PARSER(sourced(construct<OmpTraitScore>( //
165
- "SCORE" >> parenthesized(scalarIntExpr))))
166
+ "SCORE"_id >> parenthesized(scalarIntExpr))))
166
167
167
- TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension::ExtensionValue>(
168
- // Parse nested extension first.
169
- construct<OmpTraitPropertyExtension::ExtensionValue>(
170
- indirect(Parser<OmpTraitPropertyExtension>{})) ||
171
- construct<OmpTraitPropertyExtension::ExtensionValue>(
172
- Parser<OmpTraitPropertyName>{}) ||
173
- construct<OmpTraitPropertyExtension::ExtensionValue>(scalarExpr))))
174
-
175
- TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension>( //
168
+ TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension::Complex>(
176
169
Parser<OmpTraitPropertyName>{},
177
170
parenthesized(nonemptySeparated(
178
- Parser<OmpTraitPropertyExtension::ExtensionValue >{}, ","_tok )))))
171
+ indirect( Parser<OmpTraitPropertyExtension>{}) , ",")))))
179
172
180
- TYPE_PARSER(sourced(construct<OmpTraitProperty>(
181
- // Try clause first, then extension before OmpTraitPropertyName.
182
- construct<OmpTraitProperty>(indirect(Parser<OmpClause>{})) ||
183
- construct<OmpTraitProperty>(Parser<OmpTraitPropertyExtension>{}) ||
184
- construct<OmpTraitProperty>(Parser<OmpTraitPropertyName>{}) ||
185
- construct<OmpTraitProperty>(scalarExpr))))
173
+ TYPE_PARSER(sourced(construct<OmpTraitPropertyExtension>(
174
+ construct<OmpTraitPropertyExtension>(
175
+ Parser<OmpTraitPropertyExtension::Complex>{}) ||
176
+ construct<OmpTraitPropertyExtension>(Parser<OmpTraitPropertyName>{}) ||
177
+ construct<OmpTraitPropertyExtension>(scalarExpr))))
186
178
187
179
TYPE_PARSER(construct<OmpTraitSelectorName::Value>(
188
- "ARCH" >> pure(OmpTraitSelectorName::Value::Arch) ||
189
- "ATOMIC_DEFAULT_MEM_ORDER" >>
180
+ "ARCH"_id >> pure(OmpTraitSelectorName::Value::Arch) ||
181
+ "ATOMIC_DEFAULT_MEM_ORDER"_id >>
190
182
pure(OmpTraitSelectorName::Value::Atomic_Default_Mem_Order) ||
191
- "CONDITION" >> pure(OmpTraitSelectorName::Value::Condition) ||
192
- "DEVICE_NUM" >> pure(OmpTraitSelectorName::Value::Device_Num) ||
193
- "EXTENSION" >> pure(OmpTraitSelectorName::Value::Extension) ||
194
- "ISA" >> pure(OmpTraitSelectorName::Value::Isa) ||
195
- "KIND" >> pure(OmpTraitSelectorName::Value::Kind) ||
196
- "REQUIRES" >> pure(OmpTraitSelectorName::Value::Requires) ||
197
- "SIMD" >> pure(OmpTraitSelectorName::Value::Simd) ||
198
- "UID" >> pure(OmpTraitSelectorName::Value::Uid) ||
199
- "VENDOR" >> pure(OmpTraitSelectorName::Value::Vendor)))
183
+ "CONDITION"_id >> pure(OmpTraitSelectorName::Value::Condition) ||
184
+ "DEVICE_NUM"_id >> pure(OmpTraitSelectorName::Value::Device_Num) ||
185
+ "EXTENSION"_id >> pure(OmpTraitSelectorName::Value::Extension) ||
186
+ "ISA"_id >> pure(OmpTraitSelectorName::Value::Isa) ||
187
+ "KIND"_id >> pure(OmpTraitSelectorName::Value::Kind) ||
188
+ "REQUIRES"_id >> pure(OmpTraitSelectorName::Value::Requires) ||
189
+ "SIMD"_id >> pure(OmpTraitSelectorName::Value::Simd) ||
190
+ "UID"_id >> pure(OmpTraitSelectorName::Value::Uid) ||
191
+ "VENDOR"_id >> pure(OmpTraitSelectorName::Value::Vendor)))
200
192
201
193
TYPE_PARSER(sourced(construct<OmpTraitSelectorName>(
202
194
// Parse predefined names first (because of SIMD).
203
195
construct<OmpTraitSelectorName>(Parser<OmpTraitSelectorName::Value>{}) ||
204
- construct<OmpTraitSelectorName>(OmpDirectiveNameParser{}))))
196
+ construct<OmpTraitSelectorName>(OmpDirectiveNameParser{}) ||
197
+ // identifier-or-string for extensions
198
+ construct<OmpTraitSelectorName>(
199
+ applyFunction(nameToString, Parser<Name>{})) ||
200
+ construct<OmpTraitSelectorName>(space >> charLiteralConstantWithoutKind))))
201
+
202
+ // Parser for OmpTraitSelector::Properties
203
+ template <typename... PropParser>
204
+ static constexpr auto propertyListParser(PropParser... pp) {
205
+ // Parse the property list "(score(expr): item1...)" in three steps:
206
+ // 1. Parse the "("
207
+ // 2. Parse the optional "score(expr):"
208
+ // 3. Parse the "item1, ...)", together with the ")".
209
+ // The reason for including the ")" in the 3rd step is to force parsing
210
+ // the entire list in each of the alternative property parsers. Otherwise,
211
+ // the name parser could stop after "foo" in "(foo, bar(1))", without
212
+ // allowing the next parser to give the list a try.
213
+ auto listOf{[](auto parser) { //
214
+ return nonemptySeparated(parser, ",");
215
+ }};
216
+
217
+ using P = OmpTraitProperty;
218
+ return maybe("(" >> //
219
+ construct<OmpTraitSelector::Properties>(
220
+ maybe(Parser<OmpTraitScore>{} / ":"),
221
+ (attempt(listOf(sourced(construct<P>(pp))) / ")") || ...)));
222
+ }
223
+
224
+ // Parser for OmpTraitSelector
225
+ struct TraitSelectorParser {
226
+ using resultType = OmpTraitSelector;
227
+
228
+ constexpr TraitSelectorParser(Parser<OmpTraitSelectorName> p) : np(p) {}
205
229
206
- TYPE_PARSER(construct<OmpTraitSelector::Properties>(
207
- maybe(Parser<OmpTraitScore>{} / ":"_tok),
208
- nonemptySeparated(Parser<OmpTraitProperty>{}, ","_tok)))
230
+ std::optional<resultType> Parse(ParseState &state) const {
231
+ auto name{attempt(np).Parse(state)};
232
+ if (!name.has_value()) {
233
+ return std::nullopt;
234
+ }
235
+
236
+ // Default fallback parser for lists that cannot be parser using the
237
+ // primary property parser.
238
+ auto extParser{Parser<OmpTraitPropertyExtension>{}};
239
+
240
+ if (auto *v{std::get_if<OmpTraitSelectorName::Value>(&name->u)}) {
241
+ // (*) The comments below show the sections of the OpenMP spec that
242
+ // describe given trait. The cases marked with a (*) are those where
243
+ // the spec doesn't assign any list-type to these traits, but for
244
+ // convenience they can be treated as if they were.
245
+ switch (*v) {
246
+ // name-list properties
247
+ case OmpTraitSelectorName::Value::Arch: // [6.0:319:18]
248
+ case OmpTraitSelectorName::Value::Extension: // [6.0:319:30]
249
+ case OmpTraitSelectorName::Value::Isa: // [6.0:319:15]
250
+ case OmpTraitSelectorName::Value::Kind: // [6.0:319:10]
251
+ case OmpTraitSelectorName::Value::Uid: // [6.0:319:23](*)
252
+ case OmpTraitSelectorName::Value::Vendor: { // [6.0:319:27]
253
+ auto pp{propertyListParser(Parser<OmpTraitPropertyName>{}, extParser)};
254
+ return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state)));
255
+ }
256
+ // clause-list
257
+ case OmpTraitSelectorName::Value::Atomic_Default_Mem_Order:
258
+ // [6.0:321:26-29](*)
259
+ case OmpTraitSelectorName::Value::Requires: // [6.0:319:33]
260
+ case OmpTraitSelectorName::Value::Simd: { // [6.0:318:31]
261
+ auto pp{propertyListParser(indirect(Parser<OmpClause>{}), extParser)};
262
+ return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state)));
263
+ }
264
+ // expr-list
265
+ case OmpTraitSelectorName::Value::Condition: // [6.0:321:33](*)
266
+ case OmpTraitSelectorName::Value::Device_Num: { // [6.0:321:23-24](*)
267
+ auto pp{propertyListParser(scalarExpr, extParser)};
268
+ return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state)));
269
+ }
270
+ } // switch
271
+ } else {
272
+ // The other alternatives are `llvm::omp::Directive`, and `std::string`.
273
+ // The former doesn't take any properties[1], the latter is a name of an
274
+ // extension[2].
275
+ // [1] [6.0:319:1-2]
276
+ // [2] [6.0:319:36-37]
277
+ auto pp{propertyListParser(extParser)};
278
+ return OmpTraitSelector(std::move(*name), std::move(*pp.Parse(state)));
279
+ }
280
+
281
+ llvm_unreachable("Unhandled trait name?");
282
+ }
283
+
284
+ private:
285
+ const Parser<OmpTraitSelectorName> np;
286
+ };
209
287
210
- TYPE_PARSER(sourced(construct<OmpTraitSelector>( //
211
- Parser<OmpTraitSelectorName>{}, //
212
- maybe(parenthesized(Parser<OmpTraitSelector::Properties>{})))))
288
+ TYPE_PARSER(sourced(construct<OmpTraitSelector>(
289
+ sourced(TraitSelectorParser(Parser<OmpTraitSelectorName>{})))))
213
290
214
291
TYPE_PARSER(construct<OmpTraitSetSelectorName::Value>(
215
- "CONSTRUCT" >> pure(OmpTraitSetSelectorName::Value::Construct) ||
216
- "DEVICE" >> pure(OmpTraitSetSelectorName::Value::Device) ||
217
- "IMPLEMENTATION" >> pure(OmpTraitSetSelectorName::Value::Implementation) ||
218
- "TARGET_DEVICE" >> pure(OmpTraitSetSelectorName::Value::Target_Device) ||
219
- "USER" >> pure(OmpTraitSetSelectorName::Value::User)))
292
+ "CONSTRUCT"_id >> pure(OmpTraitSetSelectorName::Value::Construct) ||
293
+ "DEVICE"_id >> pure(OmpTraitSetSelectorName::Value::Device) ||
294
+ "IMPLEMENTATION"_id >>
295
+ pure(OmpTraitSetSelectorName::Value::Implementation) ||
296
+ "TARGET_DEVICE"_id >> pure(OmpTraitSetSelectorName::Value::Target_Device) ||
297
+ "USER"_id >> pure(OmpTraitSetSelectorName::Value::User)))
220
298
221
299
TYPE_PARSER(sourced(construct<OmpTraitSetSelectorName>(
222
300
Parser<OmpTraitSetSelectorName::Value>{})))
223
301
224
302
TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( //
225
303
Parser<OmpTraitSetSelectorName>{},
226
- "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","_tok )))))
304
+ "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ",")))))
227
305
228
306
TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>(
229
- nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","_tok ))))
307
+ nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","))))
230
308
231
309
// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
232
310
0 commit comments