We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[textual][bug] CSS rule parsing fails when the name of the colour we pass contains a digit
So while this is working correctly:
```css
#my_widget {
  background: dark_cyan;
}
```

...this fails:
```css
#my_widget {
  background: turquoise4;
}
```
...with the following error:
```
 • failed to parse color 'turquoise';                                                                                                                                         
 • failed to parse 'turquoise' as a color;  
```
(maybe just a regex that doesn't take into account the fact that colour names can include numbers?)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/textual/css/tokenize.py`
Content:
```
1 from __future__ import annotations
2 
3 import re
4 from typing import Iterable
5 
6 from textual.css.tokenizer import Expect, Tokenizer, Token
7 
8 COMMENT_START = r"\/\*"
9 SCALAR = r"\-?\d+\.?\d*(?:fr|%|w|h|vw|vh)"
10 DURATION = r"\d+\.?\d*(?:ms|s)"
11 NUMBER = r"\-?\d+\.?\d*"
12 COLOR = r"\#[0-9a-fA-F]{8}|\#[0-9a-fA-F]{6}|rgb\(\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*\)|rgba\(\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*\)"
13 KEY_VALUE = r"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\-\/]+"
14 TOKEN = "[a-zA-Z_-]+"
15 STRING = r"\".*?\""
16 VARIABLE_REF = r"\$[a-zA-Z0-9_\-]+"
17 
18 # Values permitted in variable and rule declarations.
19 DECLARATION_VALUES = {
20     "scalar": SCALAR,
21     "duration": DURATION,
22     "number": NUMBER,
23     "color": COLOR,
24     "key_value": KEY_VALUE,
25     "token": TOKEN,
26     "string": STRING,
27     "variable_ref": VARIABLE_REF,
28 }
29 
30 # The tokenizers "expectation" while at the root/highest level of scope
31 # in the CSS file. At this level we might expect to see selectors, comments,
32 # variable definitions etc.
33 expect_root_scope = Expect(
34     whitespace=r"\s+",
35     comment_start=COMMENT_START,
36     selector_start_id=r"\#[a-zA-Z_\-][a-zA-Z0-9_\-]*",
37     selector_start_class=r"\.[a-zA-Z_\-][a-zA-Z0-9_\-]*",
38     selector_start_universal=r"\*",
39     selector_start=r"[a-zA-Z_\-]+",
40     variable_name=rf"{VARIABLE_REF}:",
41 ).expect_eof(True)
42 
43 # After a variable declaration e.g. "$warning-text: TOKENS;"
44 #              for tokenizing variable value ------^~~~~~~^
45 expect_variable_name_continue = Expect(
46     variable_value_end=r"\n|;",
47     whitespace=r"\s+",
48     comment_start=COMMENT_START,
49     **DECLARATION_VALUES,
50 ).expect_eof(True)
51 
52 expect_comment_end = Expect(
53     comment_end=re.escape("*/"),
54 )
55 
56 # After we come across a selector in CSS e.g. ".my-class", we may
57 # find other selectors, pseudo-classes... e.g. ".my-class :hover"
58 expect_selector_continue = Expect(
59     whitespace=r"\s+",
60     comment_start=COMMENT_START,
61     pseudo_class=r"\:[a-zA-Z_-]+",
62     selector_id=r"\#[a-zA-Z_\-][a-zA-Z0-9_\-]*",
63     selector_class=r"\.[a-zA-Z_\-][a-zA-Z0-9_\-]*",
64     selector_universal=r"\*",
65     selector=r"[a-zA-Z_\-]+",
66     combinator_child=">",
67     new_selector=r",",
68     declaration_set_start=r"\{",
69 )
70 
71 # A rule declaration e.g. "text: red;"
72 #                          ^---^
73 expect_declaration = Expect(
74     whitespace=r"\s+",
75     comment_start=COMMENT_START,
76     declaration_name=r"[a-zA-Z_\-]+\:",
77     declaration_set_end=r"\}",
78 )
79 
80 expect_declaration_solo = Expect(
81     whitespace=r"\s+",
82     comment_start=COMMENT_START,
83     declaration_name=r"[a-zA-Z_\-]+\:",
84     declaration_set_end=r"\}",
85 ).expect_eof(True)
86 
87 # The value(s)/content from a rule declaration e.g. "text: red;"
88 #                                                         ^---^
89 expect_declaration_content = Expect(
90     declaration_end=r";",
91     whitespace=r"\s+",
92     comment_start=COMMENT_START,
93     **DECLARATION_VALUES,
94     important=r"\!important",
95     comma=",",
96     declaration_set_end=r"\}",
97 )
98 
99 expect_declaration_content_solo = Expect(
100     declaration_end=r";",
101     whitespace=r"\s+",
102     comment_start=COMMENT_START,
103     **DECLARATION_VALUES,
104     important=r"\!important",
105     comma=",",
106     declaration_set_end=r"\}",
107 ).expect_eof(True)
108 
109 
110 class TokenizerState:
111     """State machine for the tokenizer.
112 
113     Attributes:
114         EXPECT: The initial expectation of the tokenizer. Since we start tokenizing
115             at the root scope, we might expect to see either a variable or selector, for example.
116         STATE_MAP: Maps token names to Expects, defines the sets of valid tokens
117             that we'd expect to see next, given the current token. For example, if
118             we've just processed a variable declaration name, we next expect to see
119             the value of that variable.
120     """
121 
122     EXPECT = expect_root_scope
123     STATE_MAP = {
124         "variable_name": expect_variable_name_continue,
125         "variable_value_end": expect_root_scope,
126         "selector_start": expect_selector_continue,
127         "selector_start_id": expect_selector_continue,
128         "selector_start_class": expect_selector_continue,
129         "selector_start_universal": expect_selector_continue,
130         "selector_id": expect_selector_continue,
131         "selector_class": expect_selector_continue,
132         "selector_universal": expect_selector_continue,
133         "declaration_set_start": expect_declaration,
134         "declaration_name": expect_declaration_content,
135         "declaration_end": expect_declaration,
136         "declaration_set_end": expect_root_scope,
137     }
138 
139     def __call__(self, code: str, path: str) -> Iterable[Token]:
140         tokenizer = Tokenizer(code, path=path)
141         expect = self.EXPECT
142         get_token = tokenizer.get_token
143         get_state = self.STATE_MAP.get
144         while True:
145             token = get_token(expect)
146             name = token.name
147             if name == "comment_start":
148                 tokenizer.skip_to(expect_comment_end)
149                 continue
150             elif name == "eof":
151                 break
152             expect = get_state(name, expect)
153             yield token
154 
155 
156 class DeclarationTokenizerState(TokenizerState):
157     EXPECT = expect_declaration_solo
158     STATE_MAP = {
159         "declaration_name": expect_declaration_content,
160         "declaration_end": expect_declaration_solo,
161     }
162 
163 
164 class ValueTokenizerState(TokenizerState):
165     EXPECT = expect_declaration_content_solo
166 
167 
168 tokenize = TokenizerState()
169 tokenize_declarations = DeclarationTokenizerState()
170 tokenize_value = ValueTokenizerState()
171 
172 
173 def tokenize_values(values: dict[str, str]) -> dict[str, list[Token]]:
174     """Tokens the values in a dict of strings.
175 
176     Args:
177         values (dict[str, str]): A mapping of CSS variable name on to a value, to be
178             added to the CSS context.
179 
180     Returns:
181         dict[str, list[Token]]: A mapping of name on to a list of tokens,
182     """
183     value_tokens = {
184         name: list(tokenize_value(value, "__name__")) for name, value in values.items()
185     }
186     return value_tokens
187 
188 
189 if __name__ == "__main__":
190     from rich import print
191 
192     css = """#something {
193 
194         color: rgb(10,12,23)
195     }
196     """
197     # transition: offset 500 in_out_cubic;
198     tokens = tokenize(css, __name__)
199     print(list(tokens))
200 
201     print(tokenize_values({"primary": "rgb(10,20,30)", "secondary": "#ff00ff"}))
202
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/textual/css/tokenize.py b/src/textual/css/tokenize.py
--- a/src/textual/css/tokenize.py
+++ b/src/textual/css/tokenize.py
@@ -11,7 +11,7 @@
 NUMBER = r"\-?\d+\.?\d*"
 COLOR = r"\#[0-9a-fA-F]{8}|\#[0-9a-fA-F]{6}|rgb\(\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*\)|rgba\(\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*,\-?\d+\.?\d*\)"
 KEY_VALUE = r"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\-\/]+"
-TOKEN = "[a-zA-Z_-]+"
+TOKEN = "[a-zA-Z][a-zA-Z0-9_-]*"
 STRING = r"\".*?\""
 VARIABLE_REF = r"\$[a-zA-Z0-9_\-]+"

{"golden_diff": "diff --git a/src/textual/css/tokenize.py b/src/textual/css/tokenize.py\n--- a/src/textual/css/tokenize.py\n+++ b/src/textual/css/tokenize.py\n@@ -11,7 +11,7 @@\n NUMBER = r\"\\-?\\d+\\.?\\d*\"\n COLOR = r\"\\#[0-9a-fA-F]{8}|\\#[0-9a-fA-F]{6}|rgb\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)|rgba\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)\"\n KEY_VALUE = r\"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\\-\\/]+\"\n-TOKEN = \"[a-zA-Z_-]+\"\n+TOKEN = \"[a-zA-Z][a-zA-Z0-9_-]*\"\n STRING = r\"\\\".*?\\\"\"\n VARIABLE_REF = r\"\\$[a-zA-Z0-9_\\-]+\"\n", "issue": "[textual][bug] CSS rule parsing fails when the name of the colour we pass contains a digit\nSo while this is working correctly:\r\n```css\r\n#my_widget {\r\n  background: dark_cyan;\r\n}\r\n```\r\n\r\n...this fails:\r\n```css\r\n#my_widget {\r\n  background: turquoise4;\r\n}\r\n```\r\n...with the following error:\r\n```\r\n \u2022 failed to parse color 'turquoise';                                                                                                                                         \r\n \u2022 failed to parse 'turquoise' as a color;  \r\n```\r\n(maybe just a regex that doesn't take into account the fact that colour names can include numbers?)\n", "before_files": [{"content": "from __future__ import annotations\n\nimport re\nfrom typing import Iterable\n\nfrom textual.css.tokenizer import Expect, Tokenizer, Token\n\nCOMMENT_START = r\"\\/\\*\"\nSCALAR = r\"\\-?\\d+\\.?\\d*(?:fr|%|w|h|vw|vh)\"\nDURATION = r\"\\d+\\.?\\d*(?:ms|s)\"\nNUMBER = r\"\\-?\\d+\\.?\\d*\"\nCOLOR = r\"\\#[0-9a-fA-F]{8}|\\#[0-9a-fA-F]{6}|rgb\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)|rgba\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)\"\nKEY_VALUE = r\"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\\-\\/]+\"\nTOKEN = \"[a-zA-Z_-]+\"\nSTRING = r\"\\\".*?\\\"\"\nVARIABLE_REF = r\"\\$[a-zA-Z0-9_\\-]+\"\n\n# Values permitted in variable and rule declarations.\nDECLARATION_VALUES = {\n    \"scalar\": SCALAR,\n    \"duration\": DURATION,\n    \"number\": NUMBER,\n    \"color\": COLOR,\n    \"key_value\": KEY_VALUE,\n    \"token\": TOKEN,\n    \"string\": STRING,\n    \"variable_ref\": VARIABLE_REF,\n}\n\n# The tokenizers \"expectation\" while at the root/highest level of scope\n# in the CSS file. At this level we might expect to see selectors, comments,\n# variable definitions etc.\nexpect_root_scope = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    selector_start_id=r\"\\#[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_start_class=r\"\\.[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_start_universal=r\"\\*\",\n    selector_start=r\"[a-zA-Z_\\-]+\",\n    variable_name=rf\"{VARIABLE_REF}:\",\n).expect_eof(True)\n\n# After a variable declaration e.g. \"$warning-text: TOKENS;\"\n#              for tokenizing variable value ------^~~~~~~^\nexpect_variable_name_continue = Expect(\n    variable_value_end=r\"\\n|;\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n).expect_eof(True)\n\nexpect_comment_end = Expect(\n    comment_end=re.escape(\"*/\"),\n)\n\n# After we come across a selector in CSS e.g. \".my-class\", we may\n# find other selectors, pseudo-classes... e.g. \".my-class :hover\"\nexpect_selector_continue = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    pseudo_class=r\"\\:[a-zA-Z_-]+\",\n    selector_id=r\"\\#[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_class=r\"\\.[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_universal=r\"\\*\",\n    selector=r\"[a-zA-Z_\\-]+\",\n    combinator_child=\">\",\n    new_selector=r\",\",\n    declaration_set_start=r\"\\{\",\n)\n\n# A rule declaration e.g. \"text: red;\"\n#                          ^---^\nexpect_declaration = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    declaration_name=r\"[a-zA-Z_\\-]+\\:\",\n    declaration_set_end=r\"\\}\",\n)\n\nexpect_declaration_solo = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    declaration_name=r\"[a-zA-Z_\\-]+\\:\",\n    declaration_set_end=r\"\\}\",\n).expect_eof(True)\n\n# The value(s)/content from a rule declaration e.g. \"text: red;\"\n#                                                         ^---^\nexpect_declaration_content = Expect(\n    declaration_end=r\";\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n    important=r\"\\!important\",\n    comma=\",\",\n    declaration_set_end=r\"\\}\",\n)\n\nexpect_declaration_content_solo = Expect(\n    declaration_end=r\";\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n    important=r\"\\!important\",\n    comma=\",\",\n    declaration_set_end=r\"\\}\",\n).expect_eof(True)\n\n\nclass TokenizerState:\n    \"\"\"State machine for the tokenizer.\n\n    Attributes:\n        EXPECT: The initial expectation of the tokenizer. Since we start tokenizing\n            at the root scope, we might expect to see either a variable or selector, for example.\n        STATE_MAP: Maps token names to Expects, defines the sets of valid tokens\n            that we'd expect to see next, given the current token. For example, if\n            we've just processed a variable declaration name, we next expect to see\n            the value of that variable.\n    \"\"\"\n\n    EXPECT = expect_root_scope\n    STATE_MAP = {\n        \"variable_name\": expect_variable_name_continue,\n        \"variable_value_end\": expect_root_scope,\n        \"selector_start\": expect_selector_continue,\n        \"selector_start_id\": expect_selector_continue,\n        \"selector_start_class\": expect_selector_continue,\n        \"selector_start_universal\": expect_selector_continue,\n        \"selector_id\": expect_selector_continue,\n        \"selector_class\": expect_selector_continue,\n        \"selector_universal\": expect_selector_continue,\n        \"declaration_set_start\": expect_declaration,\n        \"declaration_name\": expect_declaration_content,\n        \"declaration_end\": expect_declaration,\n        \"declaration_set_end\": expect_root_scope,\n    }\n\n    def __call__(self, code: str, path: str) -> Iterable[Token]:\n        tokenizer = Tokenizer(code, path=path)\n        expect = self.EXPECT\n        get_token = tokenizer.get_token\n        get_state = self.STATE_MAP.get\n        while True:\n            token = get_token(expect)\n            name = token.name\n            if name == \"comment_start\":\n                tokenizer.skip_to(expect_comment_end)\n                continue\n            elif name == \"eof\":\n                break\n            expect = get_state(name, expect)\n            yield token\n\n\nclass DeclarationTokenizerState(TokenizerState):\n    EXPECT = expect_declaration_solo\n    STATE_MAP = {\n        \"declaration_name\": expect_declaration_content,\n        \"declaration_end\": expect_declaration_solo,\n    }\n\n\nclass ValueTokenizerState(TokenizerState):\n    EXPECT = expect_declaration_content_solo\n\n\ntokenize = TokenizerState()\ntokenize_declarations = DeclarationTokenizerState()\ntokenize_value = ValueTokenizerState()\n\n\ndef tokenize_values(values: dict[str, str]) -> dict[str, list[Token]]:\n    \"\"\"Tokens the values in a dict of strings.\n\n    Args:\n        values (dict[str, str]): A mapping of CSS variable name on to a value, to be\n            added to the CSS context.\n\n    Returns:\n        dict[str, list[Token]]: A mapping of name on to a list of tokens,\n    \"\"\"\n    value_tokens = {\n        name: list(tokenize_value(value, \"__name__\")) for name, value in values.items()\n    }\n    return value_tokens\n\n\nif __name__ == \"__main__\":\n    from rich import print\n\n    css = \"\"\"#something {\n\n        color: rgb(10,12,23)\n    }\n    \"\"\"\n    # transition: offset 500 in_out_cubic;\n    tokens = tokenize(css, __name__)\n    print(list(tokens))\n\n    print(tokenize_values({\"primary\": \"rgb(10,20,30)\", \"secondary\": \"#ff00ff\"}))\n", "path": "src/textual/css/tokenize.py"}], "after_files": [{"content": "from __future__ import annotations\n\nimport re\nfrom typing import Iterable\n\nfrom textual.css.tokenizer import Expect, Tokenizer, Token\n\nCOMMENT_START = r\"\\/\\*\"\nSCALAR = r\"\\-?\\d+\\.?\\d*(?:fr|%|w|h|vw|vh)\"\nDURATION = r\"\\d+\\.?\\d*(?:ms|s)\"\nNUMBER = r\"\\-?\\d+\\.?\\d*\"\nCOLOR = r\"\\#[0-9a-fA-F]{8}|\\#[0-9a-fA-F]{6}|rgb\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)|rgba\\(\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*,\\-?\\d+\\.?\\d*\\)\"\nKEY_VALUE = r\"[a-zA-Z_-][a-zA-Z0-9_-]*=[0-9a-zA-Z_\\-\\/]+\"\nTOKEN = \"[a-zA-Z][a-zA-Z0-9_-]*\"\nSTRING = r\"\\\".*?\\\"\"\nVARIABLE_REF = r\"\\$[a-zA-Z0-9_\\-]+\"\n\n# Values permitted in variable and rule declarations.\nDECLARATION_VALUES = {\n    \"scalar\": SCALAR,\n    \"duration\": DURATION,\n    \"number\": NUMBER,\n    \"color\": COLOR,\n    \"key_value\": KEY_VALUE,\n    \"token\": TOKEN,\n    \"string\": STRING,\n    \"variable_ref\": VARIABLE_REF,\n}\n\n# The tokenizers \"expectation\" while at the root/highest level of scope\n# in the CSS file. At this level we might expect to see selectors, comments,\n# variable definitions etc.\nexpect_root_scope = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    selector_start_id=r\"\\#[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_start_class=r\"\\.[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_start_universal=r\"\\*\",\n    selector_start=r\"[a-zA-Z_\\-]+\",\n    variable_name=rf\"{VARIABLE_REF}:\",\n).expect_eof(True)\n\n# After a variable declaration e.g. \"$warning-text: TOKENS;\"\n#              for tokenizing variable value ------^~~~~~~^\nexpect_variable_name_continue = Expect(\n    variable_value_end=r\"\\n|;\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n).expect_eof(True)\n\nexpect_comment_end = Expect(\n    comment_end=re.escape(\"*/\"),\n)\n\n# After we come across a selector in CSS e.g. \".my-class\", we may\n# find other selectors, pseudo-classes... e.g. \".my-class :hover\"\nexpect_selector_continue = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    pseudo_class=r\"\\:[a-zA-Z_-]+\",\n    selector_id=r\"\\#[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_class=r\"\\.[a-zA-Z_\\-][a-zA-Z0-9_\\-]*\",\n    selector_universal=r\"\\*\",\n    selector=r\"[a-zA-Z_\\-]+\",\n    combinator_child=\">\",\n    new_selector=r\",\",\n    declaration_set_start=r\"\\{\",\n)\n\n# A rule declaration e.g. \"text: red;\"\n#                          ^---^\nexpect_declaration = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    declaration_name=r\"[a-zA-Z_\\-]+\\:\",\n    declaration_set_end=r\"\\}\",\n)\n\nexpect_declaration_solo = Expect(\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    declaration_name=r\"[a-zA-Z_\\-]+\\:\",\n    declaration_set_end=r\"\\}\",\n).expect_eof(True)\n\n# The value(s)/content from a rule declaration e.g. \"text: red;\"\n#                                                         ^---^\nexpect_declaration_content = Expect(\n    declaration_end=r\";\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n    important=r\"\\!important\",\n    comma=\",\",\n    declaration_set_end=r\"\\}\",\n)\n\nexpect_declaration_content_solo = Expect(\n    declaration_end=r\";\",\n    whitespace=r\"\\s+\",\n    comment_start=COMMENT_START,\n    **DECLARATION_VALUES,\n    important=r\"\\!important\",\n    comma=\",\",\n    declaration_set_end=r\"\\}\",\n).expect_eof(True)\n\n\nclass TokenizerState:\n    \"\"\"State machine for the tokenizer.\n\n    Attributes:\n        EXPECT: The initial expectation of the tokenizer. Since we start tokenizing\n            at the root scope, we might expect to see either a variable or selector, for example.\n        STATE_MAP: Maps token names to Expects, defines the sets of valid tokens\n            that we'd expect to see next, given the current token. For example, if\n            we've just processed a variable declaration name, we next expect to see\n            the value of that variable.\n    \"\"\"\n\n    EXPECT = expect_root_scope\n    STATE_MAP = {\n        \"variable_name\": expect_variable_name_continue,\n        \"variable_value_end\": expect_root_scope,\n        \"selector_start\": expect_selector_continue,\n        \"selector_start_id\": expect_selector_continue,\n        \"selector_start_class\": expect_selector_continue,\n        \"selector_start_universal\": expect_selector_continue,\n        \"selector_id\": expect_selector_continue,\n        \"selector_class\": expect_selector_continue,\n        \"selector_universal\": expect_selector_continue,\n        \"declaration_set_start\": expect_declaration,\n        \"declaration_name\": expect_declaration_content,\n        \"declaration_end\": expect_declaration,\n        \"declaration_set_end\": expect_root_scope,\n    }\n\n    def __call__(self, code: str, path: str) -> Iterable[Token]:\n        tokenizer = Tokenizer(code, path=path)\n        expect = self.EXPECT\n        get_token = tokenizer.get_token\n        get_state = self.STATE_MAP.get\n        while True:\n            token = get_token(expect)\n            name = token.name\n            if name == \"comment_start\":\n                tokenizer.skip_to(expect_comment_end)\n                continue\n            elif name == \"eof\":\n                break\n            expect = get_state(name, expect)\n            yield token\n\n\nclass DeclarationTokenizerState(TokenizerState):\n    EXPECT = expect_declaration_solo\n    STATE_MAP = {\n        \"declaration_name\": expect_declaration_content,\n        \"declaration_end\": expect_declaration_solo,\n    }\n\n\nclass ValueTokenizerState(TokenizerState):\n    EXPECT = expect_declaration_content_solo\n\n\ntokenize = TokenizerState()\ntokenize_declarations = DeclarationTokenizerState()\ntokenize_value = ValueTokenizerState()\n\n\ndef tokenize_values(values: dict[str, str]) -> dict[str, list[Token]]:\n    \"\"\"Tokens the values in a dict of strings.\n\n    Args:\n        values (dict[str, str]): A mapping of CSS variable name on to a value, to be\n            added to the CSS context.\n\n    Returns:\n        dict[str, list[Token]]: A mapping of name on to a list of tokens,\n    \"\"\"\n    value_tokens = {\n        name: list(tokenize_value(value, \"__name__\")) for name, value in values.items()\n    }\n    return value_tokens\n\n\nif __name__ == \"__main__\":\n    from rich import print\n\n    css = \"\"\"#something {\n\n        color: rgb(10,12,23)\n    }\n    \"\"\"\n    # transition: offset 500 in_out_cubic;\n    tokens = tokenize(css, __name__)\n    print(list(tokens))\n\n    print(tokenize_values({\"primary\": \"rgb(10,20,30)\", \"secondary\": \"#ff00ff\"}))\n", "path": "src/textual/css/tokenize.py"}]}