{"id":17780667,"url":"https://github.com/wandersonwhcr/romans","last_synced_at":"2025-08-08T16:17:29.186Z","repository":{"id":19652989,"uuid":"87566367","full_name":"wandersonwhcr/romans","owner":"wandersonwhcr","description":"A Simple PHP Roman Numerals Library","archived":false,"fork":false,"pushed_at":"2024-09-03T21:02:39.000Z","size":430,"stargazers_count":44,"open_issues_count":5,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-09T01:44:44.450Z","etag":null,"topics":["composer","converter","filter","format","php","roman","roman-number","roman-numeral","validator"],"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/wandersonwhcr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2017-04-07T16:35:12.000Z","updated_at":"2025-03-04T19:22:25.000Z","dependencies_parsed_at":"2024-12-28T14:12:41.566Z","dependency_job_id":"7d1e4639-f82f-43c0-a527-3acdcaa16e50","html_url":"https://github.com/wandersonwhcr/romans","commit_stats":{"total_commits":452,"total_committers":6,"mean_commits":75.33333333333333,"dds":"0.011061946902654829","last_synced_commit":"cb169e4d453c8c40ca8f439d5502de2dce3a715d"},"previous_names":[],"tags_count":42,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersonwhcr%2Fromans","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersonwhcr%2Fromans/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersonwhcr%2Fromans/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wandersonwhcr%2Fromans/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wandersonwhcr","download_url":"https://codeload.github.com/wandersonwhcr/romans/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243500790,"owners_count":20300773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["composer","converter","filter","format","php","roman","roman-number","roman-numeral","validator"],"created_at":"2024-10-27T03:03:28.693Z","updated_at":"2025-03-14T00:02:19.708Z","avatar_url":"https://github.com/wandersonwhcr.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"# romans\n\nA Simple PHP Roman Numerals Library\n\n[![Build Status](https://github.com/wandersonwhcr/romans/actions/workflows/test.yml/badge.svg?branch=main)](https://github.com/wandersonwhcr/romans/actions/workflows/test.yml?query=branch%3Amain)\n[![Updated](https://github.com/wandersonwhcr/romans/actions/workflows/updated.yml/badge.svg)](https://github.com/wandersonwhcr/romans/actions/workflows/updated.yml)\n[![Latest Stable Version](https://poser.pugx.org/wandersonwhcr/romans/v/stable?format=flat)](https://packagist.org/packages/wandersonwhcr/romans)\n[![codecov](https://codecov.io/gh/wandersonwhcr/romans/branch/main/graph/badge.svg)](https://codecov.io/gh/wandersonwhcr/romans)\n[![License](https://poser.pugx.org/wandersonwhcr/romans/license?format=flat)](https://packagist.org/packages/wandersonwhcr/romans)\n[![StandWithUkraine](https://raw.githubusercontent.com/vshymanskyy/StandWithUkraine/main/badges/StandWithUkraine.svg)](https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md)\n\n## Usage\n\nThis library includes a simple couple of filters to convert a `string` with\nRoman number to an `int` that represents the input as decimal and decimal `int`\nto a `string` with Roman number as result.\n\n```php\nuse Romans\\Filter\\RomanToInt;\n\n$filter = new RomanToInt();\n$result = $filter-\u003efilter('MCMXCIX'); // 1999\n```\n\n```php\nuse Romans\\Filter\\IntToRoman;\n\n$filter = new IntToRoman();\n$result = $filter-\u003efilter(1999); // MCMXCIX\n```\n\n## Installation\n\nThis package uses\n[Composer](https://packagist.org/packages/wandersonwhcr/romans) as default\nrepository. You can install it adding the name of package in `require` section\nof `composer.json`, pointing to the last stable version.\n\n```json\n{\n  \"require\": {\n    \"wandersonwhcr/romans\": \"^1.0\"\n  }\n}\n```\n\nAlso, Romans uses Semantic Versioning. The following package versions support\nthese PHP releases:\n\n* Romans `1.0.*`: PHP `^7.0` (Augustus)\n* Romans `1.1.*`: PHP `^7.0` (Tiberius)\n* Romans `1.2.*`: PHP `\u003e=7.4` (Caligula)\n* Romans `1.3.*`: PHP `\u003e=7.4` (Claudius)\n* Romans `1.4.*`: PHP `\u003e=7.4` (Nero)\n* Romans `1.5.*`: PHP `\u003e=8.0` (Galba)\n\n## Integrations\n\nThis library can be used as dependency for projects, making integrations with\nlibraries or frameworks easier. If you want to add more items in this list,\nplease, open an issue or create a pull request, adding your project\nalphabetically.\n\n* [Illuminate Romans](https://github.com/wandersonwhcr/illuminate-romans): Laravel Illuminate Romans Integration\n* [Kirby Romans](https://github.com/moevbiz/k3-romans): Kirby CMS Integration\n* [Laminas Romans](https://github.com/wandersonwhcr/laminas-romans): Laminas Project Romans Integration\n* [Plates Romans Extension](https://github.com/wandersonwhcr/plates-romans): Plates Extension\n* [Twig Roman Numerals Extension](https://github.com/EmilMassey/twig-roman-numerals): Twig Extension (Symfony, WordPress + Timber)\n* ~~[Zend Romans](https://github.com/wandersonwhcr/zend-romans): Zend Framework Romans Integration~~ **DEPRECATED**\n\n## Advanced Usage\n\nThe `Romans` package uses a Lexer-Parser approach and a Deterministic Finite\nAutomaton (DFA) to convert Roman number to `int`, using a Grammar Token library.\n\n```php\nuse Romans\\Grammar\\Grammar;\nuse Romans\\Lexer\\Lexer;\nuse Romans\\Parser\\Parser;\n\n$grammar = new Grammar();\n$lexer   = new Lexer($grammar);\n$parser  = new Parser($grammar);\n\n$tokens = $lexer-\u003etokenize('MCMXCIX');\n\n/*\n$tokens = [\n    0 =\u003e 'M'  // Grammar::T_M\n    1 =\u003e 'C', // Grammar::T_C\n    2 =\u003e 'M', // Grammar::T_M\n    3 =\u003e 'X', // Grammar::T_X\n    4 =\u003e 'C', // Grammar::T_C\n    5 =\u003e 'I', // Grammar::T_I\n    6 =\u003e 'X', // Grammar::T_X\n];\n*/\n\n$result = $parser-\u003eparse($tokens); // 1999\n```\n\n### Exception Handling\n\nThe filter `RomanToInt` uses Lexer to tokenize the input and Parser to build the\n`int` number. When errors are found, the Lexer or Parser throw Exceptions to\nnotify the problem with a specific code.\n\n```php\nuse Romans\\Filter\\RomanToInt;\nuse Romans\\Lexer\\Exception as LexerException;\nuse Romans\\Parser\\Exception as ParserException;\n\n$filter = new RomanToInt();\n\ntry {\n    $filter-\u003efilter($input);\n} catch (LexerException $e) {\n    // Unknown Token (LexerException::UNKNOWN_TOKEN)\n} catch (ParserException $e) {\n    // Invalid Token Type (Not String) (ParserException::INVALID_TOKEN_TYPE)\n    // Unknown Token (ParserException::UNKNOWN_TOKEN)\n    // Invalid Roman (ParserException::INVALID_ROMAN)\n}\n```\n\nYou can use this structure to validate Roman numbers, adding a _try..catch_\nblock to check if `$input` is valid. Also, you can validate if an `int` can be\nfiltered to Roman using an `IntToRoman` filter.\n\n```php\nuse Romans\\Filter\\IntToRoman;\nuse Romans\\Filter\\Exception as FilterException;\n\n$filter = new IntToRoman();\n\ntry {\n    $filter-\u003efilter($input);\n} catch (FilterException $e) {\n    // Invalid Integer (\u003c 0) (FilterException::INVALID_INTEGER)\n}\n```\n\n### Zero\n\nThe zero value is represented as `string` `\"N\"`, the initial of _nulla_ or\n_nihil_, the Latin word for \"nothing\" (see references).\n\n```php\nuse Romans\\Filter\\RomanToInt;\nuse Romans\\Filter\\IntToRoman;\n\n$filter = new RomanToInt();\n$result = $filter-\u003efilter('N'); // 0 (Zero)\n\n$filter = new IntToRoman();\n$result = $filter-\u003efilter(0); // N\n```\n\n### Cache\n\nThis package uses [PSR-6 Caching Interface](https://www.php-fig.org/psr/psr-6)\nto improve execution, mainly over loops (like `while` or `foreach`) using cache\nlibraries. Any PSR-6 implementation can be used and we suggest\n[Symfony Cache](https://packagist.org/packages/symfony/cache) package.\n\n```php\nuse Romans\\Filter\\IntToRoman;\nuse Romans\\Filter\\RomanToInt;\nuse Symfony\\Component\\Cache\\Adapter\\ArrayAdapter;\n\n$cache = new ArrayAdapter();\n\n$filter = new RomanToInt();\n$filter-\u003esetCache($cache);\n$result = $filter-\u003efilter('MCMXCIX'); // 1999\n$result = $filter-\u003efilter('MCMXCIX'); // 1999 (from cache)\n\n$filter = new IntToRoman();\n$filter-\u003esetCache($cache);\n$result = $filter-\u003efilter(1999); // MCMXCIX\n$result = $filter-\u003efilter(1999); // MCMXCIX (from cache)\n```\n\n## Development\n\nYou can use Docker Compose to build an image and run a container to develop and\ntest this package.\n\n```bash\ndocker-compose build\ndocker-compose run --rm romans composer install\ndocker-compose run --rm romans composer test\n```\n\n## Techniques\n\nThis section describes techniques used by this package to convert Roman numbers\ninto `int` and vice-versa.\n\n### Lexer-Parser\n\nA Lexer-Parser approach was chosen because the validating and reading of Roman\nnumbers are more simplified: the Lexer is responsible for reading and transform\nthe input into tokens, validating content at char level; and the Parser is\nresponsible for transform tokens into numbers, validating content at position\nlevel and converting to `int` through a DFA.\n\nWikipedia says that \"lexical analysis is the process of converting a sequence of\ncharacters into a sequence of tokens\", that \"is a structure representing a\nlexeme that explicity indicates its categorization for the purpose of parsing\".\nEven, Wikipedia says that \"parsing or syntax analysis is the process of\nanalysing symbols conforming to the rules of a formal grammar\".\n\nThis structure makes easier the development of a structure responsible to read\nan input `string`, converting it to another structure according to specific\ncharset and its position inside input.\n\n### Deterministic Finite Automaton (DFA)\n\nA DFA was developed to check if a `string` with Roman number is valid. This\ntechnique was choiced because other implementations simply convert the input\nwithout checking rules, like four chars sequentially.\n\nThe current automaton definition is declared below.\n\n```plain\nM  = (Q, Σ, δ, q0, F)\nQ  = { a, b, c, d, e, f, g, y, z }\nΣ  = { I, V, X, L, C, D, M, N }\nq0 = g\nF  = { z }\n\nz -\u003e ε\ny -\u003e $z\na -\u003e y | Iy  | IIy | IIIy\nb -\u003e a | IVy | Va  | IXy\nc -\u003e b | Xb  | XXb | XXXb\nd -\u003e c | XLb | Lc  | XCb\ne -\u003e d | Cd  | CCd | CCCd\nf -\u003e e | CDd | De  | CMd\ng -\u003e f | Ny  | Mg\n```\n\n## References\n\n* Rapid Tables: [How to Convert Roman Numerals to Numbers](http://www.rapidtables.com/convert/number/how-roman-numerals-to-number.htm)\n* Wikipedia: [Zero in Roman Numerals](https://en.wikipedia.org/wiki/Roman_numerals#Zero)\n* Wikipedia: [Lexical Analysis](https://en.wikipedia.org/wiki/Lexical_analysis)\n* Wikipedia: [Parsing](https://en.wikipedia.org/wiki/Parsing)\n* Wikipedia: [Deterministic Finite Automaton](https://en.wikipedia.org/wiki/Deterministic_finite_automaton)\n\n## License\n\nThis package is opensource and available under MIT license described in\n[LICENSE](https://github.com/wandersonwhcr/romans/blob/main/LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwandersonwhcr%2Fromans","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwandersonwhcr%2Fromans","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwandersonwhcr%2Fromans/lists"}