class IdentifierGlob
Defined at line 106 of file ../../src/developer/debug/zxdb/expr/identifier_glob.h
Provides a simple very-restricted Glob-like syntax for matching template types.
For the requirements of the pretty-printing system, we want to be able to match different
template types but in a type-aware manner.
For example, say we were to write a pretty-printer matching the glob "MyClass<*>" with a normal
string-based matcher. It would match "MyClass<int>" as desired. But it would also match things
like nested templates such as "MyClass<int>::Ref<Foo>" which is not desirable.
So this class provides a way to match "*" for template type parameters ONLY in a manner that's
aware of the syntax of template definitions. Since type matching doesn't need to match things
like "all type names tarting with the letter 'a'", "*" never matches anything other than template
parameters.
Syntax
------
There is only one special character: *
- All non-template parameters must match exactly (case sensitive).
- A '*' normally matches EXACTLY ONE template parameter.
- If the LAST template parameter in a glob is a "*", it will match ALL REMAINING template
parameters.
- The "*" must occur by itself as a template parameter to match. So "Foo<*>" a glob matching
any type, but "Foo<int*>" is a literal. This is important because "*" occurs in many type
definitions but never by itself in a language we support.
- It does not work recursively so while "Foo<*>" is "Foo<Bar<*>>" is currently a literal. This
could be changed in the future if needed.
- Global qualifications "::Foo" are ignored. Names are assumed to be globally qualified, unless
|match_any_namespace| is given during initialization.
- When |match_any_namespace| is given, simple names such as "Foo" will match all of
"SomeNamespace::Foo", "OtherNamespace::Foo", and "Foo".
Scoring glob matching
---------------------
Say we have three globs:
[1] MyClass
<float
>
[2] MyClass
<
*>
[3] MyClass
<
*, *>
We have the following requirements:
- The type "MyClass<float>" should preferentially match [1], and secondarily match [2]
- The type "MyClass<int>" will match only [2].
- The type "MyClass<int, float>" and "MyClass<int, float, char>" will preferentially match [3]
and secondarily match [2].
Note that the type "MyClass<>" will match none of the globs. If you wanted to match something
with this name (which is not a valid type name in C++, but is valid in some contexts) you will
need to supply a separate glob with an exact match.
To measure match priority, Matches() computes the number of template parameters the last
encountered wildcard (if any) matches. Better matches have lower scores.
- An exact string match with no wildcard will have a score of 0.
- A single wildcard matching a single template parameter will score 1.
- Two wildcards matching two template parameters will score 1.
- One wildcard matching two template parameters will score 2.
- The glob "Foo<*, Bar>" matching "Foo<int, Bar>" will score 1 (last * matched 1 param).
It's possible to have multiple levels of templates, say with a glob:
MyClass
<
*, *>::Something
<
*>
In this case we return the largest number of matches of the last "*" across all components. So
in this example
- "MyClass<int, int>::Something<int>" will score 1.
- "MyClass<int, int, int>::Something<int>" will score 2.
- "MyClass<int, int>::Something<int, int>" will also score 2 (not clear which is better).
Scoring namespace glob matching
-------------------------------
Say we have three globs:
[1] Foo (where match_any_namespace is true)
[2] MyClass::Foo
[3] Nested::Namespace::Foo
[4] MyClass::Foo
<
*>
The requirements are now:
- A function named "MyClass::Foo" should preferentially match [1], and secondarily match [2].
- A function named "Nested::Namespace::Foo" should preferentially match [3] and secondarily
match [1].
- A function named "MyClass::Foo<int>" is the same as described above. [3] is deferentially
matched, [1] does not match at all.
Match priority is measured similarly to template globs, the score is computed as the number of
namespace scopes that were skipped. Again, better matches have lower scores.
Public Methods
Err Init (const std::string & glob)
An error is returned if the glob could not be parsed. It must be syntactially valid.
Defined at line 57 of file ../../src/developer/debug/zxdb/expr/identifier_glob.cc
Err Init (const std::string & glob, bool match_any_namespace)
Defined at line 59 of file ../../src/developer/debug/zxdb/expr/identifier_glob.cc
std::optional<int> Matches (const ParsedIdentifier & type)
When the glob matches the given type, the match score will be returned. Lower scores are
better matches (see above).
When there is no match, a nullopt will be returned.
Defined at line 64 of file ../../src/developer/debug/zxdb/expr/identifier_glob.cc
void IdentifierGlob ()
Call Init() to initialize with a parsed identifier.
Defined at line 109 of file ../../src/developer/debug/zxdb/expr/identifier_glob.h
void IdentifierGlob (ParsedIdentifier input)
Specify a pre-parsed identifier. This also allows expressing some patterns that won't parse as
normal identifiers (they may be expressed in DWARF).
Defined at line 113 of file ../../src/developer/debug/zxdb/expr/identifier_glob.h