{"id":15056331,"url":"https://github.com/bel-framework/bel-scan","last_synced_at":"2026-02-16T10:10:37.101Z","repository":{"id":233898623,"uuid":"786812798","full_name":"bel-framework/bel-scan","owner":"bel-framework","description":"Generic scanner for Erlang","archived":false,"fork":false,"pushed_at":"2024-04-30T20:32:10.000Z","size":95,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-21T00:50:14.921Z","etag":null,"topics":["erlang","erlang-library","parser","parser-library"],"latest_commit_sha":null,"homepage":"","language":"Erlang","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/bel-framework.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["williamthome"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":["https://www.buymeacoffee.com/williamthome"]}},"created_at":"2024-04-15T10:57:56.000Z","updated_at":"2024-04-17T14:18:37.000Z","dependencies_parsed_at":"2024-04-30T21:48:33.564Z","dependency_job_id":"a3227de4-c3e0-488b-85c2-181da04aeee3","html_url":"https://github.com/bel-framework/bel-scan","commit_stats":null,"previous_names":["bel-framework/bel-scan"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bel-framework%2Fbel-scan","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bel-framework%2Fbel-scan/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bel-framework%2Fbel-scan/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bel-framework%2Fbel-scan/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bel-framework","download_url":"https://codeload.github.com/bel-framework/bel-scan/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243532562,"owners_count":20306156,"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":["erlang","erlang-library","parser","parser-library"],"created_at":"2024-09-24T21:49:57.761Z","updated_at":"2025-10-04T13:15:31.812Z","avatar_url":"https://github.com/bel-framework.png","language":"Erlang","funding_links":["https://github.com/sponsors/williamthome","https://www.buymeacoffee.com/williamthome"],"categories":[],"sub_categories":[],"readme":"# bel-framework/bel-scan\n\nGeneric scanner for Erlang.\n\n## Example\n\nThe example below is simplistic and scans a string into a tokens list containing params and texts. Params are enclosed with two brackets, like `{{ foo }}`, and produces the token `{param, {Line, Column}, \u003c\u003c\"foo\"\u003e\u003e}`. Texts, like `bar`, are scanned as `{text, {Line, Column}, \u003c\u003c\"bar\"\u003e\u003e}`.\n\nThe output of the [module](#module) of the example below is:\n\n```shell\n1\u003e my_scan:string(\u003c\u003c\"foo {{ bar }} baz\"\u003e\u003e).\n[{text,{1,1},\u003c\u003c\"foo \"\u003e\u003e},\n {param,{1,5},\u003c\u003c\"bar\"\u003e\u003e},\n {text,{1,14},\u003c\u003c\" baz\"\u003e\u003e}]\n```\n\n### Module\n\n```erlang\n-module(my_scan).\n-behaviour(bel_scan).\n\n% API\n-export([ string/1 ]).\n\n% bel_scan callbacks\n-export([ init/1, handle_char/3, handle_tokens/2 ]).\n\n-import(bel_scan, [ incr_col/1\n                  , incr_col/2\n                  , new_ln/1\n                  , continue/2\n                  , skip_new_lns/2\n                  , update_pos/1\n                  , token/2\n                  , push_token/2\n                  , snapshot/1\n                  , fold/2\n                  ]).\n\n-record(state, {}).\n\n%%%=====================================================================\n%%% API\n%%%=====================================================================\n\nstring(Text) -\u003e\n    Scan = bel_scan:new(#{\n        input =\u003e Text,\n        handler =\u003e ?MODULE\n    }),\n    bel_scan:string(#{}, Scan).\n\n%%%=====================================================================\n%%% bel_scan callbacks\n%%%=====================================================================\n\ninit(Opts) when is_map(Opts) -\u003e\n    {ok, #state{}}.\n\nhandle_char(${, \u003c\u003c${, $\\s, Rest/bitstring\u003e\u003e, Scan) -\u003e\n    scan_param(Rest, fold(Scan, [\n        fun(S) -\u003e push_token(token(text, S), S) end,\n        fun(S) -\u003e snapshot(S) end,\n        fun(S) -\u003e incr_col(3, S) end,\n        fun(S) -\u003e update_pos(S) end\n    ]));\nhandle_char(_Char, \u003c\u003c\u003e\u003e, Scan) -\u003e\n    continue(\u003c\u003c\u003e\u003e, fold(Scan, [\n        fun(S) -\u003e incr_col(S) end,\n        fun(S) -\u003e push_token(token(text, S), S) end\n    ]));\nhandle_char(_Char, \u003c\u003cRest/bitstring\u003e\u003e, Scan) -\u003e\n    continue(Rest, incr_col(Scan)).\n\nhandle_tokens(Tokens, _Scan) -\u003e\n    lists:reverse(Tokens).\n\n%%%=====================================================================\n%%% Internal functions\n%%%=====================================================================\n\nscan_param(\u003c\u003c$\\s, $}, $}, Rest/bitstring\u003e\u003e, Scan) -\u003e\n    continue(Rest, fold(Scan, [\n        fun(S) -\u003e push_token(token(param, S), S) end,\n        fun(S) -\u003e incr_col(3, S) end,\n        fun(S) -\u003e update_pos(S) end,\n        fun(S) -\u003e snapshot(S) end\n    ]));\nscan_param(\u003c\u003cRest0/bitstring\u003e\u003e, Scan0) -\u003e\n    {ok, {_Char, Rest, Scan}} = skip_new_lns(Rest0, Scan0),\n    scan_param(Rest, incr_col(Scan)).\n```\n\n## Build\n\n```shell\n$ rebar3 compile\n```\n\n## Test\n\n```shell\n$ rebar3 eunit\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbel-framework%2Fbel-scan","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbel-framework%2Fbel-scan","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbel-framework%2Fbel-scan/lists"}