%%% BEGIN pibfi_parser.erl %%% %%% %%% pibfi - Platonic Ideal Brainf*ck Interpreter %%% Copyright (c)2003 Cat's Eye Technologies. All rights reserved. %%% %%% Redistribution and use in source and binary forms, with or without %%% modification, are permitted provided that the following conditions %%% are met: %%% %%% Redistributions of source code must retain the above copyright %%% notice, this list of conditions and the following disclaimer. %%% %%% Redistributions in binary form must reproduce the above copyright %%% notice, this list of conditions and the following disclaimer in %%% the documentation and/or other materials provided with the %%% distribution. %%% %%% Neither the name of Cat's Eye Technologies nor the names of its %%% contributors may be used to endorse or promote products derived %%% from this software without specific prior written permission. %%% %%% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND %%% CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, %%% INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF %%% MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE %%% DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE %%% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, %%% OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, %%% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, %%% OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON %%% ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, %%% OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY %%% OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE %%% POSSIBILITY OF SUCH DAMAGE. %% @doc Brainf*ck parser for pibfi. %% %% @end -module(pibfi_parser). -vsn('2003.0426'). -copyright('Copyright (c)2003 Cat`s Eye Technologies. All rights reserved.'). -export([parse/2]). %% @spec parse(string() | binary(), Options) -> {tuple(), string()} %% @doc Transforms a string into a nested tuple data structure %% suitable for interpretation. parse(Binary, Options) when is_binary(Binary) -> parse(binary_to_list(Binary), Options); parse(Source, Options) -> {DocBody, Source0} = case pibfi_options:get_option(Options, heredoc, undefined) of undefined -> {"", Source}; [Marker] -> extract_heredoc(Source, Marker, false, [], []) end, Program = parse0(Source0), Exclude = pibfi_options:get_option(Options, dontstrip, ""), Program0 = pibfi_stripper:strip(Program, Exclude), Program1 = case pibfi_options:get_option(Options, optimize, 1) of 0 -> Program0; 1 -> pibfi_optimizer:optimize(Program0) end, % ce_log:write("~p", [Program1]), {Program1, DocBody}. parse0(String) -> TupleList = annotate(String), parse0({}, TupleList). parse0(Tuple, []) -> Tuple; parse0(Tuple, [{$], R, C} | Tail]) -> {Tuple, Tail}; parse0(Tuple, [{$[, R, C} | Tail]) -> {NewTuple, NewTail} = parse0({}, Tail), parse0(erlang:append_element(Tuple, {while, R, C, NewTuple}), NewTail); parse0(Tuple, [{Head, R, C} | Tail]) -> parse0(erlang:append_element(Tuple, {instruction, R, C, Head}), Tail). annotate(String) -> annotate(String, 1, 1, []). annotate("", R, C, Acc) -> lists:reverse(Acc); annotate("\n" ++ Tail, R, C, Acc) -> annotate(Tail, R+1, 1, Acc); annotate([Head | Tail], R, C, Acc) -> annotate(Tail, R, C+1, [{Head, R, C} | Acc]). extract_heredoc("", Marker, Found, AccD, AccS) -> {lists:reverse(AccD), lists:reverse(AccS)}; extract_heredoc([Marker | Tail], Marker, Found, AccD, AccS) -> extract_heredoc(Tail, Marker, true, AccD, AccS); extract_heredoc([Head | Tail], Marker, true, AccD, AccS) -> extract_heredoc(Tail, Marker, true, [Head | AccD], AccS); extract_heredoc([Head | Tail], Marker, false, AccD, AccS) -> extract_heredoc(Tail, Marker, false, AccD, [Head | AccS]). %%% END of pibfi_parser.erl %%%