(s: Scanner)
| 212 | |
| 213 | |
| 214 | def single_kwarg(s: Scanner) -> ast.keyword: |
| 215 | keyword_name = s.accept(TokenType.IDENT, reject=True) |
| 216 | if not keyword_name.value.isidentifier(): |
| 217 | raise SyntaxError( |
| 218 | f"not a valid python identifier {keyword_name.value}", |
| 219 | (FILE_NAME, 1, keyword_name.pos + 1, s.input), |
| 220 | ) |
| 221 | if keyword.iskeyword(keyword_name.value): |
| 222 | raise SyntaxError( |
| 223 | f"unexpected reserved python keyword `{keyword_name.value}`", |
| 224 | (FILE_NAME, 1, keyword_name.pos + 1, s.input), |
| 225 | ) |
| 226 | s.accept(TokenType.EQUAL, reject=True) |
| 227 | |
| 228 | if value_token := s.accept(TokenType.STRING): |
| 229 | value: str | int | bool | None = value_token.value[1:-1] # strip quotes |
| 230 | else: |
| 231 | value_token = s.accept(TokenType.IDENT, reject=True) |
| 232 | if (number := value_token.value).isdigit() or ( |
| 233 | number.startswith("-") and number[1:].isdigit() |
| 234 | ): |
| 235 | value = int(number) |
| 236 | elif value_token.value in BUILTIN_MATCHERS: |
| 237 | value = BUILTIN_MATCHERS[value_token.value] |
| 238 | else: |
| 239 | raise SyntaxError( |
| 240 | f'unexpected character/s "{value_token.value}"', |
| 241 | (FILE_NAME, 1, value_token.pos + 1, s.input), |
| 242 | ) |
| 243 | |
| 244 | ret = ast.keyword(keyword_name.value, ast.Constant(value)) |
| 245 | return ret |
| 246 | |
| 247 | |
| 248 | def all_kwargs(s: Scanner) -> list[ast.keyword]: |
no test coverage detected