[vscode] Add type constructor syntax highlighting

This change makes 3 related improvements:
* The `layout-member-*`-like repository definitions are all simplified
  by extracting out a new repository definition group,
  `type-constructor-*`, which handles highlighting for type constructors
  separately. All locations that make use of type constructors save
  type aliases are modified to use this new definition instead of trying
  to match type constructor shapes manually.
* Type parameter matchers are simplified. This is possible because we
  will always have 1 or 2 elements in a type parameter list: a type
  constructor (or protocol, which for highlighting purposes can be
  considered equivalent), and optionally a numerical constant (if the
  parameterized type is an array, like `array<Foo, 5>`).
* Named payloads are highlighted as types. This is also made possible by
  the type constructor refactor described above, as all
  `method-argument` patterns are now just `type-constructor`.

Change-Id: Ia1c18427c349fa15252fb6d08cbef726fb8be098
Reviewed-on: https://fuchsia-review.googlesource.com/c/fidl-misc/+/661809
Reviewed-by: Mitchell Kember <mkember@google.com>
diff --git a/vscode-language-fidl/syntaxes/fidl.tmLanguage.json b/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
index 76c83da..4f4cc7e 100644
--- a/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
+++ b/vscode-language-fidl/syntaxes/fidl.tmLanguage.json
@@ -189,7 +189,30 @@
             ]
         },
         {
-            "include": "#layout-introduction"
+            "name": "meta.type.fidl",
+            "begin": "\\b(type)\\b\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)",
+            "beginCaptures": {
+                "1": {
+                    "name": "keyword.control"
+                },
+                "2": {
+                    "name": "entity.name.type"
+                },
+                "3": {
+                    "name": "punctuation.separator"
+                }
+            },
+            "end": "(;)",
+            "endCaptures": {
+                "1": {
+                    "name": "punctuation.terminator"
+                }
+            },
+            "patterns": [
+                {
+                    "include": "#type-constructor"
+                }
+            ]
         }
     ],
     "repository": {
@@ -354,162 +377,74 @@
                 }
             ]
         },
+        "default-value": {
+            "patterns": [
+                {
+                    "name": "meta.separator.fidl",
+                    "match": "(=)",
+                    "captures": {
+                        "1": {
+                            "name": "punctuation.separator"
+                        }
+                    }
+                },
+                {
+                    "include": "#const-value"
+                }
+            ]
+        },
         "method-argument": {
             "patterns": [
                 {
                     "name": "meta.method.arguments.fidl",
-                    "begin": "\\(\\s*(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
-                    "beginCaptures": {
-                        "1": {
-                            "name": "storage.type.modifier"
-                        },
-                        "2": {
-                            "name": "storage.type.modifier"
-                        },
-                        "3": {
-                            "name": "storage.type.modifier"
-                        },
-                        "4": {
-                            "name": "keyword.control"
-                        },
-                        "5": {
-                            "name": "keyword.control"
-                        },
-                        "6": {
-                            "name": "keyword.control"
-                        },
-                        "7": {
-                            "name": "keyword.control"
-                        },
-                        "8": {
-                            "name": "keyword.control"
-                        },
-                        "9": {
-                            "name": "punctuation.separator"
-                        },
-                        "10": {
-                            "name": "entity.name.type"
-                        }
-                    },
-                    "end": "}\\)",
+                    "begin": "\\(",
+                    "beginCaptures": {},
+                    "end": "\\)",
                     "endCaptures": {},
                     "patterns": [
                         {
-                            "include": "#comments"
-                        },
-                        {
-                            "include": "#attributes"
-                        },
-                        {
-                            "include": "#layout-member"
+                            "include": "#type-constructor"
                         }
                     ]
                 }
             ]
         },
