git @ Cat's Eye Technologies GraNoLa-M / master src / granolam.erl
master

Tree @master (Download .tar.gz)

granolam.erl @masterraw · history · blame

-module(granolam).
-vsn('2002.0314').  % This work is a part of the public domain.

-compile([nowarn_unused_vars]).

-export([parse/1, interpret/1, run/1, test/1, shell/0, main/1]).

-define(g0(X),X++S)->" "++X++" "++sub(S).
-define(g1(X),X|R0])->{Q,R1}=).
-define(g2(X),{S0,X}=pop(C,S)).
-define(g3(X),S0=push(C,S,X)).
-define(g9,++K->S0=push(C,S).
-define(y,S,C,CS).
-define(t,C,CS,M).
-define(t0,L,P,S0).
-define(l(X),list_to_atom(X)).

%% Parser --------------------------------------------------------------

sub(?g0("("));sub(?g0(")"));sub(?g0("^"));sub(?g0("="));
sub([C|S])->[C]++sub(S);sub([])->[].
lta([])->[];lta([H|T])->[?l(H)|lta(T)].
parse(S)->{P,R}=graph(lta(string:tokens(sub(S)," "))),P.
graph(['^',N|R0])->{N,R0};
graph([N,?g1('=')graph(R0),['('|R2]=R1,{Q2,R3}=
graph2(R2,[]),{{N,Q,Q2},R3};
graph([N,?g1('(')graph2(R0,[]),{{N,nil,Q},R1}.
graph2([')'|R0],A)->{A,R0};
graph2(R,A)->{Q,R0}=graph(R),graph2(R0,A++[Q]).

%% Interpreter ---------------------------------------------------------

interpret(P)->interpret(first(P),P,{stack,nil,[]},stack,[],random).
interpret(nil,  P,?y,M)->{?y};
interpret(stop, P,?y,M)->{?y};
interpret(N, P,?y,M)->
  case find(N,P) of
    {N,nil,L} ->
      interpret(pick(L,M),P,?y,M);
    {N,V,L} when is_atom(V)->
      {N0,P0,S0,C0,CS0,M0} = do(N,V,P,?y,M),
      {N1,V1,L1}=find(N0,P0),
      case N0 of
        N->interpret(pick(L1,M0),P0,S0,C0,CS0,M0);
	_->interpret(N0,P0,S0,C0,CS0,M0)
      end;	
    {N,V,L} ->
      {S0,C0,CS0}=interpret(first(V),V,?y,M),
      interpret(pick(L,M),P,S0,C0,CS0,M);
    _ ->
      {?y}
  end.

do(L,V,P,?y,M) ->
  case V of
    uwaming->?g2(Q),io:fwrite("~s ",[format(Q)]),{?t0,?t};
    bejadoz->?g3(input()),{?t0,?t};
    duronilt->?g2(Q),{L,Q,S0,?t};
    whebong->?g3(P),{?t0,?t};
    taug->?g3({embed,S,[]}),{?t0,?t};
    chehy->?g2(Q),{L,P,Q,?t};
    bimodang->?g2(Q),case Q of
        skip->{?t0,?t};
	   _->{Q,P,S0,C,[L|CS],M}end;
    ubewic->?g3(skip),[H|T]=CS,{H,P,S0,C,T,M};
    rehohur->?g2(Q),{?t0,?t};
    soduv->?g2(Q),case Q of
        {_,_,[]}   ->{?t0,C,CS,first};
	{_,_,[_|_]}->{?t0,C,CS,last};
	          _->{?t0,?t}end;
    chuwakagathaz->{L,P,?y,random};
    sajalom->{L,P,?y,first};
    grangnum->{L,P,?y,last};
    _ ->
      case atom_to_list(V) of
        "#"?g9,?l(K)),{?t0,?t};
        "0"?g9,{?l(K),nil,[]}),{?t0,?t};
        "1"?g9,find(?l(K),P)),{?t0,?t};
        "@"++C0->{L,P,S,?l(C0),CS,M};
	_->{L,P,?y,M}
      end
  end.

%% Utilities ------------------------------------------------------------

first({N,S,L})->N;first(A)->A. pick([],_)->stop;pick([H|_],first)->first(H);
pick(L,last)->first(lists:nth(length(L),L));pick(L,random)->first(lists:nth(
random:uniform(length(L)),L)). find(N,[])->false;find(N,[H|T])->case find(N,H)
of false->find(N,T);V->V end;find(N,{N,S,L}=P)->P;find(N,{O,S,L})->find(N,L);
find(N,_)->false. replace(N,[],G)->[];replace(N,[H|T],G)->[replace(N,H,G)|
replace(N,T,G)];replace(N,{N,S,L}=P,G)->G;replace(N,{O,S,L},G)->replace(N,L,G);
replace(N,V,G)->V. push(C,S,G)->{N,D,L}=find(C,S),replace(C,S,{N,D,[G|L]}). pop
(C, S)->case find(C,S) of{N,D,[]}->{S,nil};{N,D,[H|T]}->{replace(C,S,{N,D,T}),
H}end. format([])->"";format(A) when is_atom(A)->"^"++atom_to_list(A);format([H|T])
->format(H)++format(T);format({N,nil,L})->io_lib:format("~w(~s)",[N,format(L)])
;format({N,V,L})->io_lib:format("~w=~s(~s)",[N,format(V),format(L)]);format(_)

                                  ->"?".

%% User Interface ------------------------------------------------------

input()->parse(lib:nonl(io:get_line('GraNoLa/M> '))).
run(S)->interpret(parse(S)).
test(1)->run("a=^#cthulhu(b=^uwaming(^a))");
test(2)->run("a=^whebong(b=^uwaming(^a))");
test(4)->run("a=^0hello(b=^@hello(c=^taug(d=^uwaming(^a))))");
test(5)->run("a=^1hello(b=^uwaming(end() hello(world())))");
test(6)->run("a=^sajalom(b=^#d(c=^bimodang(^a))"
             "d(e=^#sakura(f=^uwaming(g=^ubewic()))))");
test(7)->run("a=^sajalom(b=^bejadoz(c=^soduv(^a d())))");
test(_)->unknown_test.
shell()->{?y}=interpret(input()),io:fwrite("~s@~w~n",[format(S),C]),
shell().

%% Script Interface ------------------------------------------------------

main(["run",N]) ->
  {ok,B} = file:read_file(N),run(binary_to_list(B)),io:fwrite("\n");
main(["parse",N]) ->
  {ok,B} = file:read_file(N),io:fwrite("~w\n",[parse(binary_to_list(B))]).