{"id":17955271,"url":"https://github.com/atifaziz/gratt","last_synced_at":"2025-03-25T01:31:14.264Z","repository":{"id":43057380,"uuid":"216065737","full_name":"atifaziz/Gratt","owner":"atifaziz","description":"A Generic Vaughn Pratt's top-down operator precedence parser for .NET Standard","archived":false,"fork":false,"pushed_at":"2022-07-12T17:32:36.000Z","size":102,"stargazers_count":10,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-19T06:39:52.580Z","etag":null,"topics":["csharp","dotnet","dotnet-standard","parser","pratt","pratt-parser","tdop"],"latest_commit_sha":null,"homepage":"https://www.nuget.org/packages/Gratt/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/atifaziz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"COPYING.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-10-18T16:31:16.000Z","updated_at":"2025-01-25T22:06:29.000Z","dependencies_parsed_at":"2022-09-24T09:32:54.287Z","dependency_job_id":null,"html_url":"https://github.com/atifaziz/Gratt","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atifaziz%2FGratt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atifaziz%2FGratt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atifaziz%2FGratt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/atifaziz%2FGratt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/atifaziz","download_url":"https://codeload.github.com/atifaziz/Gratt/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245381532,"owners_count":20606047,"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":["csharp","dotnet","dotnet-standard","parser","pratt","pratt-parser","tdop"],"created_at":"2024-10-29T10:25:41.853Z","updated_at":"2025-03-25T01:31:14.004Z","avatar_url":"https://github.com/atifaziz.png","language":"C#","readme":"# Gratt\n\nGratt is a _generic_ implementation of a [Pratt parser] in C# for .NET\nStandard.\n\nA _Pratt parser_ is the affectionate name for a simple parsing\ntechnique presented by [Vaughn Pratt][pratt] in his 1973 paper “[Top\ndown operator precedence][TDOP]” ([TDOP]).\n\nGratt was inspired by the design of the Java implementation presented by [Bob\nNystrom] in his journal entry “[Pratt Parsers: Expression Parsing Made\nEasy][easy-pratt]”. The actual inspiration was the simplification and\nseparation of interfaces in terms of _prefix_ (_nud_) and _infix (led)\nparselets_ (rather than the full Java implementation):\n\n```java\ninterface PrefixParselet {\n  Expression parse(Parser parser, Token token);\n}\n\ninterface InfixParselet {\n  Expression parse(Parser parser, Expression left, Token token);\n}\n```\n\nThe unit tests for Gratt re-create and test the parser for the toy language\n[Bantam] discussed in Bob's journal entry.\n\nThe unit tests also contain a complete implementation for parsing and\nevaluating [C# pre-processing expressions][cs-pp-expr] used in conditional\ndirectives `#if` and `#elif`.\n\nUnlike Bob's Java implementation, Gratt's parser is completely generic:\n\n```c#\nclass Parser\u003cTState, TKind, TToken, TPrecedence, TResult\u003e\n{\n    // ...\n}\n```\n\nIt can therefore work with any model of tokens (`TToken`), token types\n(`TKind`), precedence (`TPrecedence`) and result (`TResult`). It can also hold\nany user-defined state (`TState`) that may be needed during parsing although it\nis not required. An overload without any user-state simply assumes a\n[_unit_][unit].\n\nUnlike Bob's Java implementation, Gratt does not define any interfaces to\nrepresent (prefix or infix) parselets. Instead, it relies on them being simple\nfunctions:\n\n```c#\n// version 2.0+\n\npublic static TResult\n    Parse\u003cTState, TKind, TToken, TPrecedence, TResult\u003e(\n        TState state,\n        TPrecedence initialPrecedence, IComparer\u003cTPrecedence\u003e precedenceComparer,\n        IEqualityComparer\u003cTKind\u003e kindEqualityComparer,\n        TKind eoi, Func\u003cTToken, Exception\u003e eoiErrorSelector,\n        Func\u003cTKind, TToken, TState, Func\u003cTToken, Parser\u003cTState, TKind, TToken, TPrecedence, TResult\u003e, TResult\u003e\u003e prefixFunction,\n        Func\u003cTKind, TToken, TState, (TPrecedence, Func\u003cTToken, TResult, Parser\u003cTState, TKind, TToken, TPrecedence, TResult\u003e, TResult\u003e)?\u003e infixFunction,\n        IEnumerable\u003c(TKind, TToken)\u003e lexer)\n```\n\nThe above might read a little dense so below is a brief explanation of each\nparameter in order:\n\n- a user-defined state that is associated with the parser object during parsing\n- the initial precedence (this is usually 0 if `TPrecedence` is an `int`)\n- a precedence comparer\n- an equality comparer that can compare two token kinds\n- a token kind marking _end of input_ (EOI)\n- a function used to project an `Exception` when the EOI token is not the\n  the last token of the tokens sequence\n- a prefix function\n- an infix function\n- a sequence of token kind and token pairs (2-tuple) yielded by a lexer\n  implementation\n\nA prefix function receives a token kind, a token and a user-defined state as\ninput and it _must_ return a parsing function if the token kind has prefix\nparsing semantics. If the token kind is invalid as a prefix, then the token and\nuser-defined state may be used for the purpose of providing details in a thrown\nexception (e.g., while `TKind` may be a simple `enum` type, `TToken` will\nusually be a rich object containing the position of the token in the source\ntext among other data). The parsing function returned by the prefix function\nthen receives the token and the parser as arguments and produces some result\n(`TResult`).\n\nAn infix function receives a token kind, a token and a user-defined state as\ninput as arguments and _optionally_ returns a precedence (_left binding power_)\nand parsing function pair. The parsing function then receives the token, the\nleft result and the parser as arguments and produces some result (`TResult`).\n\n\n[pratt]: https://en.wikipedia.org/wiki/Vaughan_Pratt\n[TDOP]: https://web.archive.org/web/20151223215421/http://hall.org.ua/halls/wizzard/pdf/Vaughan.Pratt.TDOP.pdf\n[Pratt parser]: https://en.wikipedia.org/wiki/Pratt_parser\n[Bob Nystrom]: http://stuffwithstuff.com/\n[easy-pratt]: http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/\n[Bantam]: https://github.com/munificent/bantam\n[unit]: https://docs.microsoft.com/en-us/dotnet/api/system.valuetuple\n[cs-pp-expr]: https://github.com/dotnet/csharplang/blob/892af9016b3317a8fae12d195014dc38ba51cf16/spec/lexical-structure.md#pre-processing-expressions\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatifaziz%2Fgratt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fatifaziz%2Fgratt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fatifaziz%2Fgratt/lists"}