diff options
-rw-r--r-- | .gitignore | 4 | ||||
-rw-r--r-- | rebar.config | 10 | ||||
-rw-r--r-- | src/rcl_goal.peg | 54 | ||||
-rw-r--r-- | src/rcl_goal_utils.erl | 79 | ||||
-rw-r--r-- | test/rclt_goal.erl | 63 |
5 files changed, 205 insertions, 5 deletions
@@ -3,4 +3,6 @@ ebin/* *.beam .eunit .relcool_plt -relcool
\ No newline at end of file +relcool +# This is a generated file that should be ignored +src/rcl_goal.erl diff --git a/rebar.config b/rebar.config index cd3797a..e31e544 100644 --- a/rebar.config +++ b/rebar.config @@ -1,13 +1,15 @@ %% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- -{deps, [{erlware_commons, "", +{deps, [{neotoma, "", + {git, "https://github.com/seancribbs/neotoma.git", {tag, "1.5"}}}, + {erlware_commons, "", {git, "https://github.com/ericbmerritt/erlware_commons.git", {tag, "v0.7.0"}}}, - {getopt, "0.5.1", + {getopt, "", {git, "https://github.com/jcomellas/getopt.git", {tag, "v0.5.1"}}}, - {depsolver, "0.0.2", + {depsolver, "", {git, "https://github.com/ericbmerritt/depsolver.git", {tag, "v0.0.2"}}}]}. {escript_incl_apps, [getopt, depsolver]}. -{erl_opts, [debug_info, warnings_as_errors]}. +{erl_opts, [debug_info, warnings_as_errors, inline]}. diff --git a/src/rcl_goal.peg b/src/rcl_goal.peg new file mode 100644 index 0000000..24e78a8 --- /dev/null +++ b/src/rcl_goal.peg @@ -0,0 +1,54 @@ + +constraint <- ws? app_name ws? between_op ws? version ws? "," ws? version ws? !. + / ws? app_name ws? constraint_op ws? version ws? !. + / ws? app_name ws? !. + + ` + case Node of + [_,AppName,_, _] -> + {ok, erlang:iolist_to_binary(AppName)}; + [_,AppName,_,Op,_,Vsn,_, _] -> + {ok, + {erlang:iolist_to_binary(AppName), + rcl_goal_utils:to_vsn(Vsn), + rcl_goal_utils:to_op(Op)}}; + [_,AppName,_,Op,_,Vsn1,_,_,_,Vsn2,_,_] -> + {ok, + {erlang:iolist_to_binary(AppName), + rcl_goal_utils:to_vsn(Vsn1), + rcl_goal_utils:to_vsn(Vsn2), + rcl_goal_utils:to_op(Op)}}; + _ -> + io:format("~p~n", [Node]) + end + ` ; + +ws <- [ \t\n\s\r] ; + +app_name <- [a-zA-Z0-9_]+ ; + +between_op <- + ":" ws? ( "btwn" / "between" ) ws? ":" + ` case Node of + [C,_,Op,_,C] -> erlang:iolist_to_binary([C,Op,C]); + _ -> Node + end + ` ; + +constraint_op <- "=" / "-" / "<=" / "<" / "~>" / ">=" / ">" / word_constraint_op / ":" ; + +word_constraint_op <- + ":" ws? ( "gte" / "lte" / "gt" / "lt" / "pes" ) ws? ":" + ` case Node of + [C,_,Op,_,C] -> erlang:iolist_to_binary([C,Op,C]); + _ -> Node + end + ` ; + + +version <- [0-9a-zA-Z-+.]+ ; + +%% This only exists to get around a bug in erlang where if +%% warnings_as_errors is specified `nowarn` directives are ignored + + `-compile(export_all).`
\ No newline at end of file diff --git a/src/rcl_goal_utils.erl b/src/rcl_goal_utils.erl new file mode 100644 index 0000000..75fcda4 --- /dev/null +++ b/src/rcl_goal_utils.erl @@ -0,0 +1,79 @@ +%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt <[email protected]> +%%% @copyright (C) 2012 Erlware, LLC. +%%% +%%% @doc +%%% Utilities to help with parsing of target specs +-module(rcl_goal_utils). + +-export([to_op/1, + to_vsn/1]). + +%%============================================================================ +%% types +%%============================================================================ + + +%%============================================================================ +%% API +%%============================================================================ +-spec to_op(iolist()) -> depsolver:constraint_op(). +to_op(List) + when erlang:is_list(List) -> + to_op(erlang:iolist_to_binary(List)); +to_op(<<"=">>) -> + '='; +to_op(<<":">>) -> + '='; +to_op(<<"-">>) -> + '='; +to_op(<<"<">>) -> + 'lt'; +to_op(<<":lt:">>) -> + 'lt'; +to_op(<<"<=">>) -> + 'lte'; +to_op(<<":lte:">>) -> + 'lte'; +to_op(<<">">>) -> + 'gt'; +to_op(<<":gt:">>) -> + 'gt'; +to_op(<<">=">>) -> + 'gte'; +to_op(<<":gte:">>) -> + 'gte'; +to_op(<<"~>">>) -> + 'pes'; +to_op(<<":pes:">>) -> + 'pes'; +to_op(<<":btwn:">>) -> + 'between'; +to_op(<<":between:">>) -> + 'between'. + + +to_vsn(Version) when erlang:is_list(Version) -> + to_vsn(erlang:iolist_to_binary(Version)); +to_vsn(Vsn) -> + depsolver:parse_version(Vsn). + +%%%=================================================================== +%%% Test Functions +%%%=================================================================== diff --git a/test/rclt_goal.erl b/test/rclt_goal.erl new file mode 100644 index 0000000..9fd31ae --- /dev/null +++ b/test/rclt_goal.erl @@ -0,0 +1,63 @@ +%%% -*- mode: Erlang; fill-column: 80; comment-column: 75; -*- +%%% Copyright 2012 Erlware, LLC. All Rights Reserved. +%%% +%%% This file is provided to you under the Apache License, +%%% Version 2.0 (the "License"); you may not use this file +%%% except in compliance with the License. You may obtain +%%% a copy of the License at +%%% +%%% http://www.apache.org/licenses/LICENSE-2.0 +%%% +%%% Unless required by applicable law or agreed to in writing, +%%% software distributed under the License is distributed on an +%%% "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +%%% KIND, either express or implied. See the License for the +%%% specific language governing permissions and limitations +%%% under the License. +%%%--------------------------------------------------------------------------- +%%% @author Eric Merritt <[email protected]> +%%% @copyright (C) 2012 Erlware, LLC. +%%% @doc test for target spec parsing +-module(rclt_goal). + +-include_lib("eunit/include/eunit.hrl"). + +parse_test() -> + ?assertMatch({ok, <<"getopt">>}, + rcl_goal:parse("getopt")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, '='}}, + rcl_goal:parse("getopt=0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, '='}}, + rcl_goal:parse("getopt:0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, '='}}, + rcl_goal:parse("getopt-0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, gte}}, + rcl_goal:parse("getopt >= 0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, gte}}, + rcl_goal:parse("getopt:gte:0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, gt}}, + rcl_goal:parse("getopt>0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, gt}}, + rcl_goal:parse("getopt:gt:0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, lte}}, + rcl_goal:parse("getopt<= 0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, lte}}, + rcl_goal:parse("getopt:lte:0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, lt}}, + rcl_goal:parse("getopt<0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, pes}}, + rcl_goal:parse("getopt ~>0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, pes}}, + rcl_goal:parse("getopt: pes:0.5.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, {{0,6,1},{[],[]}}, between}}, + rcl_goal:parse("getopt:btwn:0.5.1,0.6.1")), + ?assertMatch({ok, {<<"getopt">>, {{0,5,1},{[],[]}}, {{0,6,1},{[],[]}}, between}}, + rcl_goal:parse("getopt:between :0.5.1,0.6.1")). + +fail_test() -> + ?assertMatch({fail,_}, + rcl_goal:parse("got:")), + ?assertMatch({fail,_}, + rcl_goal:parse("between:btwn:0.5")), + ?assertMatch({fail,_}, + rcl_goal:parse("between:btwn:0.5,")). |