-        "layout-introduction": {
-            "name": "meta.inline-layout-block.fidl",
-            "begin": "\\b(type)\\b\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(=)\\s*(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
-            "beginCaptures": {
-                "1": {
-                    "name": "keyword.control"
-                },
-                "2": {
-                    "name": "entity.name.type"
-                },
-                "3": {
-                    "name": "punctuation.separator"
-                },
-                "4": {
-                    "name": "storage.type.modifier"
-                },
-                "5": {
-                    "name": "storage.type.modifier"
-                },
-                "6": {
-                    "name": "storage.type.modifier"
-                },
-                "7": {
-                    "name": "keyword.control"
-                },
-                "8": {
-                    "name": "keyword.control"
-                },
-                "9": {
-                    "name": "keyword.control"
-                },
-                "10": {
-                    "name": "keyword.control"
-                },
-                "11": {
-                    "name": "keyword.control"
-                },
-                "12": {
-                    "name": "punctuation.separator"
-                },
-                "13": {
-                    "name": "entity.name.type"
-                }
-            },
-            "end": "}",
-            "endCaptures": {},
+        "type-constructor": {
             "patterns": [
                 {
-                    "include": "#comments"
+                    "include": "#type-constructor-inline"
                 },
                 {
-                    "include": "#attributes"
+                    "include": "#type-constructor-inline-arg"
                 },
                 {
-                    "include": "#layout-member"
+                    "include": "#type-constructor-reference"
                 }
             ]
         },
-        "layout-member": {
+        "type-constructor-inline": {
             "patterns": [
                 {
-                    "include": "#layout-member-inline"
-                },
-                {
-                    "include": "#layout-member-default"
-                },
-                {
-                    "include": "#layout-member-reference"
-                },
-                {
-                    "include": "#layout-member-inline-arg"
-                },
-                {
-                    "include": "#layout-member-value"
-                },
-                {
-                    "include": "#layout-member-reserved"
-                }
-            ]
-        },
-        "layout-member-inline": {
-            "patterns": [
-                {
-                    "name": "meta.layout.member.fidl",
-                    "begin": "(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:))?\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
+                    "name": "meta.type-constructor-inline.fidl",
+                    "begin": "(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
                     "beginCaptures": {
                         "1": {
-                            "name": "constant.numeric"
+                            "name": "storage.type.modifier"
                         },
                         "2": {
-                            "name": "punctuation.separator"
+                            "name": "storage.type.modifier"
                         },
                         "3": {
-                            "name": "variable"
+                            "name": "storage.type.modifier"
                         },
                         "4": {
-                            "name": "storage.type.modifier"
+                            "name": "keyword.control"
                         },
                         "5": {
-                            "name": "storage.type.modifier"
+                            "name": "keyword.control"
                         },
                         "6": {
-                            "name": "storage.type.modifier"
+                            "name": "keyword.control"
                         },
                         "7": {
                             "name": "keyword.control"
@@ -518,22 +453,13 @@
                             "name": "keyword.control"
                         },
                         "9": {
-                            "name": "keyword.control"
-                        },
-                        "10": {
-                            "name": "keyword.control"
-                        },
-                        "11": {
-                            "name": "keyword.control"
-                        },
-                        "12": {
                             "name": "punctuation.separator"
                         },
-                        "13": {
+                        "10": {
                             "name": "entity.name.type"
                         }
                     },
-                    "end": "}\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?\\s*(;)",
+                    "end": "}\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?",
                     "endCaptures": {
                         "1": {
                             "name": "storage.type.constraint"
@@ -576,9 +502,6 @@
                         },
                         "14": {
                             "name": "punctuation.bracket.angle"
-                        },
-                        "15": {
-                            "name": "punctuation.terminator"
                         }
                     },
                     "patterns": [
@@ -595,20 +518,236 @@
                 }
             ]
         },
-        "layout-member-default": {
+        "type-constructor-inline-arg": {
             "patterns": [
                 {
-                    "name": "meta.layout.struct-member.fidl",
-                    "begin": "(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(\\b(?:bool|float32|float64|int8|int16|int32|int64|uint8|uint16|uint32|uint64)\\b)\\s*(=)",
+                    "name": "meta.type-constructor-inline-arg.fidl",
+                    "begin": "(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*<\\s*(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
                     "beginCaptures": {
                         "1": {
-                            "name": "variable"
+                            "name": "entity.name.type"
                         },
                         "2": {
-                            "name": "storage.type.basic"
+                            "name": "storage.type.modifier"
                         },
                         "3": {
+                            "name": "storage.type.modifier"
+                        },
+                        "4": {
+                            "name": "storage.type.modifier"
+                        },
+                        "5": {
+                            "name": "keyword.control"
+                        },
+                        "6": {
+                            "name": "keyword.control"
+                        },
+                        "7": {
+                            "name": "keyword.control"
+                        },
+                        "8": {
+                            "name": "keyword.control"
+                        },
+                        "9": {
+                            "name": "keyword.control"
+                        },
+                        "10": {
                             "name": "punctuation.separator"
+                        },
+                        "11": {
+                            "name": "entity.name.type"
+                        }
+                    },
+                    "end": "(?:,\\s*(?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*>\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?",
+                    "endCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "constant.language"
+                        },
+                        "3": {
+                            "name": "string.quoted.double"
+                        },
+                        "4": {
+                            "name": "storage.type.constraint"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "constant.language"
+                        },
+                        "7": {
+                            "name": "string.quoted.double"
+                        },
+                        "8": {
+                            "name": "punctuation.bracket.angle"
+                        },
+                        "9": {
+                            "name": "storage.type.constraint"
+                        },
+                        "10": {
+                            "name": "constant.numeric"
+                        },
+                        "11": {
+                            "name": "constant.language"
+                        },
+                        "12": {
+                            "name": "string.quoted.double"
+                        },
+                        "13": {
+                            "name": "storage.type.constraint"
+                        },
+                        "14": {
+                            "name": "constant.numeric"
+                        },
+                        "15": {
+                            "name": "constant.language"
+                        },
+                        "16": {
+                            "name": "string.quoted.double"
+                        },
+                        "17": {
+                            "name": "punctuation.bracket.angle"
+                        }
+                    },
+                    "patterns": [
+                        {
+                            "include": "#comments"
+                        },
+                        {
+                            "include": "#attributes"
+                        },
+                        {
+                            "include": "#layout-member"
+                        }
+                    ]
+                }
+            ]
+        },
+        "type-constructor-reference": {
+            "patterns": [
+                {
+                    "name": "meta.type-constructor-reference.fidl",
+                    "match": "(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*(?:(<)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*(?:(,)\\s*(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*(>))?\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?",
+                    "captures": {
+                        "1": {
+                            "name": "entity.name.type"
+                        },
+                        "2": {
+                            "name": "punctuation.bracket.angle"
+                        },
+                        "3": {
+                            "name": "entity.name.type"
+                        },
+                        "4": {
+                            "name": "punctuation.separator"
+                        },
+                        "5": {
+                            "name": "constant.numeric"
+                        },
+                        "6": {
+                            "name": "punctuation.bracket.angle"
+                        },
+                        "7": {
+                            "name": "storage.type.constraint"
+                        },
+                        "8": {
+                            "name": "constant.numeric"
+                        },
+                        "9": {
+                            "name": "constant.language"
+                        },
+                        "10": {
+                            "name": "string.quoted.double"
+                        },
+                        "11": {
+                            "name": "punctuation.bracket.angle"
+                        },
+                        "12": {
+                            "name": "storage.type.constraint"
+                        },
+                        "13": {
+                            "name": "constant.numeric"
+                        },
+                        "14": {
+                            "name": "constant.language"
+                        },
+                        "15": {
+                            "name": "string.quoted.double"
+                        },
+                        "16": {
+                            "name": "storage.type.constraint"
+                        },
+                        "17": {
+                            "name": "constant.numeric"
+                        },
+                        "18": {
+                            "name": "constant.language"
+                        },
+                        "19": {
+                            "name": "string.quoted.double"
+                        },
+                        "20": {
+                            "name": "punctuation.bracket.angle"
+                        }
+                    }
+                }
+            ]
+        },
+        "layout-member": {
+            "patterns": [
+                {
+                    "include": "#layout-member-reserved"
+                },
+                {
+                    "include": "#layout-member-value"
+                },
+                {
+                    "include": "#layout-member-struct"
+                },
+                {
+                    "include": "#layout-member-ordinaled"
+                }
+            ]
+        },
+        "layout-member-reserved": {
+            "patterns": [
+                {
+                    "name": "meta.layout.reserved-member.fidl",
+                    "match": "(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:)\\s*\\b(reserved)\\b\\s*(;)",
+                    "captures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "punctuation.separator"
+                        },
+                        "3": {
+                            "name": "keyword.control"
+                        },
+                        "4": {
+                            "name": "punctuation.terminator"
+                        }
+                    }
+                }
+            ]
+        },
+        "layout-member-ordinaled": {
+            "patterns": [
+                {
+                    "name": "meta.layout.ordinaled-member.fidl",
+                    "begin": "(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)",
+                    "beginCaptures": {
+                        "1": {
+                            "name": "constant.numeric"
+                        },
+                        "2": {
+                            "name": "punctuation.separator"
+                        },
+                        "3": {
+                            "name": "variable"
                         }
                     },
                     "end": "(;)",
@@ -619,218 +758,34 @@
                     },
                     "patterns": [
                         {
-                            "include": "#const-value"
+                            "include": "#type-constructor"
                         }
                     ]
                 }
             ]
         },
