@@ -158,75 +158,153 @@ static TypeDeclarationStmt makeIterSpecDecl(std::list<ObjectName> &&names) {
158158static std::string nameToString(Name &&name) { return name.ToString(); }
159159
160160TYPE_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>{})))))
163164
164165TYPE_PARSER(sourced(construct<OmpTraitScore>( //
165- "SCORE" >> parenthesized(scalarIntExpr))))
166+ "SCORE"_id >> parenthesized(scalarIntExpr))))
166167
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>(
176169 Parser<OmpTraitPropertyName>{},
177170 parenthesized(nonemptySeparated(
178- Parser<OmpTraitPropertyExtension::ExtensionValue >{}, ","_tok )))))
171+ indirect( Parser<OmpTraitPropertyExtension>{}) , ",")))))
179172
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))))
186178
187179TYPE_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 >>
190182 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)))
200192
201193TYPE_PARSER(sourced(construct<OmpTraitSelectorName>(
202194 // Parse predefined names first (because of SIMD).
203195 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) {}
205229
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+ };
209287
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>{})))))
213290
214291TYPE_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)))
220298
221299TYPE_PARSER(sourced(construct<OmpTraitSetSelectorName>(
222300 Parser<OmpTraitSetSelectorName::Value>{})))
223301
224302TYPE_PARSER(sourced(construct<OmpTraitSetSelector>( //
225303 Parser<OmpTraitSetSelectorName>{},
226- "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ","_tok )))))
304+ "=" >> braced(nonemptySeparated(Parser<OmpTraitSelector>{}, ",")))))
227305
228306TYPE_PARSER(sourced(construct<OmpContextSelectorSpecification>(
229- nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","_tok ))))
307+ nonemptySeparated(Parser<OmpTraitSetSelector>{}, ","))))
230308
231309// Parser<OmpContextSelector> == Parser<traits::OmpContextSelectorSpecification>
232310
0 commit comments