Merge pull request #53 from jwilberding/fix_bug

Fix argument for iolist_to_binary call
This commit is contained in:
Tristan Sloughter 2014-03-28 09:09:21 -05:00
commit 4c97d4a962
2 changed files with 83 additions and 11 deletions

View file

@ -70,7 +70,7 @@ strip_leading_v(Vsn) ->
-spec find_vsn_from_start_of_branch(string()) -> string(). -spec find_vsn_from_start_of_branch(string()) -> string().
find_vsn_from_start_of_branch(RefTag) -> find_vsn_from_start_of_branch(RefTag) ->
Count = do_cmd("git rev-list HEAD --count"), Count = do_cmd("git rev-list HEAD --count"),
erlang:iolist_to_binary("0.0.0+build.", Count, ".ref.", RefTag). erlang:iolist_to_binary(["0.0.0+build.", Count, ".ref.", RefTag]).
do_cmd(Cmd) -> do_cmd(Cmd) ->
trim_whitespace(os:cmd(Cmd)). trim_whitespace(os:cmd(Cmd)).

View file

@ -1,6 +1,15 @@
-module(ec_semver_parser). -module(ec_semver_parser).
-export([parse/1,file/1]). -export([parse/1,file/1]).
-compile({nowarn_unused_function,[p/4, p/5, p_eof/0, p_optional/1, p_not/1, p_assert/1, p_seq/1, p_and/1, p_choose/1, p_zero_or_more/1, p_one_or_more/1, p_label/2, p_string/1, p_anything/0, p_charclass/1, p_regexp/1, p_attempt/4, line/1, column/1]}). -define(p_anything,true).
-define(p_charclass,true).
-define(p_choose,true).
-define(p_not,true).
-define(p_one_or_more,true).
-define(p_optional,true).
-define(p_scan,true).
-define(p_seq,true).
-define(p_string,true).
-define(p_zero_or_more,true).
-compile(export_all). -compile(export_all).
@ -10,34 +19,45 @@ file(Filename) -> case file:read_file(Filename) of {ok,Bin} -> parse(Bin); Err -
-spec parse(binary() | list()) -> any(). -spec parse(binary() | list()) -> any().
parse(List) when is_list(List) -> parse(list_to_binary(List)); parse(List) when is_list(List) -> parse(list_to_binary(List));
parse(Input) when is_binary(Input) -> parse(Input) when is_binary(Input) ->
setup_memo(), _ = setup_memo(),
Result = case 'semver'(Input,{{line,1},{column,1}}) of Result = case 'semver'(Input,{{line,1},{column,1}}) of
{AST, <<>>, _Index} -> AST; {AST, <<>>, _Index} -> AST;
Any -> Any Any -> Any
end, end,
release_memo(), Result. release_memo(), Result.
-spec 'semver'(input(), index()) -> parse_result().
'semver'(Input, Index) -> 'semver'(Input, Index) ->
p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end). p(Input, Index, 'semver', fun(I,D) -> (p_seq([fun 'major_minor_patch_min_patch'/2, p_optional(p_seq([p_string(<<"-">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_optional(p_seq([p_string(<<"+">>), fun 'alpha_part'/2, p_zero_or_more(p_seq([p_string(<<".">>), fun 'alpha_part'/2]))])), p_not(p_anything())]))(I,D) end, fun(Node, _Idx) -> ec_semver:internal_parse_version(Node) end).
-spec 'major_minor_patch_min_patch'(input(), index()) -> parse_result().
'major_minor_patch_min_patch'(Input, Index) -> 'major_minor_patch_min_patch'(Input, Index) ->
p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end). p(Input, Index, 'major_minor_patch_min_patch', fun(I,D) -> (p_seq([p_choose([p_seq([p_optional(p_string(<<"v">>)), fun 'numeric_part'/2]), fun 'alpha_part'/2]), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2])), p_optional(p_seq([p_string(<<".">>), fun 'version_part'/2]))]))(I,D) end, fun(Node, Idx) ->transform('major_minor_patch_min_patch', Node, Idx) end).
-spec 'version_part'(input(), index()) -> parse_result().
'version_part'(Input, Index) -> 'version_part'(Input, Index) ->
p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end). p(Input, Index, 'version_part', fun(I,D) -> (p_choose([fun 'numeric_part'/2, fun 'alpha_part'/2]))(I,D) end, fun(Node, Idx) ->transform('version_part', Node, Idx) end).
-spec 'numeric_part'(input(), index()) -> parse_result().
'numeric_part'(Input, Index) -> 'numeric_part'(Input, Index) ->
p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end). p(Input, Index, 'numeric_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:list_to_integer(erlang:binary_to_list(erlang:iolist_to_binary(Node))) end).
-spec 'alpha_part'(input(), index()) -> parse_result().
'alpha_part'(Input, Index) -> 'alpha_part'(Input, Index) ->
p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end). p(Input, Index, 'alpha_part', fun(I,D) -> (p_one_or_more(p_charclass(<<"[A-Za-z0-9]">>)))(I,D) end, fun(Node, _Idx) ->erlang:iolist_to_binary(Node) end).
transform(_,Node,_Index) -> Node. transform(_,Node,_Index) -> Node.
-file("peg_includes.hrl", 1).
-type index() :: {{line, pos_integer()}, {column, pos_integer()}}.
-type input() :: binary().
-type parse_failure() :: {fail, term()}.
-type parse_success() :: {term(), input(), index()}.
-type parse_result() :: parse_failure() | parse_success().
-type parse_fun() :: fun((input(), index()) -> parse_result()).
-type xform_fun() :: fun((input(), index()) -> term()).
p(Inp, Index, Name, ParseFun) -> -spec p(input(), index(), atom(), parse_fun(), xform_fun()) -> parse_result().
p(Inp, Index, Name, ParseFun, fun(N, _Idx) -> N end).
p(Inp, StartIndex, Name, ParseFun, TransformFun) -> p(Inp, StartIndex, Name, ParseFun, TransformFun) ->
case get_memo(StartIndex, Name) of % See if the current reduction is memoized case get_memo(StartIndex, Name) of % See if the current reduction is memoized
{ok, Memo} -> %Memo; % If it is, return the stored result {ok, Memo} -> %Memo; % If it is, return the stored result
@ -54,12 +74,15 @@ p(Inp, StartIndex, Name, ParseFun, TransformFun) ->
Result Result
end. end.
-spec setup_memo() -> ets:tid().
setup_memo() -> setup_memo() ->
put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])). put({parse_memo_table, ?MODULE}, ets:new(?MODULE, [set])).
-spec release_memo() -> true.
release_memo() -> release_memo() ->
ets:delete(memo_table_name()). ets:delete(memo_table_name()).
-spec memoize(index(), atom(), parse_result()) -> true.
memoize(Index, Name, Result) -> memoize(Index, Name, Result) ->
Memo = case ets:lookup(memo_table_name(), Index) of Memo = case ets:lookup(memo_table_name(), Index) of
[] -> []; [] -> [];
@ -67,6 +90,7 @@ memoize(Index, Name, Result) ->
end, end,
ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}). ets:insert(memo_table_name(), {Index, [{Name, Result}|Memo]}).
-spec get_memo(index(), atom()) -> {ok, term()} | {error, not_found}.
get_memo(Index, Name) -> get_memo(Index, Name) ->
case ets:lookup(memo_table_name(), Index) of case ets:lookup(memo_table_name(), Index) of
[] -> {error, not_found}; [] -> {error, not_found};
@ -77,13 +101,19 @@ get_memo(Index, Name) ->
end end
end. end.
-spec memo_table_name() -> ets:tid().
memo_table_name() -> memo_table_name() ->
get({parse_memo_table, ?MODULE}). get({parse_memo_table, ?MODULE}).
-ifdef(p_eof).
-spec p_eof() -> parse_fun().
p_eof() -> p_eof() ->
fun(<<>>, Index) -> {eof, [], Index}; fun(<<>>, Index) -> {eof, [], Index};
(_, Index) -> {fail, {expected, eof, Index}} end. (_, Index) -> {fail, {expected, eof, Index}} end.
-endif.
-ifdef(p_optional).
-spec p_optional(parse_fun()) -> parse_fun().
p_optional(P) -> p_optional(P) ->
fun(Input, Index) -> fun(Input, Index) ->
case P(Input, Index) of case P(Input, Index) of
@ -91,7 +121,10 @@ p_optional(P) ->
{_, _, _} = Success -> Success {_, _, _} = Success -> Success
end end
end. end.
-endif.
-ifdef(p_not).
-spec p_not(parse_fun()) -> parse_fun().
p_not(P) -> p_not(P) ->
fun(Input, Index)-> fun(Input, Index)->
case P(Input,Index) of case P(Input,Index) of
@ -100,7 +133,10 @@ p_not(P) ->
{Result, _, _} -> {fail, {expected, {no_match, Result},Index}} {Result, _, _} -> {fail, {expected, {no_match, Result},Index}}
end end
end. end.
-endif.
-ifdef(p_assert).
-spec p_assert(parse_fun()) -> parse_fun().
p_assert(P) -> p_assert(P) ->
fun(Input,Index) -> fun(Input,Index) ->
case P(Input,Index) of case P(Input,Index) of
@ -108,27 +144,32 @@ p_assert(P) ->
_ -> {[], Input, Index} _ -> {[], Input, Index}
end end
end. end.
-endif.
p_and(P) -> -ifdef(p_seq).
p_seq(P). -spec p_seq([parse_fun()]) -> parse_fun().
p_seq(P) -> p_seq(P) ->
fun(Input, Index) -> fun(Input, Index) ->
p_all(P, Input, Index, []) p_all(P, Input, Index, [])
end. end.
-spec p_all([parse_fun()], input(), index(), [term()]) -> parse_result().
p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index}; p_all([], Inp, Index, Accum ) -> {lists:reverse( Accum ), Inp, Index};
p_all([P|Parsers], Inp, Index, Accum) -> p_all([P|Parsers], Inp, Index, Accum) ->
case P(Inp, Index) of case P(Inp, Index) of
{fail, _} = Failure -> Failure; {fail, _} = Failure -> Failure;
{Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum]) {Result, InpRem, NewIndex} -> p_all(Parsers, InpRem, NewIndex, [Result|Accum])
end. end.
-endif.
-ifdef(p_choose).
-spec p_choose([parse_fun()]) -> parse_fun().
p_choose(Parsers) -> p_choose(Parsers) ->
fun(Input, Index) -> fun(Input, Index) ->
p_attempt(Parsers, Input, Index, none) p_attempt(Parsers, Input, Index, none)
end. end.
-spec p_attempt([parse_fun()], input(), index(), none | parse_failure()) -> parse_result().
p_attempt([], _Input, _Index, Failure) -> Failure; p_attempt([], _Input, _Index, Failure) -> Failure;
p_attempt([P|Parsers], Input, Index, FirstFailure)-> p_attempt([P|Parsers], Input, Index, FirstFailure)->
case P(Input, Index) of case P(Input, Index) of
@ -139,12 +180,18 @@ p_attempt([P|Parsers], Input, Index, FirstFailure)->
end; end;
Result -> Result Result -> Result
end. end.
-endif.
-ifdef(p_zero_or_more).
-spec p_zero_or_more(parse_fun()) -> parse_fun().
p_zero_or_more(P) -> p_zero_or_more(P) ->
fun(Input, Index) -> fun(Input, Index) ->
p_scan(P, Input, Index, []) p_scan(P, Input, Index, [])
end. end.
-endif.
-ifdef(p_one_or_more).
-spec p_one_or_more(parse_fun()) -> parse_fun().
p_one_or_more(P) -> p_one_or_more(P) ->
fun(Input, Index)-> fun(Input, Index)->
Result = p_scan(P, Input, Index, []), Result = p_scan(P, Input, Index, []),
@ -156,7 +203,10 @@ p_one_or_more(P) ->
{fail, {expected, {at_least_one, Failure}, Index}} {fail, {expected, {at_least_one, Failure}, Index}}
end end
end. end.
-endif.
-ifdef(p_label).
-spec p_label(atom(), parse_fun()) -> parse_fun().
p_label(Tag, P) -> p_label(Tag, P) ->
fun(Input, Index) -> fun(Input, Index) ->
case P(Input, Index) of case P(Input, Index) of
@ -166,15 +216,20 @@ p_label(Tag, P) ->
{{Tag, Result}, InpRem, NewIndex} {{Tag, Result}, InpRem, NewIndex}
end end
end. end.
-endif.
p_scan(_, [], Index, Accum) -> {lists:reverse( Accum ), [], Index}; -ifdef(p_scan).
-spec p_scan(parse_fun(), input(), index(), [term()]) -> {[term()], input(), index()}.
p_scan(_, <<>>, Index, Accum) -> {lists:reverse(Accum), <<>>, Index};
p_scan(P, Inp, Index, Accum) -> p_scan(P, Inp, Index, Accum) ->
case P(Inp, Index) of case P(Inp, Index) of
{fail,_} -> {lists:reverse(Accum), Inp, Index}; {fail,_} -> {lists:reverse(Accum), Inp, Index};
{Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum]) {Result, InpRem, NewIndex} -> p_scan(P, InpRem, NewIndex, [Result | Accum])
end. end.
-endif.
p_string(S) when is_list(S) -> p_string(list_to_binary(S)); -ifdef(p_string).
-spec p_string(binary()) -> parse_fun().
p_string(S) -> p_string(S) ->
Length = erlang:byte_size(S), Length = erlang:byte_size(S),
fun(Input, Index) -> fun(Input, Index) ->
@ -185,14 +240,20 @@ p_string(S) ->
error:{badmatch,_} -> {fail, {expected, {string, S}, Index}} error:{badmatch,_} -> {fail, {expected, {string, S}, Index}}
end end
end. end.
-endif.
-ifdef(p_anything).
-spec p_anything() -> parse_fun().
p_anything() -> p_anything() ->
fun(<<>>, Index) -> {fail, {expected, any_character, Index}}; fun(<<>>, Index) -> {fail, {expected, any_character, Index}};
(Input, Index) when is_binary(Input) -> (Input, Index) when is_binary(Input) ->
<<C/utf8, Rest/binary>> = Input, <<C/utf8, Rest/binary>> = Input,
{<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)} {<<C/utf8>>, Rest, p_advance_index(<<C/utf8>>, Index)}
end. end.
-endif.
-ifdef(p_charclass).
-spec p_charclass(string() | binary()) -> parse_fun().
p_charclass(Class) -> p_charclass(Class) ->
{ok, RE} = re:compile(Class, [unicode, dotall]), {ok, RE} = re:compile(Class, [unicode, dotall]),
fun(Inp, Index) -> fun(Inp, Index) ->
@ -203,7 +264,10 @@ p_charclass(Class) ->
_ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}} _ -> {fail, {expected, {character_class, binary_to_list(Class)}, Index}}
end end
end. end.
-endif.
-ifdef(p_regexp).
-spec p_regexp(binary()) -> parse_fun().
p_regexp(Regexp) -> p_regexp(Regexp) ->
{ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]), {ok, RE} = re:compile(Regexp, [unicode, dotall, anchored]),
fun(Inp, Index) -> fun(Inp, Index) ->
@ -214,13 +278,21 @@ p_regexp(Regexp) ->
_ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}} _ -> {fail, {expected, {regexp, binary_to_list(Regexp)}, Index}}
end end
end. end.
-endif.
-ifdef(line).
-spec line(index() | term()) -> pos_integer() | undefined.
line({{line,L},_}) -> L; line({{line,L},_}) -> L;
line(_) -> undefined. line(_) -> undefined.
-endif.
-ifdef(column).
-spec column(index() | term()) -> pos_integer() | undefined.
column({_,{column,C}}) -> C; column({_,{column,C}}) -> C;
column(_) -> undefined. column(_) -> undefined.
-endif.
-spec p_advance_index(input() | unicode:charlist() | pos_integer(), index()) -> index().
p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings p_advance_index(MatchedInput, Index) when is_list(MatchedInput) orelse is_binary(MatchedInput)-> % strings
lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput)); lists:foldl(fun p_advance_index/2, Index, unicode:characters_to_list(MatchedInput));
p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters p_advance_index(MatchedInput, Index) when is_integer(MatchedInput) -> % single characters