-        "layout-member-reference": {
+        "layout-member-struct": {
             "patterns": [
                 {
-                    "name": "meta.layout.member.fidl",
-                    "match": "(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:))?\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*(?:(<)\\s*(?:(?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))(?:,\\s*(?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))*\\s*(>))?\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?\\s*(;)",
-                    "captures": {
-                        "1": {
-                            "name": "constant.numeric"
-                        },
-                        "2": {
-                            "name": "punctuation.separator"
-                        },
-                        "3": {
-                            "name": "variable"
-                        },
-                        "4": {
-                            "name": "entity.name.type"
-                        },
-                        "5": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "6": {
-                            "name": "constant.numeric"
-                        },
-                        "7": {
-                            "name": "constant.language"
-                        },
-                        "8": {
-                            "name": "string.quoted.double"
-                        },
-                        "9": {
-                            "name": "constant.numeric"
-                        },
-                        "10": {
-                            "name": "constant.language"
-                        },
-                        "11": {
-                            "name": "string.quoted.double"
-                        },
-                        "12": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "13": {
-                            "name": "storage.type.constraint"
-                        },
-                        "14": {
-                            "name": "constant.numeric"
-                        },
-                        "15": {
-                            "name": "constant.language"
-                        },
-                        "16": {
-                            "name": "string.quoted.double"
-                        },
-                        "17": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "18": {
-                            "name": "storage.type.constraint"
-                        },
-                        "19": {
-                            "name": "constant.numeric"
-                        },
-                        "20": {
-                            "name": "constant.language"
-                        },
-                        "21": {
-                            "name": "string.quoted.double"
-                        },
-                        "22": {
-                            "name": "storage.type.constraint"
-                        },
-                        "23": {
-                            "name": "constant.numeric"
-                        },
-                        "24": {
-                            "name": "constant.language"
-                        },
-                        "25": {
-                            "name": "string.quoted.double"
-                        },
-                        "26": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "27": {
-                            "name": "punctuation.terminator"
-                        }
-                    }
-                }
-            ]
-        },
-        "layout-member-inline-arg": {
-            "patterns": [
-                {
-                    "name": "meta.layout.member.fidl",
-                    "begin": "(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:))?\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)\\s*<\\s*(?:(?:\\b(strict)\\b|\\b(flexible)\\b|\\b(resource)\\b)\\s*)*\\s*(?:\\b(union)\\b|\\b(struct)\\b|\\b(table)\\b|\\b(enum)\\b|\\b(bits)\\b)\\s*(?:(:)\\s*(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*{",
+                    "name": "meta.layout.struct-struct-member.fidl",
+                    "begin": "(\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)",
                     "beginCaptures": {
                         "1": {
-                            "name": "constant.numeric"
-                        },
-                        "2": {
-                            "name": "punctuation.separator"
-                        },
-                        "3": {
                             "name": "variable"
-                        },
-                        "4": {
-                            "name": "entity.name.type"
-                        },
-                        "5": {
-                            "name": "storage.type.modifier"
-                        },
-                        "6": {
-                            "name": "storage.type.modifier"
-                        },
-                        "7": {
-                            "name": "storage.type.modifier"
-                        },
-                        "8": {
-                            "name": "keyword.control"
-                        },
-                        "9": {
-                            "name": "keyword.control"
-                        },
-                        "10": {
-                            "name": "keyword.control"
-                        },
-                        "11": {
-                            "name": "keyword.control"
-                        },
-                        "12": {
-                            "name": "keyword.control"
-                        },
-                        "13": {
-                            "name": "punctuation.separator"
-                        },
-                        "14": {
-                            "name": "entity.name.type"
                         }
                     },
-                    "end": "(?:,\\s*(?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))?\\s*>\\s*(?::\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*))|(<)\\s*(?:((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))(?:,\\s*((?:(?:(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)|(\\b(?:true|false)\\b)|(\"(?:[^\\\"]|\\.)*\"))|\\b[a-zA-Z_][0-9a-zA-Z_]*\\b(?:\\.\\b[a-zA-Z_][0-9a-zA-Z_]*\\b)*)))*\\s*(>)))?\\s*(;)",
+                    "end": "(;)",
                     "endCaptures": {
                         "1": {
-                            "name": "constant.numeric"
-                        },
-                        "2": {
-                            "name": "constant.language"
-                        },
-                        "3": {
-                            "name": "string.quoted.double"
-                        },
-                        "4": {
-                            "name": "storage.type.constraint"
-                        },
-                        "5": {
-                            "name": "constant.numeric"
-                        },
-                        "6": {
-                            "name": "constant.language"
-                        },
-                        "7": {
-                            "name": "string.quoted.double"
-                        },
-                        "8": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "9": {
-                            "name": "storage.type.constraint"
-                        },
-                        "10": {
-                            "name": "constant.numeric"
-                        },
-                        "11": {
-                            "name": "constant.language"
-                        },
-                        "12": {
-                            "name": "string.quoted.double"
-                        },
-                        "13": {
-                            "name": "storage.type.constraint"
-                        },
-                        "14": {
-                            "name": "constant.numeric"
-                        },
-                        "15": {
-                            "name": "constant.language"
-                        },
-                        "16": {
-                            "name": "string.quoted.double"
-                        },
-                        "17": {
-                            "name": "punctuation.bracket.angle"
-                        },
-                        "18": {
                             "name": "punctuation.terminator"
                         }
                     },
                     "patterns": [
                         {
-                            "include": "#comments"
+                            "include": "#type-constructor"
                         },
                         {
-                            "include": "#attributes"
-                        },
-                        {
-                            "include": "#layout-member"
+                            "include": "#default-value"
                         }
                     ]
                 }
@@ -862,28 +817,6 @@
                     ]
                 }
             ]
