Skip to content

Instantly share code, notes, and snippets.

@bluegraybox
Created July 15, 2011 03:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bluegraybox/1083971 to your computer and use it in GitHub Desktop.
Save bluegraybox/1083971 to your computer and use it in GitHub Desktop.
This is the core functionality from the indent parser (sequential Erlang version)
-record(line, {content, indent}).
-record(node, {content, children}).
parse_text_line(Text) ->
%% converts " text" to (:content "text" :indent 4)
Content = string:strip(string:strip(Text, left), left, $\t),
Indent = length(Text) - length(Content),
#line{content=string:strip(Content, right, $\n), indent=Indent}.
%% Split a list of lines in two, breaking on the first line whose indent is =< the minimum.
split_list(_MinIndent, List1, []) -> [lists:reverse(List1), []];
split_list(MinIndent, List1, [First|Rest]) when First#line.indent =< MinIndent ->
[lists:reverse(List1), [First|Rest]];
split_list(MinIndent, List1, [First|Rest]) ->
split_list(MinIndent, [First|List1], Rest).
%% Parse a list of 'line' record into a tree structure, based on indent
build_nodes([]) -> [];
build_nodes([First|Rest]) ->
[ChildLines, SiblingLines] = split_list(First#line.indent, [], Rest),
Children = build_nodes(ChildLines),
Siblings = build_nodes(SiblingLines),
Node = #node{content=First#line.content, children=Children},
[Node|Siblings].
@bluegraybox
Copy link
Author

I eventually discovered lists:splitwith/2, which obsolesces my split_list/3. So you can throw that out and replace line 20 with:

IsChild = fun(L) -> L#line.indent > First#line.indent end,
{ChildLines, SiblingLines} = lists:splitwith(IsChild, Rest),

@bluegraybox
Copy link
Author

Here's the full code for the sequential Erlang version of the indent parser. There's also a concurrent Erlang version and a Lisp version.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment