Add pseudo-key synonyms for keys like shift, meta, alt, and control. (#33695)

This adds a list of key synonyms for non-printable keyboard keys that appear in more than one place So keys like LogicalKeyboardKey.shiftLeft and LogicalKeyboardKey.shiftRight now can be mapped to just LogicalKeyboardKey.shift.

I also fixed a bug in the gen_keycodes tool where GLFW entries would get removed if they weren't parsed from the source on the web.
diff --git a/dev/tools/gen_keycodes/data/keyboard_key.tmpl b/dev/tools/gen_keycodes/data/keyboard_key.tmpl
index b9bd7b5..f627b78 100644
--- a/dev/tools/gen_keycodes/data/keyboard_key.tmpl
+++ b/dev/tools/gen_keycodes/data/keyboard_key.tmpl
@@ -166,14 +166,6 @@
   /// null, if not found.
   static LogicalKeyboardKey findKeyByKeyId(int keyId) => _knownLogicalKeys[keyId];
 
-  @override
-  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
-    super.debugFillProperties(properties);
-    properties.add(StringProperty('keyId', '0x${keyId.toRadixString(16).padLeft(8, '0')}', showName: true));
-    properties.add(StringProperty('keyLabel', keyLabel, showName: true));
-    properties.add(StringProperty('debugName', debugName, showName: true, defaultValue: null));
-  }
-
   /// Returns true if the given label represents a Unicode control character.
   ///
   /// Examples of control characters are characters like "U+000A LINE FEED (LF)"
@@ -215,10 +207,35 @@
   /// platforms that had a "do what I mean" key from then on.
   bool get isAutogenerated => (keyId & autogeneratedMask) != 0;
 
+  /// Returns a set of pseudo-key synonyms for the given `key`.
+  ///
+  /// This allows finding the pseudo-keys that also represents a concrete
+  /// `key` so that a class with a key map can match pseudo-keys as well as the
+  /// actual generated keys.
+  ///
+  /// The pseudo-keys returned in the set are typically used to represent keys
+  /// which appear in multiple places on the keyboard, such as the [shift],
+  /// [alt], [control], and [meta] keys. The keys in the returned set won't ever
+  /// be generated directly, but if a more specific key event is received, then
+  /// this set can be used to find the more general pseudo-key. For example, if
+  /// this is a [shiftLeft] key, this accessor will return the set
+  /// `<LogicalKeyboardKey>{ shift }`.
+  Set<LogicalKeyboardKey> get synonyms {
+    final LogicalKeyboardKey result = _synonyms[this];
+    return result == null ? <LogicalKeyboardKey>{} : <LogicalKeyboardKey>{result};
+  }
+
+  @override
+  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+    super.debugFillProperties(properties);
+    properties.add(StringProperty('keyId', '0x${keyId.toRadixString(16).padLeft(8, '0')}', showName: true));
+    properties.add(StringProperty('keyLabel', keyLabel, showName: true));
+    properties.add(StringProperty('debugName', debugName, showName: true, defaultValue: null));
+  }
+
   /// Mask for the 32-bit value portion of the key code.
   ///
-  /// This is used by
-  /// platform-specific code to generate Flutter key codes.
+  /// This is used by platform-specific code to generate Flutter key codes.
   static const int valueMask = 0x000FFFFFFFF;
 
   /// Mask for the platform prefix portion of the key code.
@@ -248,6 +265,10 @@
   static const Map<int, LogicalKeyboardKey> _knownLogicalKeys = <int, LogicalKeyboardKey>{
 @@@LOGICAL_KEY_MAP@@@
   };
+
+  // A map of keys to the pseudo-key synonym for that key. Used by getSynonyms.
+  static final Map<LogicalKeyboardKey, LogicalKeyboardKey> _synonyms = <LogicalKeyboardKey, LogicalKeyboardKey>{
+@@@LOGICAL_KEY_SYNONYMS@@@  };
 }
 
 /// A class with static values that describe the keys that are returned from