python/moz/l10n/util/printf.py (39 lines of code) (raw):

# Copyright Mozilla Foundation # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from __future__ import annotations from collections.abc import Iterator from re import compile from ..model import Expression, VariableRef printf = compile( # 1:argnum 2:python-name 3:java-datetime 4:type r"%(?:([1-9])\$|\(([\w.]+)\))?[-#+ 0,]?[0-9.]*(?:([Tt][A-Za-z]+)|(?:(?:hh?|ll?|[Lzjq])?([@%A-Za-z])))" ) def parse_printf_pattern(src: str | None) -> Iterator[str | Expression]: if not src: return pos = 0 for m in printf.finditer(src): start = m.start() if start > pos: yield src[pos:start] source = m[0] [argnum, argname, datetime, type] = m.groups() pos = m.end() if type == "%": yield Expression("%", attributes={"source": source}) continue func: str | None # TODO post-py38: should be a match if datetime: func = "datetime" elif type in {"c", "C", "s", "S"}: func = "string" elif type in {"d", "D", "o", "O", "p", "u", "U", "x", "X"}: func = "integer" elif type in {"a", "A", "e", "E", "f", "F", "g", "G"}: func = "number" else: func = "printf" yield Expression( VariableRef(argname or ("arg" + (argnum or ""))), func, attributes={"source": source}, ) if pos < len(src): yield src[pos:]