Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Export consult_file/2 and reconsult_file/2 from erlog.erl.

  • Loading branch information...
commit f7a801c72d7269d39ba766a63d6a5c5d47378809 1 parent bd15d21
@rvirding authored
View
BIN  ebin/erlog.beam
Binary file not shown
View
BIN  ebin/erlog_scan.beam
Binary file not shown
View
76 examples/homer.pl
@@ -0,0 +1,76 @@
+%% Homer Simpson, after a stop at Moe’s, went to the Springfield Mall to buy
+%% Marge, Lisa, Bart and Maggie a gift in anticipation that they will be upset
+%% with him when he gets home. He bought 4 gifts: a green dress for Marge, a
+%% saxophone book for Lisa, a slingshot for Bart and a pacifier for Maggie. He
+%% recalls buying the gifts at: The Leftorium, Sprawl-Mart, Try-N-Save, and King
+%% Toots. Somewhere along the way, Homer lost his car keys and had to walk home
+%% carrying the gifts. Wanting to retrace his steps and find his lost car keys,
+%% the family asks Homer where he bought the gifts and the order in which he
+%% bought the gifts. Being partly inebriated however, Homer couldn’t remember
+%% which stores he bought the gifts at and in which order he visited the
+%% stores.
+%%
+%% After some interrogation, Homer does remember:
+%%
+%% · He bought the saxophone book at King Toot’s
+%% · The store he visited just after buying the slingshot was not Sprawl-Mart
+%% · The Leftorium was his second stop
+%% · Two stops after leaving Try-N-Save, he bought the pacifier
+%%
+%% Can you help drunken Homer and the Simpson family figure out the order that
+%% Homer bought the gifts and where he bought them?
+
+%% All stores and presents. (Not really used)
+
+store(leftorium).
+store(sprawl_mart).
+store(try_n_save).
+store(king_toots).
+
+present(green_dress).
+present(saxophone_book).
+present(slingshot).
+present(pacifier).
+
+solve(Solution) :-
+ %% Generate all possible combinations.
+ perm([leftorium,sprawl_mart,try_n_save,king_toots], [S1,S2,S3,S4]),
+ perm([green_dress,saxophone_book,slingshot,pacifier], [P1,P2,P3,P4]),
+ %% This is the solution.
+ S = [bought(P1, S1),bought(P2, S2),bought(P3, S3),bought(P4, S4)],
+ %% Now add facts.
+ %% He bought the saxophone book at King Toot’s.
+ member(bought(saxophone_book, king_toots), S),
+ %% The store he visited just after buying the slingshot was
+ %% not Sprawl-Mart.
+ index(bought(slingshot, _), S, I21),
+ index(bought(_, Sa), S, I22),
+ I22 is I21 + 1,
+ Sa \= sprawl_mart,
+ %% The Leftorium was his second stop.
+ index(bought(_, leftorium), S, 2),
+ %% Two stops after leaving Try-N-Save, he bought the pacifier.
+ index(bought(_, try_n_save), S, I41),
+ index(bought(pacifier, _), S, I42),
+ I42 is I41 + 2,
+ %% We have our solution, now export it.
+ Solution = S.
+
+%% Utilities.
+
+%% index(Term, List, -Index).
+%% Find the index of Term in List, backtracking finds all possible ones.
+
+index(X, L, I) :- index(X, L, 1, I).
+
+index(X, [X|_], I, I).
+index(X, [_|L], I, R) :- I1 is I+1, index(X, L, I1, R).
+
+%% perm(+List, ?Perm).
+%% Generate permutations of List, backtracking generates all.
+
+perm([], []).
+perm([X|Xs], Ys1) :- perm(Xs, Ys), insert(Ys, X, Ys1).
+
+insert(X, Y, [Y|X]).
+insert([A|B], C, [A|D]) :- insert(B, C, D).
View
1  src/erlog.erl
@@ -47,6 +47,7 @@
consult/2,reconsult/2,get_db/1,set_db/2,halt/1]).
%% User utilities.
-export([is_legal_term/1,vars_in/1]).
+-export([consult_file/2,reconsult_file/2]).
-import(lists, [foldl/3,foreach/2]).
View
179 src/erlog_scan.erl
@@ -116,19 +116,22 @@ string(String, Line) -> string(String, Line, String, []).
%% string(InChars, Line, TokenChars, Tokens) ->
%% {ok,Tokens,Line} | {error,ErrorInfo,Line}.
+%% Note the line number going into yystate, L0, is line of token
+%% start while line number returned is line of token end. We want line
+%% of token start.
string([], L, [], Ts) -> %No partial tokens!
{ok,yyrev(Ts),L};
string(Ics0, L0, Tcs, Ts) ->
case yystate(yystate(), Ics0, L0, 0, reject, 0) of
{A,Alen,Ics1,L1} -> %Accepting end state
- string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts);
- {A,Alen,Ics1,L1,_S1} -> %After an accepting state
- string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L1), Ts);
- {reject,_Alen,Clen,_Ics1,L1,_S1} -> %After a non-accepting state
- {error,{L1,?MODULE,{illegal,yypre(Tcs, Clen+1)}},L1};
- {A,Alen,_Clen,_Ics1,L1,_S1} ->
- string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L1), Ts)
+ string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
+ {A,Alen,Ics1,L1,_S1} -> %Accepting transistion state
+ string_cont(Ics1, L1, yyaction(A, Alen, Tcs, L0), Ts);
+ {reject,_Alen,Tlen,_Ics1,L1,_S1} -> %After a non-accepting state
+ {error,{L0,?MODULE,{illegal,yypre(Tcs, Tlen+1)}},L1};
+ {A,Alen,_Tlen,_Ics1,L1,_S1} ->
+ string_cont(yysuf(Tcs, Alen), L1, yyaction(A, Alen, Tcs, L0), Ts)
end.
%% string_cont(RestChars, Line, Token, Tokens)
@@ -143,38 +146,51 @@ string_cont(Rest, Line, skip_token, Ts) ->
string_cont(_Rest, Line, {error,S}, _Ts) ->
{error,{Line,?MODULE,{user,S}},Line}.
+%% token(Continuation, Chars) ->
%% token(Continuation, Chars, Line) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
%% Must be careful when re-entering to append the latest characters to the
-%% after characters in an accept.
+%% after characters in an accept. The continuation is:
+%% {token,State,CurrLine,TokenChars,TokenLen,TokenLine,AccAction,AccLen}
token(Cont, Chars) -> token(Cont, Chars, 1).
token([], Chars, Line) ->
- token(Chars, Line, yystate(), Chars, 0, reject, 0);
-token({token,Line,State,Tcs,Clen,Action,Alen}, Chars, _) ->
- token(Chars, Line, State, Tcs ++ Chars, Clen, Action, Alen).
+ token(yystate(), Chars, Line, Chars, 0, Line, reject, 0);
+token({token,State,Line,Tcs,Tlen,Tline,Action,Alen}, Chars, _) ->
+ token(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Action, Alen).
-%% token(InChars, Line, State, TokenChars, CurrTokLen,
+%% token(State, InChars, Line, TokenChars, TokenLen, TokenLine,
%% AcceptAction, AcceptLen) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
-
-token(Ics0, L0, S0, Tcs, Clen0, A0, Alen0) ->
- case yystate(S0, Ics0, L0, Clen0, A0, Alen0) of
- {A1,Alen1,Ics1,L1} -> %Accepting end state
- token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1));
- {A1,Alen1,[],L1,S1} -> %After an accepting state
- {more,{token,L1,S1,Tcs,Alen1,A1,Alen1}};
- {A1,Alen1,Ics1,L1,_S1} ->
- token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1));
- {A1,Alen1,Clen1,[],L1,S1} -> %After a non-accepting state
- {more,{token,L1,S1,Tcs,Clen1,A1,Alen1}};
- {reject,_Alen1,_Clen1,eof,L1,_S1} ->
- {done,{eof,L1},[]};
- {reject,_Alen1,Clen1,Ics1,L1,_S1} ->
- {done,{error,{L1,?MODULE,{illegal,yypre(Tcs, Clen1+1)}},L1},Ics1};
- {A1,Alen1,_Clen1,_Ics1,L1,_S1} ->
- token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1))
+%% The argument order is chosen to be more efficient.
+
+token(S0, Ics0, L0, Tcs, Tlen0, Tline, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
+ %% Accepting end state, we have a token.
+ {A1,Alen1,Ics1,L1} ->
+ token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline));
+ %% Accepting transition state, can take more chars.
+ {A1,Alen1,[],L1,S1} -> %Need more chars to check
+ {more,{token,S1,Tcs,L1,Alen1,Tline,A1,Alen1}};
+ {A1,Alen1,Ics1,L1,_S1} -> %Take what we got
+ token_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline));
+ %% After a non-accepting state, maybe reach accept state later.
+ {A1,Alen1,Tlen1,[],L1,S1} -> %Need more chars to check
+ {more,{token,S1,Tcs,L1,Tlen1,Tline,A1,Alen1}};
+ {reject,_Alen1,Tlen1,eof,L1,_S1} -> %No token match
+ %% Check for partial token which is error.
+ Ret = if Tlen1 > 0 -> {error,{Tline,?MODULE,
+ %% Skip eof tail in Tcs.
+ {illegal,yypre(Tcs, Tlen1)}},L1};
+ true -> {eof,L1}
+ end,
+ {done,Ret,eof};
+ {reject,_Alen1,Tlen1,Ics1,L1,_S1} -> %No token match
+ Error = {Tline,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},
+ {done,{error,Error,L1},Ics1};
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} -> %Use last accept match
+ token_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, Tline))
end.
%% tokens_cont(RestChars, Line, Token)
@@ -186,47 +202,59 @@ token_cont(Rest, Line, {token,T}) ->
token_cont(Rest, Line, {end_token,T}) ->
{done,{ok,T,Line},Rest};
token_cont(Rest, Line, skip_token) ->
- token(Rest, Line, yystate(), Rest, 0, reject, 0);
+ token(yystate(), Rest, Line, Rest, 0, Line, reject, 0);
token_cont(Rest, Line, {error,S}) ->
{done,{error,{Line,?MODULE,{user,S}},Line},Rest}.
%% tokens(Continuation, Chars, Line) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
%% Must be careful when re-entering to append the latest characters to the
-%% after characters in an accept.
+%% after characters in an accept. The continuation is:
+%% {tokens,State,CurrLine,TokenChars,TokenLen,TokenLine,Tokens,AccAction,AccLen}
+%% {skip_tokens,State,CurrLine,TokenChars,TokenLen,TokenLine,Error,AccAction,AccLen}
tokens(Cont, Chars) -> tokens(Cont, Chars, 1).
tokens([], Chars, Line) ->
- tokens(Chars, Line, yystate(), Chars, 0, [], reject, 0);
-tokens({tokens,Line,State,Tcs,Clen,Ts,Action,Alen}, Chars, _) ->
- tokens(Chars, Line, State, Tcs ++ Chars, Clen, Ts, Action, Alen);
-tokens({skip_tokens,Line,State,Tcs,Clen,Error,Action,Alen}, Chars, _) ->
- skip_tokens(Chars, Line, State, Tcs ++ Chars, Clen, Error, Action, Alen).
+ tokens(yystate(), Chars, Line, Chars, 0, Line, [], reject, 0);
+tokens({tokens,State,Line,Tcs,Tlen,Tline,Ts,Action,Alen}, Chars, _) ->
+ tokens(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Ts, Action, Alen);
+tokens({skip_tokens,State,Line,Tcs,Tlen,Tline,Error,Action,Alen}, Chars, _) ->
+ skip_tokens(State, Chars, Line, Tcs ++ Chars, Tlen, Tline, Error, Action, Alen).
-%% tokens(InChars, Line, State, TokenChars, CurrTokLen, Tokens,
+%% tokens(State, InChars, Line, TokenChars, TokenLen, TokenLine, Tokens,
%% AcceptAction, AcceptLen) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
-tokens(Ics0, L0, S0, Tcs, Clen0, Ts, A0, Alen0) ->
- case yystate(S0, Ics0, L0, Clen0, A0, Alen0) of
- {A1,Alen1,Ics1,L1} -> %Accepting end state
- tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts);
- {A1,Alen1,[],L1,S1} -> %After an accepting state
- {more,{tokens,L1,S1,Tcs,Alen1,Ts,A1,Alen1}};
- {A1,Alen1,Ics1,L1,_S1} ->
- tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Ts);
- {A1,Alen1,Clen1,[],L1,S1} -> %After a non-accepting state
- {more,{tokens,L1,S1,Tcs,Clen1,Ts,A1,Alen1}};
- {reject,_Alen1,_Clen1,eof,L1,_S1} ->
- {done,if Ts == [] -> {eof,L1};
- true -> {ok,yyrev(Ts),L1} end,[]};
- {reject,_Alen1,Clen1,_Ics1,L1,_S1} ->
+tokens(S0, Ics0, L0, Tcs, Tlen0, Tline, Ts, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
+ %% Accepting end state, we have a token.
+ {A1,Alen1,Ics1,L1} ->
+ tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Ts);
+ %% Accepting transition state, can take more chars.
+ {A1,Alen1,[],L1,S1} -> %Need more chars to check
+ {more,{tokens,S1,L1,Tcs,Alen1,Tline,Ts,A1,Alen1}};
+ {A1,Alen1,Ics1,L1,_S1} -> %Take what we got
+ tokens_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Ts);
+ %% After a non-accepting state, maybe reach accept state later.
+ {A1,Alen1,Tlen1,[],L1,S1} -> %Need more chars to check
+ {more,{tokens,S1,L1,Tcs,Tlen1,Tline,Ts,A1,Alen1}};
+ {reject,_Alen1,Tlen1,eof,L1,_S1} -> %No token match
+ %% Check for partial token which is error, no need to skip here.
+ Ret = if Tlen1 > 0 -> {error,{Tline,?MODULE,
+ %% Skip eof tail in Tcs.
+ {illegal,yypre(Tcs, Tlen1)}},L1};
+ Ts == [] -> {eof,L1};
+ true -> {ok,yyrev(Ts),L1}
+ end,
+ {done,Ret,eof};
+ {reject,_Alen1,Tlen1,_Ics1,L1,_S1} ->
%% Skip rest of tokens.
- skip_tokens(yysuf(Tcs, Clen1+1), L1,
- {L1,?MODULE,{illegal,yypre(Tcs, Clen1+1)}});
- {A1,Alen1,_Clen1,_Ics1,L1,_S1} ->
- tokens_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Ts)
+ Error = {L1,?MODULE,{illegal,yypre(Tcs, Tlen1+1)}},
+ skip_tokens(yysuf(Tcs, Tlen1+1), L1, Error);
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} ->
+ Token = yyaction(A1, Alen1, Tcs, Tline),
+ tokens_cont(yysuf(Tcs, Alen1), L1, Token, Ts)
end.
%% tokens_cont(RestChars, Line, Token, Tokens)
@@ -235,11 +263,11 @@ tokens(Ics0, L0, S0, Tcs, Clen0, Ts, A0, Alen0) ->
%% just continue.
tokens_cont(Rest, Line, {token,T}, Ts) ->
- tokens(Rest, Line, yystate(), Rest, 0, [T|Ts], reject, 0);
+ tokens(yystate(), Rest, Line, Rest, 0, Line, [T|Ts], reject, 0);
tokens_cont(Rest, Line, {end_token,T}, Ts) ->
{done,{ok,yyrev(Ts, [T]),Line},Rest};
tokens_cont(Rest, Line, skip_token, Ts) ->
- tokens(Rest, Line, yystate(), Rest, 0, Ts, reject, 0);
+ tokens(yystate(), Rest, Line, Rest, 0, Line, Ts, reject, 0);
tokens_cont(Rest, Line, {error,S}, _Ts) ->
skip_tokens(Rest, Line, {Line,?MODULE,{user,S}}).
@@ -247,28 +275,29 @@ tokens_cont(Rest, Line, {error,S}, _Ts) ->
%% Skip tokens until an end token, junk everything and return the error.
skip_tokens(Ics, Line, Error) ->
- skip_tokens(Ics, Line, yystate(), Ics, 0, Error, reject, 0).
+ skip_tokens(yystate(), Ics, Line, Ics, 0, Line, Error, reject, 0).
-%% skip_tokens(InChars, Line, State, TokenChars, CurrTokLen, Tokens,
+%% skip_tokens(State, InChars, Line, TokenChars, TokenLen, TokenLine, Tokens,
%% AcceptAction, AcceptLen) ->
%% {more,Continuation} | {done,ReturnVal,RestChars}.
-skip_tokens(Ics0, L0, S0, Tcs, Clen0, Error, A0, Alen0) ->
- case yystate(S0, Ics0, L0, Clen0, A0, Alen0) of
+skip_tokens(S0, Ics0, L0, Tcs, Tlen0, Tline, Error, A0, Alen0) ->
+ case yystate(S0, Ics0, L0, Tlen0, A0, Alen0) of
{A1,Alen1,Ics1,L1} -> %Accepting end state
- skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error);
+ skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Error);
{A1,Alen1,[],L1,S1} -> %After an accepting state
- {more,{skip_tokens,L1,S1,Tcs,Alen1,Error,A1,Alen1}};
+ {more,{skip_tokens,S1,L1,Tcs,Alen1,Tline,Error,A1,Alen1}};
{A1,Alen1,Ics1,L1,_S1} ->
- skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, L1), Error);
- {A1,Alen1,Clen1,[],L1,S1} -> %After a non-accepting state
- {more,{skip_tokens,L1,S1,Tcs,Clen1,Error,A1,Alen1}};
- {reject,_Alen1,_Clen1,eof,L1,_S1} ->
- {done,{error,Error,L1},[]};
- {reject,_Alen1,Clen1,_Ics1,L1,_S1} ->
- skip_tokens(yysuf(Tcs, Clen1+1), L1, Error);
- {A1,Alen1,_Clen1,_Ics1,L1,_S1} ->
- skip_cont(yysuf(Tcs, Alen1), L1, yyaction(A1, Alen1, Tcs, L1), Error)
+ skip_cont(Ics1, L1, yyaction(A1, Alen1, Tcs, Tline), Error);
+ {A1,Alen1,Tlen1,[],L1,S1} -> %After a non-accepting state
+ {more,{skip_tokens,S1,L1,Tcs,Tlen1,Tline,Error,A1,Alen1}};
+ {reject,_Alen1,_Tlen1,eof,L1,_S1} ->
+ {done,{error,Error,L1},eof};
+ {reject,_Alen1,Tlen1,_Ics1,L1,_S1} ->
+ skip_tokens(yysuf(Tcs, Tlen1+1), L1, Error);
+ {A1,Alen1,_Tlen1,_Ics1,L1,_S1} ->
+ Token = yyaction(A1, Alen1, Tcs, Tline),
+ skip_cont(yysuf(Tcs, Alen1), L1, Token, Error)
end.
%% skip_cont(RestChars, Line, Token, Error)
@@ -276,13 +305,13 @@ skip_tokens(Ics0, L0, S0, Tcs, Clen0, Error, A0, Alen0) ->
%% with the original rror.
skip_cont(Rest, Line, {token,_T}, Error) ->
- skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0);
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0);
skip_cont(Rest, Line, {end_token,_T}, Error) ->
{done,{error,Error,Line},Rest};
skip_cont(Rest, Line, {error,_S}, Error) ->
- skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0);
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0);
skip_cont(Rest, Line, skip_token, Error) ->
- skip_tokens(Rest, Line, yystate(), Rest, 0, Error, reject, 0).
+ skip_tokens(yystate(), Rest, Line, Rest, 0, Line, Error, reject, 0).
yyrev(List) -> lists:reverse(List).
yyrev(List, Tail) -> lists:reverse(List, Tail).
Please sign in to comment.
Something went wrong with that request. Please try again.