{"id":25195867,"url":"https://github.com/s-expressionists/eclector","last_synced_at":"2026-02-16T11:35:01.866Z","repository":{"id":48325705,"uuid":"118264746","full_name":"s-expressionists/Eclector","owner":"s-expressionists","description":"A portable Common Lisp reader that is highly customizable, can recover from errors and can return concrete syntax trees","archived":false,"fork":false,"pushed_at":"2026-01-27T16:31:04.000Z","size":9260,"stargazers_count":126,"open_issues_count":12,"forks_count":11,"subscribers_count":12,"default_branch":"master","last_synced_at":"2026-01-28T03:03:15.384Z","etag":null,"topics":["common-lisp","concrete-syntax-trees","error-recovery","extensible","portable","reader"],"latest_commit_sha":null,"homepage":"https://s-expressionists.github.io/Eclector/","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/s-expressionists.png","metadata":{"files":{"readme":"README.md","changelog":"NEWS","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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2018-01-20T17:25:29.000Z","updated_at":"2026-01-13T01:55:51.000Z","dependencies_parsed_at":"2025-12-31T11:01:25.685Z","dependency_job_id":null,"html_url":"https://github.com/s-expressionists/Eclector","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/s-expressionists/Eclector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s-expressionists%2FEclector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s-expressionists%2FEclector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s-expressionists%2FEclector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s-expressionists%2FEclector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/s-expressionists","download_url":"https://codeload.github.com/s-expressionists/Eclector/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/s-expressionists%2FEclector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29506768,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-16T09:05:14.864Z","status":"ssl_error","status_checked_at":"2026-02-16T08:55:59.364Z","response_time":115,"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":["common-lisp","concrete-syntax-trees","error-recovery","extensible","portable","reader"],"created_at":"2025-02-10T01:38:54.156Z","updated_at":"2026-02-16T11:35:01.860Z","avatar_url":"https://github.com/s-expressionists.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Eclector: A portable and extensible Common Lisp Reader\n\n## Introduction\n\nThe `eclector` system provides a portable implementation of a reader\nfollowing the Common Lisp specification.\n\n**``eclector`` is under active development. Its ASDF system structure,\npackage structure, exported symbols and protocols may change at any\ntime but are becoming less and less likely to do so in incompatible\nways. Consult the NEWS file or the \"Changelog\" section of the manual\nfor lists of changes in specific versions.**\n\nThis document only gives a very brief overview and highlights some\nfeatures. Proper documentation can be found in the `documentation`\ndirectory.\n\n## Usage Overview and Highlights\n\n### Basics\n\nIn the simplest case, the eclector reader can be used like any Common\nLisp reader:\n\n* ```lisp\n  (with-input-from-string (stream \"(1 2 3)\")\n    (eclector.reader:read stream))\n  ; =\u003e (1 2 3)\n  ```\n\n* ```lisp\n  (eclector.reader:read-from-string \"#C(1 1)\")\n  ; =\u003e #C(1 1) 7\n  ```\n\n### Error Recovery\n\nIn contrast to many other reader implementations, eclector can recover\nfrom most errors in the input supplied to it and continue\nreading. This capability is realized as a restart named\n`eclector.reader:recover` which is established whenever an error is\nsignaled for which a recovery strategy is available.\n\nFor example, the following code\n\n```lisp\n(handler-bind ((error (lambda (condition)\n                        (let ((restart (find-restart 'eclector.reader:recover)))\n                          (format t \"Recovering from error:~%~2@T~A~%using~%~2@T~A~%\"\n                                  condition restart))\n                        (eclector.reader:recover))))\n  (eclector.reader:read-from-string \"`(::foo ,\"))\n```\n\nproduces this:\n\n```\nRecovering from error:\n  A symbol token must not start with two package markers as in ::name.\nusing\n  Treat the character as if it had been escaped.\nRecovering from error:\n  While reading unquote, expected an object when input ended.\nusing\n  Use NIL in place of the missing object.\nRecovering from error:\n  While reading list, expected the character ) when input ended.\nusing\n  Return a list of the already read elements.\n; =\u003e (ECLECTOR.READER:QUASIQUOTE (:FOO (ECLECTOR.READER:UNQUOTE NIL))) 9\n```\n\nindicating that eclector recovered from multiple errors and consumed\nall input. Of course, the returned expression is likely unsuitable for\nevaluation, but recovery is useful for detecting multiple errors in\none go and performing further processing such as static analysis.\n\n### Custom Parse Results\n\nUsing features provided in the `eclector.parse-result` package,\nthe reader can produce parse results controlled by the client,\noptionally including source tracking and representation of skipped\ninput (due to e.g. comments and reader conditionals):\n\n```lisp\n(defclass my-client (eclector.parse-result:parse-result-client)\n  ())\n\n(defmethod eclector.parse-result:make-expression-result\n    ((client my-client) (result t) (children t) (source t))\n  (list :result result :source source :children children))\n\n(defmethod eclector.parse-result:make-skipped-input-result\n    ((client my-client) (stream t) (reason t) (children t) (source t))\n  (list :reason reason :source source :children children))\n\n(with-input-from-string (stream \"(1 #|comment|# \\\"string\\\")\")\n  (eclector.parse-result:read (make-instance 'my-client) stream))\n```\n\n### Concrete Syntax Trees\n\nThe `eclector-concrete-syntax-tree` system provides a variant of the\n`eclector` reader that produces instances of the concrete syntax tree\nclasses provided by the [concrete syntax tree library]:\n\n```lisp\n(eclector.concrete-syntax-tree:read-from-string \"(1 2 3)\")\n; =\u003e #\u003cCONCRETE-SYNTAX-TREE:CONS-CST raw: (1 2 3) {100BF94EF3}\u003e 7 NIL\n```\n\n[concrete syntax tree library]: https://github.com/s-expressionists/Concrete-Syntax-Tree\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs-expressionists%2Feclector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fs-expressionists%2Feclector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fs-expressionists%2Feclector/lists"}