{"id":37134206,"url":"https://github.com/tompaton/goparsec","last_synced_at":"2026-01-14T15:39:24.924Z","repository":{"id":57548337,"uuid":"89845859","full_name":"tompaton/goparsec","owner":"tompaton","description":"Parser combinator in Go. If there are any cross platform issues or backward compatibility issues, please reach out.","archived":false,"fork":true,"pushed_at":"2017-04-30T12:41:43.000Z","size":1379,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T02:13:03.209Z","etag":null,"topics":["golang","parser","parser-combinators"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"prataprc/goparsec","license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tompaton.png","metadata":{"files":{"readme":"README.rst","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}},"created_at":"2017-04-30T11:06:47.000Z","updated_at":"2017-04-30T11:08:02.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/tompaton/goparsec","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/tompaton/goparsec","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tompaton%2Fgoparsec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tompaton%2Fgoparsec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tompaton%2Fgoparsec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tompaton%2Fgoparsec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tompaton","download_url":"https://codeload.github.com/tompaton/goparsec/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tompaton%2Fgoparsec/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28424374,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T13:30:50.153Z","status":"ssl_error","status_checked_at":"2026-01-14T13:29:08.907Z","response_time":107,"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":["golang","parser","parser-combinators"],"created_at":"2026-01-14T15:39:24.114Z","updated_at":"2026-01-14T15:39:24.914Z","avatar_url":"https://github.com/tompaton.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"Parser combinator library in Golang.\n-----------------------------------\n\nA library to construct top-down recursive backtracking parsers using\nparser-combinators.  To know more about theory of parser\ncombinators, refer to : http://en.wikipedia.org/wiki/Parser_combinator\n\nThis package contains following components,\n\n* standard set of combinators, parsing algorithms can create input\n  specific combinator functions on top of the standard set.\n* regular expression based scanner.\n* standard set of terminal tokens.\n\n**API reference**: https://godoc.org/github.com/tompaton/goparsec\n\ncombinators\n~~~~~~~~~~~\n\nEvery combinator should confirm to the following signature,\n\n.. code-block:: go\n\n    // ParsecNode type defines a node in the AST\n    type ParsecNode interface{}\n\n    // Parser function parses input text, higher order parsers are\n    // constructed using combinators.\n    type Parser func(Scanner) (ParsecNode, Scanner)\n\n    // Nodify callback function to construct custom ParsecNode.\n    type Nodify func([]ParsecNode) ParsecNode\n\ncombinators take a variable number of parser functions and\nreturn a new parser function.\n\n`Nodify` is user supplied callback function, called by combinator when the\nrule matches current input text. The callback function receives a\ncollection of parsecNode interface generated by `parsers`.\n\nA `Parser` function must take a new copy of `Scanner` instance, with current\ncursor, as argument, and consume the scanner as long as there is a match. If\nthe parser could not match with input text it returns the scanner without\nconsuming any input. For example, the following snippet is from `And`\ncombinator,\n\n.. code-block:: go\n\n    var ns = make([]ParsecNode, 0, len(parsers))\n    var n ParsecNode\n    news := s.Clone()\n    for _, parser := range parsers {\n        n, news = doParse(parser, news)\n        if n == nil {\n            return nil, s\n        }\n        ns = append(ns, n)\n    }\n    return docallback(callb, ns), news\n\nwe can see that a new instance of `s` is passed to each `parser` and when one\nof the parser returns failure (where n==nil), it simply returns the scanner\nwithout consuming any tokens. Otherwise, it returns the new-scanner `news`\nreturned by the last parser.\n\nList of combinators\n-------------------\n\nAnd\n~~~\n\n.. code-block:: go\n    func And(callb Nodify, parsers ...interface{}) Parser {\n\naccepts a collection of parsers that must sequentially match current\ninput text, combinator fails when any of the parser fails to match.\n\nnodify callback is called with a slice of ParsecNodes obtained from each\nparser, otherwise callback is ignored.\n\nOrdChoice\n~~~~~~~~~\n\n.. code-block:: go\n    func OrdChoice(callb Nodify, parsers ...interface{}) Parser {\n\naccepts a collection of parsers, where atleast one of the parser should\nmatch current input text, combinator fails when all the parser fail to\nmatch.\n\nnodify callback is called with a slice of single parsecNode element when\none of the input parser matches with input text, otherwise callback is\nignored.\n\nwhen a parser matches the input text remaining parsers are not tried.\n\nKleene\n~~~~~~\n\n.. code-block:: go\n    func Kleene(callb Nodify, parsers ...interface{}) Parser {\n\naccepts a pair of parser, where the first element must match `zero or more\ntimes` with current input text and the second optional element acts as token\nseparator, kleene combinator will exit when the first parser or the\nsecond parser, if specified, fails.\n\nnodify callback is called with a slice of ParsecNodes obtained from every\nmatch of the first parser, otherwise called with empty-slice of ParsecNodes.\n\nMany\n~~~~\n\n.. code-block:: go\n    func Many(callb Nodify, parsers ...interface{}) Parser {\n\naccepts a pair of parser, where the first element must match `one or more\ntimes` with current input text and the second optional element acts as token\nseparator. Note that the Many repeatition will exit when first parser or\nsecond parser, if specified, fails.\n\nnodify callback is called with a slice of ParsecNodes obtained from every\nmatch of the first parser, otherwise callback is ignored.\n\nManyUntil\n~~~~\n\n.. code-block:: go\n    func ManyUntil(callb Nodify, parsers ...interface{}) Parser {\n\naccepts a two or three parsers, where the first element must match `one or more\ntimes` with current input text and the second optional element acts as token\nseparator. The last parser specifies a final token to stop matching. Note that\nthe ManyUntil repetition will exit when first parser or second parser, if\nspecified, fails or the last parser succeeds.\n\nnodify callback is called with a slice of ParsecNodes obtained from every\nmatch of the first parser, otherwise callback is ignored.\n\nMaybe\n~~~~~\n\n.. code-block:: go\n    func Maybe(callb Nodify, parser interface{}) Parser {\n\naccepts a parser that can either match or does-not-match with current\ninput text.\n\nnodify callback is called with a slice of single parsecNode element if\n`Maybe` succeeds, otherwise callback is ignored.\n\nOptional\n~~~~~\n\n.. code-block:: go\n    func Optional(callb Nodify, parser interface{}, default ParsecNode) Parser {\n\naccepts a parser that can either match or does-not-match with current\ninput text.\n\nnodify callback is called with a slice of single parsecNode element if\n`Optional` succeeds, otherwise the default parsecNode is returned.\n\nusing the builtin scanner\n-------------------------\n\nThe builtin scanner library manages the input buffer and a cursor into the\nbuffer. Create a new scanner instance,\n\n.. code-block:: go\n\n    s := parsec.NewScanner(text)\n\nthe scanner library supplies method receivers like `Match()`, `SkipWS()` and\n`Endof()`. refer to scanner.go for more information on each of these methods.\n\nExamples\n~~~~~~~~\n\n- expr/expr.go, implements a parsec grammer to parse arithmetic expressions.\n- json/json.go, implements a parsec grammer to parse JSON document.\n\nclone the repository run the benchmark suite\n\n.. code-block:: bash\n\n    $ cd expr/\n    $ go test -test.bench=. -test.benchmem=true\n    $ cd json/\n    $ go test -test.bench=. -test.benchmem=true\n\nto run the example program,\n\n.. code-block:: bash\n\n    # to parse expression\n    $ go run tools/parsec/parsec.go -expr \"10 + 29\"\n\n    # to parse JSON string\n    $ go run tools/parsec/parsec.go -json '{ \"key1\" : [10, \"hello\", true, null, false] }'\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftompaton%2Fgoparsec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftompaton%2Fgoparsec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftompaton%2Fgoparsec/lists"}