-        },
-        "layout-member-reserved": {
-            "patterns": [
-                {
-                    "name": "meta.layout.reserved-member.fidl",
-                    "match": "(-?\\b(?:(?:0(?:x|X)[0-9a-fA-F]*)|(?:0(?:b|B)[01]*)|(?:(?:[0-9]+\\.?[0-9]*)|(?:\\.[0-9]+))(?:(?:e|E)(?:\\+|-)?[0-9]+)?)\\b)\\s*(:)\\s*\\b(reserved)\\b\\s*(;)",
-                    "captures": {
-                        "1": {
-                            "name": "constant.numeric"
-                        },
-                        "2": {
-                            "name": "punctuation.separator"
-                        },
-                        "3": {
-                            "name": "keyword.control"
-                        },
-                        "4": {
-                            "name": "punctuation.terminator"
-                        }
-                    }
-                }
-            ]
         }
     }
 }
diff --git a/vscode-language-fidl/test.test.fidl b/vscode-language-fidl/test.test.fidl
index 978e2d5..5bddb69 100644
--- a/vscode-language-fidl/test.test.fidl
+++ b/vscode-language-fidl/test.test.fidl
@@ -44,7 +44,7 @@
         1: u1 Bar; // hi
         2: u2 vector<Foo>:<MY_SIZE, optional>;
         3: u3 struct {};
