{"id":15525238,"url":"https://github.com/donatj/printf-parser","last_synced_at":"2026-04-21T21:06:13.055Z","repository":{"id":45591593,"uuid":"175909184","full_name":"donatj/printf-parser","owner":"donatj","description":"A PHP printf compatible tokenizing printf string parser","archived":false,"fork":false,"pushed_at":"2026-04-17T14:43:46.000Z","size":171,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-04-17T15:41:28.143Z","etag":null,"topics":["parser","php","php-library","printf"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/donatj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"custom":"https://www.paypal.me/donatj/15","ko_fi":"donatj","github":"donatj"}},"created_at":"2019-03-16T00:46:36.000Z","updated_at":"2026-04-17T14:43:49.000Z","dependencies_parsed_at":"2026-01-01T14:08:12.921Z","dependency_job_id":null,"html_url":"https://github.com/donatj/printf-parser","commit_stats":{"total_commits":57,"total_committers":3,"mean_commits":19.0,"dds":0.08771929824561409,"last_synced_commit":"87f56c60deb0851424f38a736a5b0ae37ad945b7"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/donatj/printf-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donatj%2Fprintf-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donatj%2Fprintf-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donatj%2Fprintf-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donatj%2Fprintf-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/donatj","download_url":"https://codeload.github.com/donatj/printf-parser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/donatj%2Fprintf-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32110169,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["parser","php","php-library","printf"],"created_at":"2024-10-02T10:55:55.878Z","updated_at":"2026-04-21T21:06:13.049Z","avatar_url":"https://github.com/donatj.png","language":"PHP","readme":"# Printf Parser\n\n[![Latest Stable Version](https://poser.pugx.org/donatj/printf-parser/version)](https://packagist.org/packages/donatj/printf-parser)\n[![Total Downloads](https://poser.pugx.org/donatj/printf-parser/downloads)](https://packagist.org/packages/donatj/printf-parser)\n[![License](https://poser.pugx.org/donatj/printf-parser/license)](https://packagist.org/packages/donatj/printf-parser)\n[![ci.yml](https://github.com/donatj/printf-parser/actions/workflows/ci.yml/badge.svg)](https://github.com/donatj/printf-parser/actions/workflows/ci.yml)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/donatj/printf-parser/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/donatj/printf-parser)\n[![Code Coverage](https://scrutinizer-ci.com/g/donatj/printf-parser/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/donatj/printf-parser)\n\n\nPHP printf-syntax compatible printf string parser.\n\nParses printf strings into a stream of lexemes.\n\n\n## Requirements\n\n- **php**: \u003e=7.4\n\n## Installing\n\nInstall the latest version with:\n\n```bash\ncomposer require 'donatj/printf-parser'\n```\n\n## Example\n\nHere is a simple example:\n\n```php\n\u003c?php\n\nrequire __DIR__ . '/../vendor/autoload.php';\n\n$emitter = new \\donatj\\Printf\\LexemeEmitter;\n$parser  = new \\donatj\\Printf\\Parser($emitter);\n\n$parser-\u003eparseStr('percent of %s: %d%%');\n\n$lexemes = $emitter-\u003egetLexemes();\n\nforeach( $lexemes as $lexeme ) {\n\techo $lexeme-\u003egetLexItemType() . ' -\u003e ';\n\techo var_export($lexeme-\u003egetVal(), true);\n\n\tif( $lexeme instanceof \\donatj\\Printf\\ArgumentLexeme ) {\n\t\techo ' arg type: ' . $lexeme-\u003eargType();\n\t}\n\n\techo PHP_EOL;\n}\n\n```\n\nOutput:\n\n```\n! -\u003e 'percent of '\ns -\u003e 's' arg type: string\n! -\u003e ': '\nd -\u003e 'd' arg type: int\n! -\u003e '%'\n```\n\n## Documentation\n\n### Class: donatj\\Printf\\Parser\n\nParser implements a PHP Printf compatible Printf string parser.\n\n#### Method: Parser-\u003e__construct\n\n```php\nfunction __construct(\\donatj\\Printf\\Emitter $emitter)\n```\n\nParser constructor.\n\n##### Parameters:\n\n- ***\\donatj\\Printf\\Emitter*** `$emitter` - The given Emitter to emit Lexemes as parsed\n\n---\n\n#### Method: Parser-\u003eparseStr\n\n```php\nfunction parseStr(string $string) : void\n```\n\nParses a printf string and emit parsed lexemes to the configured Emitter\n\n### Class: donatj\\Printf\\Printer\n\nPrinter takes an iterable of Lexemes and produces a printf string.\n\n#### Method: Printer-\u003eprint\n\n```php\nfunction print(iterable $lexemes) : string\n```\n\nBuilds a canonical printf-format string from lexemes\n\n##### Parameters:\n\n- ***iterable\u003c\\donatj\\Printf\\Lexeme\u003e*** `$lexemes` - This can be a LexemeCollection\n\n**Throws**: `\\RuntimeException` - if an invalid or unrecognized lexeme is encountered\n\n### Class: donatj\\Printf\\LexemeEmitter\n\n---\n\n#### Method: LexemeEmitter-\u003egetLexemes\n\n```php\nfunction getLexemes() : \\donatj\\Printf\\LexemeCollection\n```\n\nReturn the Lexemes received by the emitter as an immutable LexemeCollection\n\n### Class: donatj\\Printf\\LexemeCollection\n\nLexemeCollection is an immutable iterable collection of Lexemes with ArrayAccess\n\n---\n\n#### Method: LexemeCollection-\u003egetInvalid\n\n```php\nfunction getInvalid() : ?\\donatj\\Printf\\Lexeme\n```\n\nRetrieve the first invalid Lexeme or null if all are valid.  \n  \nThis is useful for checking if a printf string parsed without error.\n\n---\n\n#### Method: LexemeCollection-\u003etoArray\n\n```php\nfunction toArray() : array\n```\n\nGet the LexemeCollection as an ordered array of Lexemes\n\n##### Returns:\n\n- ***\\donatj\\Printf\\Lexeme[]***\n\n---\n\n#### Method: LexemeCollection-\u003eargTypes\n\n```php\nfunction argTypes() : array\n```\n\n##### Returns the list of expected arguments as a 1-indexed map of the following\n\n```  \nArgumentLexeme::ARG_TYPE_MISSING  \nArgumentLexeme::ARG_TYPE_INT  \nArgumentLexeme::ARG_TYPE_DOUBLE  \nArgumentLexeme::ARG_TYPE_STRING  \n```\n\n##### Returns:\n\n- ***string[]***\n\n### Class: donatj\\Printf\\Lexeme\n\nLexeme represents a \"basic\" component of a printf string - either Literal Strings \"!\" or Invalid Lexemes\n\n```php\n\u003c?php\nnamespace donatj\\Printf;\n\nclass Lexeme {\n\tpublic const T_INVALID = '';\n\tpublic const T_LITERAL_STRING = '!';\n}\n```\n\n#### Method: Lexeme-\u003e__construct\n\n```php\nfunction __construct(string $lexItemType, string $val, int $pos)\n```\n\nLexItem constructor.\n\n---\n\n#### Method: Lexeme-\u003egetLexItemType\n\n```php\nfunction getLexItemType() : string\n```\n\nThe type of the printf Lexeme\n\n---\n\n#### Method: Lexeme-\u003egetVal\n\n```php\nfunction getVal() : string\n```\n\nThe text of the lexeme\n\n---\n\n#### Method: Lexeme-\u003egetPos\n\n```php\nfunction getPos() : int\n```\n\nThe string position of the given lexeme\n\n### Class: donatj\\Printf\\ArgumentLexeme\n\n```php\n\u003c?php\nnamespace donatj\\Printf;\n\nclass ArgumentLexeme {\n\t/** @var string the argument is treated as an integer and presented as a binary number. */\n\tpublic const T_INT_AS_BINARY = 'b';\n\t/** @var string the argument is treated as an integer and presented as the character with that ASCII value. */\n\tpublic const T_INT_AS_CHARACTER = 'c';\n\t/** @var string the argument is treated as an integer and presented as a (signed) decimal number. */\n\tpublic const T_INT = 'd';\n\t/** @var string the argument is treated as scientific notation (e.g. 1.2e+2). The precision specifier stands for the\nnumber of digits after the decimal point since PHP 5.2.1. In earlier versions, it was taken as number of\nsignificant digits (one less). */\n\tpublic const T_DOUBLE_AS_SCI = 'e';\n\t/** @var string like %e but uses uppercase letter (e.g. 1.2E+2). */\n\tpublic const T_DOUBLE_AS_SCI_CAP = 'E';\n\t/** @var string the argument is treated as a float and presented as a floating-point number (locale aware). */\n\tpublic const T_FLOAT_LOCALE = 'f';\n\t/** @var string the argument is treated as a float and presented as a floating-point number (non-locale aware).\nAvailable since PHP 5.0.3. */\n\tpublic const T_FLOAT_NO_LOCALE = 'F';\n\t/** @var string shorter of %e and %f. */\n\tpublic const T_FLOAT_AUTO_SCI = 'g';\n\t/** @var string shorter of %E and %F. */\n\tpublic const T_FLOAT_AUTO_SCI_CAP = 'G';\n\t/** @var string shorter of %e and %f, but uses decimal dot rather than locale-specific decimal separator. */\n\tpublic const T_FLOAT_AUTO_SCI_DECIMAL_DOT = 'h';\n\t/** @var string shorter of %E and %F, but uses decimal dot rather than locale-specific decimal separator. */\n\tpublic const T_FLOAT_AUTO_SCI_DECIMAL_DOT_CAP = 'H';\n\t/** @var string the argument is treated as an integer and presented as an octal number. */\n\tpublic const T_INT_AS_OCTAL = 'o';\n\t/** @var string the argument is treated as and presented as a string. */\n\tpublic const T_STRING = 's';\n\t/** @var string the argument is treated as an integer and presented as an unsigned decimal number. */\n\tpublic const T_INT_UNSIGNED = 'u';\n\t/** @var string the argument is treated as an integer and presented as a hexadecimal number (with lowercase letters). */\n\tpublic const T_INT_HEX = 'x';\n\t/** @var string the argument is treated as an integer and presented as a hexadecimal number (with uppercase letters). */\n\tpublic const T_INT_HEX_CAP = 'X';\n\tpublic const VALID_T_TYPES = [self::T_INT_AS_BINARY, self::T_INT_AS_CHARACTER, self::T_INT, self::T_DOUBLE_AS_SCI, self::T_DOUBLE_AS_SCI_CAP, self::T_FLOAT_LOCALE, self::T_FLOAT_NO_LOCALE, self::T_FLOAT_AUTO_SCI, self::T_FLOAT_AUTO_SCI_CAP, self::T_FLOAT_AUTO_SCI_DECIMAL_DOT, self::T_FLOAT_AUTO_SCI_DECIMAL_DOT_CAP, self::T_INT_AS_OCTAL, self::T_STRING, self::T_INT_UNSIGNED, self::T_INT_HEX, self::T_INT_HEX_CAP];\n\tpublic const ARG_TYPE_MISSING = '';\n\tpublic const ARG_TYPE_INT = 'int';\n\tpublic const ARG_TYPE_DOUBLE = 'float';\n\tpublic const ARG_TYPE_STRING = 'string';\n\t/** @var int magic number indicating a dynamic width/precision argument with an implicit (positional) argument index */\n\tpublic const ARG_INDEX_IMPLICIT = 0;\n\t/** @var string[] string    s */\n\tpublic const STRING_TYPES = [self::T_STRING];\n\t/** @var string[] integer    d, u, c, o, x, X, b */\n\tpublic const INTEGER_TYPES = [self::T_INT, self::T_INT_UNSIGNED, self::T_INT_AS_CHARACTER, self::T_INT_AS_OCTAL, self::T_INT_HEX, self::T_INT_HEX_CAP, self::T_INT_AS_BINARY];\n\t/** @var string[] double    g, G, h, H, e, E, f, F */\n\tpublic const DOUBLE_TYPES = [self::T_FLOAT_AUTO_SCI, self::T_FLOAT_AUTO_SCI_CAP, self::T_FLOAT_AUTO_SCI_DECIMAL_DOT, self::T_FLOAT_AUTO_SCI_DECIMAL_DOT_CAP, self::T_DOUBLE_AS_SCI, self::T_DOUBLE_AS_SCI_CAP, self::T_FLOAT_LOCALE, self::T_FLOAT_NO_LOCALE];\n\tpublic const T_INVALID = '';\n\tpublic const T_LITERAL_STRING = '!';\n}\n```\n\n#### Method: ArgumentLexeme-\u003e__construct\n\n```php\nfunction __construct(string $lexItemType, string $val, int $pos, ?int $arg, bool $showPositive, ?string $padChar, ?int $padWidth, bool $leftJustified, ?int $precision [, ?int $widthArgumentIndex = null [, ?int $precisionArgumentIndex = null]])\n```\n\nArgumentLexeme constructor.\n\nLexItem constructor.\n\n---\n\n#### Method: ArgumentLexeme-\u003egetArg\n\n```php\nfunction getArg() : ?int\n```\n\nThe position specifier, such as `%3$s` would return 3 and `%s` would return null\n\n##### Returns:\n\n- ***int*** | ***null*** - null on unspecified\n\n---\n\n#### Method: ArgumentLexeme-\u003egetShowPositive\n\n```php\nfunction getShowPositive() : bool\n```\n\nIs the \"Prefix positive numbers with a plus sign +\" flag enabled\n\n---\n\n#### Method: ArgumentLexeme-\u003egetPadChar\n\n```php\nfunction getPadChar() : ?string\n```\n\nSpecified pad character flag\n\n##### Returns:\n\n- ***string*** | ***null*** - null on unspecified\n\n---\n\n#### Method: ArgumentLexeme-\u003egetPadWidth\n\n```php\nfunction getPadWidth() : ?int\n```\n\nSpecified pad width\n\n##### Returns:\n\n- ***int*** | ***null*** - null on unspecified\n\n---\n\n#### Method: ArgumentLexeme-\u003egetLeftJustified\n\n```php\nfunction getLeftJustified() : bool\n```\n\nIs left-justification flag enabled?\n\n---\n\n#### Method: ArgumentLexeme-\u003egetPrecision\n\n```php\nfunction getPrecision() : ?int\n```\n\nThe Lexeme's indicated precision.\n\n##### Returns:\n\n- ***int*** | ***null*** - null on unspecified\n\n---\n\n#### Method: ArgumentLexeme-\u003egetWidthArgumentIndex\n\n```php\nfunction getWidthArgumentIndex() : ?int\n```\n\nThe argument index supplying a dynamic width, or null if width is static.  \n  \nReturns ARG_INDEX_IMPLICIT (0) when the width argument is taken from the implicit argument list,  \nor an explicit 1-based index when written as `*N$`.\n\n##### Returns:\n\n- ***int*** | ***null*** - null when width is not dynamic\n\n---\n\n#### Method: ArgumentLexeme-\u003egetPrecisionArgumentIndex\n\n```php\nfunction getPrecisionArgumentIndex() : ?int\n```\n\nThe argument index supplying a dynamic precision, or null if precision is static.  \n  \nReturns ARG_INDEX_IMPLICIT (0) when the precision argument is taken from the implicit argument list,  \nor an explicit 1-based index when written as `.*N$`.\n\n##### Returns:\n\n- ***int*** | ***null*** - null when precision is not dynamic\n\n---\n\n#### Method: ArgumentLexeme-\u003eargType\n\n```php\nfunction argType() : string\n```\n\nReturns based on the type of argument one of the following  \n  \nArgumentLexeme::ARG_TYPE_MISSING  \nArgumentLexeme::ARG_TYPE_INT  \nArgumentLexeme::ARG_TYPE_DOUBLE  \nArgumentLexeme::ARG_TYPE_STRING\n\n---\n\n#### Method: ArgumentLexeme-\u003egetLexItemType\n\n```php\nfunction getLexItemType() : string\n```\n\nThe type of the printf Lexeme\n\n---\n\n#### Method: ArgumentLexeme-\u003egetVal\n\n```php\nfunction getVal() : string\n```\n\nThe text of the lexeme\n\n---\n\n#### Method: ArgumentLexeme-\u003egetPos\n\n```php\nfunction getPos() : int\n```\n\nThe string position of the given lexeme","funding_links":["https://www.paypal.me/donatj/15","https://ko-fi.com/donatj","https://github.com/sponsors/donatj"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonatj%2Fprintf-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdonatj%2Fprintf-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdonatj%2Fprintf-parser/lists"}