{"id":27943840,"url":"https://github.com/programmatix/cparser","last_synced_at":"2026-04-25T23:37:21.156Z","repository":{"id":122050534,"uuid":"117501879","full_name":"programmatix/CParser","owner":"programmatix","description":"Parses the C language into a clean abstract syntax tree that you can use in your JVM project.","archived":false,"fork":false,"pushed_at":"2018-02-03T05:35:33.000Z","size":54,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-05-07T12:19:30.278Z","etag":null,"topics":["cparser","fastparse","grammar","jvm","language","syntax-tree"],"latest_commit_sha":null,"homepage":null,"language":"Scala","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/programmatix.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}},"created_at":"2018-01-15T05:39:40.000Z","updated_at":"2018-02-03T05:36:13.000Z","dependencies_parsed_at":null,"dependency_job_id":"7754e345-666b-4d8b-a212-97db93b94e89","html_url":"https://github.com/programmatix/CParser","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/programmatix/CParser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmatix%2FCParser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmatix%2FCParser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmatix%2FCParser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmatix%2FCParser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/programmatix","download_url":"https://codeload.github.com/programmatix/CParser/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/programmatix%2FCParser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32280981,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: 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":["cparser","fastparse","grammar","jvm","language","syntax-tree"],"created_at":"2025-05-07T12:19:29.003Z","updated_at":"2026-04-25T23:37:21.150Z","avatar_url":"https://github.com/programmatix.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CParser\n\nParses the C language into a clean abstract syntax tree that you can use in your JVM project. \n\nWritten in Scala, and ScalaJS compatible.\n\n## Getting Started\n\nClone the project.  Add the single required dependency on the lihaoyi's excellent [fastparse library](https://github.com/lihaoyi/fastparse) to your build.sbt:\n\n```\nlibraryDependencies += \"com.lihaoyi\" %%% \"fastparse\" % \"1.0.0\"\n```\n\nThere's two main entry points.  CParser.parseSnippet is for parsing a snippet of C code - something you'd find inside a C function.\nCParser.parse is for parsing a C translation unit - which can be as small as a single function, or as big as a full C file. \n\nBoth functions return a CParseSuccess if they can parse the input, containing an abstract syntax tree in the form of nested case classes.\nparseSnippet returns a Seq of BlockItem, each corresponding to block-item in the C specification, which roughly means \"a line of C code\". \n\n```\n    val parser = new CParser()\n    val parsed: CParseResult = parser.parseSnippet(\"int hello;\")\n\n    // `parsed` can be CParseSuccess or CParseFail\n    parsed match {\n      case CParseSuccess(result: Seq[BlockItem]) =\u003e\n\n        // If success, the result is an abstract syntax tree corresponding to the C code\n        assert (result.head ==\n          SimpleDeclaration(\n            DeclarationSpecifiers(\n              List(\n                TypeSpecifier(\"int\"))),\n            Some(\n              List(\n                DeclaratorEmpty(\n                  Declarator(\n                    None,\n                    DirectDeclaratorOnly(\n                      Identifier(\"hello\")))))))\n        )\n\n      case CParseFail(result) =\u003e\n        println(result)\n    }\n```\n\nparse returns a TranslationUnit, corresponding to translation-unit in the spec, which roughly means 'a complete C file'.\n\n```\n    val parser = new CParser()\n    val parsed: CParseResult = parser.parse(\n      \"\"\"int main(int argc) {\n        | return 0;\n        |}\"\"\".stripMargin)\n\n    // `parsed` can be CParseSuccess or CParseFail\n    parsed match {\n      case CParseSuccess(result: TranslationUnit) =\u003e\n\n        // If success, the result is an abstract syntax tree corresponding to the C code\n        assert (result ==\n          TranslationUnit(\n            List(\n              FunctionDefinition(\n                DeclarationSpecifiers(\n                  List(\n                    TypeSpecifier(\"int\"))),\n                Declarator(None,\n                  FunctionDeclaration(\n                    Identifier(\"main\"),\n                    ParameterTypeList(\n                      List(\n                        ParameterDeclarationDeclarator(\n                          DeclarationSpecifiers(\n                            List(\n                              TypeSpecifier(\"int\"))),\n                          Declarator(\n                            None,\n                            DirectDeclaratorOnly(\n                              Identifier(\"argc\"))))),\n                      ellipses = false))),\n                None,\n                CompoundStatement(\n                  List(\n                    Return(\n                      Some(IntConstant(0))))))))\n        )\n\n      case CParseFail(result) =\u003e\n        println(result)\n    }\n```\n\n## C Language\nThis parser understands the C language grammar defined in [Annex A of this C specification](https://port70.net/~nsz/c/c11/n1570.html#A).\n\nThe grammar needed to be refactored somewhat to be parsable.  The biggest change was removing left-recursion throughout.  Overall though, you won't have much problem matching up the code with the spec.\n\n## Granular Parsers\nCParser contains a lot of different parsers, corresponding to each part of the spec. \n\nIt's best to use either parser.parse (for a C file) or parser.parseSnippet (for the contents of a C function).  These return CParseResults.\n\nBut you're free to use the individual parsers if needed.  These will return fastparse results, so take a look at the [fastparse docs](http://www.lihaoyi.com/fastparse/) for more on how to handle them.\n \nThe most useful parsers are:\n\n* parser.translationUnit - this understands a complete C file\n* parser.blockItem - understands a single line of C inside a function (\"int myVar = 0;\")\n* parser.blockItemList - understands a Seq of multiple blockItems\n\n## Using The Results\nparse and parseSnippet return a CParseResult, which can be either a CParseSuccess or a CParseFail. \n\nA CParseSuccess contains an abstract syntax tree (AST) corresponding to the C specification.  These are best explained with an example:  \n\nThe top-level of the C grammar is translation-unit:\n\n```\n(6.9) translation-unit:\n                external-declaration\n                translation-unit external-declaration\n```   \n\nThis says that a translation-unit is made up of a list of at least one external-declaration's.\n\nSo the parser.translationUnit parser will return a TranslationUnit() case class, containing a list of ExternalDeclaration():\n\n```\ncase class TranslationUnit(v: Seq[ExternalDeclaration])\n```\n\nYou can walk through these structures, referring to the code and spec to see the options at each stage.  Every class is a simple wrapper corresponding nearly 1-to-1 with the C grammar.  \n\nA CParseFail contains the index in the input string where parsing failed, along with an attempt to explain the failure.  As long as you're providing valid C code there shouldn't be parse errors - please raise an issue if you do see them.  \n\n## Contributing\n\nPlease feel free to send PRs!\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrammatix%2Fcparser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprogrammatix%2Fcparser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprogrammatix%2Fcparser/lists"}