-        @foobar
+        @foobar("abc")
         4: reserved;
     };
     f3 vector<struct {
@@ -82,8 +82,9 @@
         f1 uint8 = 12;
     }) -> (struct {
         f1 uint32 = 1 | 2;
+        f2 string = "abc";
     }) -> (union {
-        1: f1 uint8 = Bits.A | 2;
+        1: f1 uint8;
         2: f2 struct {
             foo Bar;
         };
@@ -105,6 +106,15 @@
         f1 Bar;
         f2 uint8;
         f3 vector<Bar>:10;
+        f4 vector<struct {
+            f41 vector<table {
+                1: f411 string:50;
+                2: f412 string:optional;
+                3: f413 string:<50, optional>;
+                4: f414 string:<other.library.MY_SIZE, optional>;
+                5: f415 vector<string>:<10,optional>;
+            }>:optional;
+        }>:100;
     });
 
     -> Foo();
@@ -113,4 +123,6 @@
         f1 Bar; //hi
         f2 uint8;
     });
+
+    Foo(Foo2) -> (Bar);
 };
diff --git a/vscode-language-fidl/tools/generate-syntax.ts b/vscode-language-fidl/tools/generate-syntax.ts
index 3259505..a0e5b29 100644
--- a/vscode-language-fidl/tools/generate-syntax.ts
+++ b/vscode-language-fidl/tools/generate-syntax.ts
@@ -286,7 +286,14 @@
 
 const SUBTYPE = seq(separator(":"), LAYOUT_REFERENCE);
 
-const NON_RECURSIVE_PARAMETERS = angle_brackets(comma_separated(CONSTANT));
+// currently the only valid placement for a type layout parameter is the
+// first parameter, so take advantage of this fact to simplify this rule
+const TYPE_PARAMETERS = angle_brackets(seq(LAYOUT_REFERENCE, optional(
+  seq(
+    separator(","),
+    NUMERIC_CONSTANT,
+  )
+)));
 
 const TYPE_CONSTRAINT = named(CONSTANT, "storage.type.constraint");
 
@@ -320,7 +327,8 @@
 MODIFIERS.assert("strict resource");
 MODIFIERS.assert("flexible");
 
-NON_RECURSIVE_PARAMETERS.assert("<Foo, 3>");
+TYPE_PARAMETERS.assert("<Foo, 3>");
+TYPE_PARAMETERS.assert("<Foo>");
 
 TYPE_CONSTRAINTS.assert(":optional");
 TYPE_CONSTRAINTS.assert(":zx.rights.DUPLICATE");
@@ -393,7 +401,17 @@
       ],
     }),
 
-    include("layout-introduction"),
+    // Type declaration
+    block({
+      name: "meta.type",
+      begin: seq(
+        keyword("type"),
+        LOCAL_TYPE,
+        separator("="),
+      ),
+      end: EOL,
+      patterns: [include("type-constructor")],
+    }),
   ],
   repository: {
     comments: {
@@ -450,96 +468,55 @@
         match("storage.type.operand", NUMERIC_CONSTANT),
       ],
     },
+    "default-value": {
+      patterns: [
+        match("meta.separator", separator("=")),
+        include("const-value"),
+      ],
+    },
     "method-argument": {
       patterns: [
         block({
           name: "meta.method.arguments",
-          begin: seq("\\(", INLINE_LAYOUT_PREFIX),
-          end: "}\\)",
-          patterns: [...WITH_COMMENTS_AND_ATTRIBUTES, include("layout-member")],
+          begin: "\\(",
+          end: "\\)",
+          patterns: [include("type-constructor")],
         }),
       ],
     },
-    "layout-introduction": block({
-      name: "meta.inline-layout-block",
-      begin: seq(
-        keyword("type"),
-        LOCAL_TYPE,
-        separator("="),
-        INLINE_LAYOUT_PREFIX
-      ),
-      end: "}",
-      patterns: [...WITH_COMMENTS_AND_ATTRIBUTES, include("layout-member")],
-    }),
-    "layout-member": {
+    "type-constructor": {
       patterns: [
-        include("layout-member-inline"),
-        include("layout-member-default"),
-        include("layout-member-reference"),
-        include("layout-member-inline-arg"),
-        include("layout-member-value"),
-        include("layout-member-reserved"),
+        include("type-constructor-inline"),
+        include("type-constructor-inline-arg"),
+        include("type-constructor-reference"),
       ],
     },
-    // a member that contains an inline layout, e.g. `foo struct { ... };
-    "layout-member-inline": {
+    // a type constructor that contains an inline layout, e.g. `foo struct { ... };
+    "type-constructor-inline": {
       patterns: [
         block({
-          name: "meta.layout.member",
-          begin: seq(optional(ORDINAL), VARIABLE, INLINE_LAYOUT_PREFIX),
+          name: "meta.type-constructor-inline",
+          begin: seq(INLINE_LAYOUT_PREFIX),
           end: seq(
             "}",
             // no user-defined layouts currently accept parameters, so don't
             // worry about syntax highlighting for them yet; just check for
             // constraints
             optional(TYPE_CONSTRAINTS),
-            EOL
           ),
           patterns: [...WITH_COMMENTS_AND_ATTRIBUTES, include("layout-member")],
         }),
       ],
     },
-    // a member with a default value, e.g. `foo uint8 = 3;`, only applies to
-    // structs
-    // based on the current types that can have a default value specified, we
-    // don't need to account for inline layouts or parameterized layouts here
-    "layout-member-default": {
-      patterns: [
-        block({
-          name: "meta.layout.struct-member",
-          begin: seq(VARIABLE, PRIMITIVE_TYPE, separator("=")),
-          end: EOL,
-          patterns: [include("const-value")],
-        }),
-      ],
-    },
-    // a member that references another type, e.g. `foo bar<...>:<...>;`
-    "layout-member-reference": {
-      patterns: [
-        match(
-          "meta.layout.member",
-          seq(
-            optional(ORDINAL),
-            VARIABLE,
-            LAYOUT_REFERENCE,
-            optional(NON_RECURSIVE_PARAMETERS),
-            optional(TYPE_CONSTRAINTS),
-            EOL
-          )
-        ),
-      ],
-    },
-    // a member with a layout parameter that is an inline layout, e.g.
-    // `foo bar<struct {...}, ...>:<...>;
-    "layout-member-inline-arg": {
+    // a type constructor with a layout parameter that is an inline layout, e.g.
+    // `foo bar<struct {...}, ...>:<...>`;
+    "type-constructor-inline-arg": {
       patterns: [
         // currently the only valid placement for a type layout parameter is the
         // first parameter, so take advantage of this fact to simplify this rule
         block({
-          name: "meta.layout.member",
+          name: "meta.type-constructor-inline-arg",
           begin: seq(
-            optional(ORDINAL),
-            VARIABLE,
             LAYOUT_REFERENCE,
             "<",
             INLINE_LAYOUT_PREFIX
@@ -549,14 +526,69 @@
             optional(seq(",", CONSTANT)),
             ">",
             optional(TYPE_CONSTRAINTS),
-            EOL
           ),
           patterns: [...WITH_COMMENTS_AND_ATTRIBUTES, include("layout-member")],
         }),
       ],
     },
-    // a member that specifies a value, e.g. `foo = 1;`, only applies to bits
-    // and enums
+    // a type constructor that references another type, e.g. `foo bar<...>:<...>;`
+    "type-constructor-reference": {
+      patterns: [
+        match(
+          "meta.type-constructor-reference",
+          seq(
+            LAYOUT_REFERENCE,
+            optional(TYPE_PARAMETERS),
+            optional(TYPE_CONSTRAINTS),
+          )
+        ),
+      ],
+    },
+    "layout-member": {
+      // the ordering of the patterns below is important, since we want to attempt value before we
+      // attempt a default struct member
+      patterns: [
+        include("layout-member-reserved"),
+        include("layout-member-value"),
+        include("layout-member-struct"),
+        include("layout-member-ordinaled"),
+      ],
+    },
+    // the reserved member, e.g. `1: reserved;`, only applies to unions and tables
+    "layout-member-reserved": {
+      patterns: [
+        match(
+          "meta.layout.reserved-member",
+          seq(ORDINAL, keyword("reserved"), EOL)
+        ),
+      ],
+    },
+    // an ordinaled layout member, like `1: a bool;`, only applies to unions and tables
+    "layout-member-ordinaled": {
+      patterns: [
+        block({
+          name: "meta.layout.ordinaled-member",
+          begin: seq(ORDINAL, VARIABLE),
+          end: EOL,
+          patterns: [include("type-constructor")],
+        }),
+      ],
+    },
+    // a struct member; may have an optional default value, e.g. `foo uint8 = 3;`
+    "layout-member-struct": {
+      patterns: [
+        block({
+          name: "meta.layout.struct-struct-member",
+          begin: VARIABLE,
+          end: EOL,
+          patterns: [
+            include("type-constructor"),
+            include("default-value"),
+          ],
+        }),
+      ],
+    },
+    // a layout member that specifies a value, e.g. `foo = 1;`, only applies to bits and enums
     "layout-member-value": {
       patterns: [
         block({
@@ -570,15 +602,6 @@
         }),
       ],
     },
-    // the reserved member, e.g. `1: reserved;`, only applies to unions and tables
-    "layout-member-reserved": {
-      patterns: [
-        match(
-          "meta.layout.reserved-member",
-          seq(NUMERIC_LITERAL, separator(":"), keyword("reserved"), EOL)
-        ),
-      ],
-    },
   },
 };