This is a follow-on question from an earlier question from Mat's answer
Starting with this
e([number(0)] , t1 , Uc0 , Uc0, Bc0 , Bc0) --> [].
e([number(1)] , t2 , Uc0 , Uc0, Bc0 , Bc0) --> [].
e([number(2)] , t3 , Uc0 , Uc0, Bc0 , Bc0) --> [].
e([op(neg),[Arg]] , u1(E) , [_|Uc0], Uc1, Bc0 , Bc1) -->
[_],
e(Arg , E , Uc0, Uc1, Bc0, Bc1).
e([op(ln),[Arg]] , u2(E) , [_|Uc0], Uc1, Bc0 , Bc1) -->
[_],
e(Arg , E , Uc0, Uc1, Bc0, Bc1).
e([op(add),[Left,Right]], b1(E0,E1) , Uc0 , Uc2, [_|Bc0], Bc2) -->
[_,_],
e(Left, E0, Uc0, Uc1, Bc0, Bc1),
e(Right, E1, Uc1, Uc2, Bc1, Bc2).
e([op(sub),[Left,Right]], b2(E0,E1) , Uc0 , Uc2, [_|Bc0], Bc2) -->
[_,_],
e(Left, E0, Uc0, Uc1, Bc0, Bc1),
e(Right, E1, Uc1, Uc2, Bc1, Bc2).
e(U,B,EL,Es) :-
length(UL, U),
length(BL, B),
phrase(e(EL,Es,UL,[],BL,[]), _).
e(N,EL,Es) :-
length([_|Ls], N),
phrase(e(EL,Es,_,[],_,[]),Ls).
e_count(E, Count) :-
length([_|Ls], E),
findall(., phrase(e(_,_,_,[],_,[]), Ls), Sols),
length(Sols, Count).
then reading
For one variable, use a list with a single element that contains just that variable. If you want to pass around more than one variable, use a list that contains a single term of the form f(...), capturing all variables you want to pass around. This is also well worth its own question.
evolved into this
e( f([number(0)], t1, Uc0, Uc0, Bc0, Bc0) ) --> [].
e( f([number(1)], t2, Uc0, Uc0, Bc0, Bc0) ) --> [].
e( f([number(2)], t3, Uc0, Uc0, Bc0, Bc0) ) --> [].
e( f([op(neg), [Arg]], u1(E), [_|Uc0], Uc1, Bc0, Bc1) ) -->
[_],
e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).
e( f([op(ln) , [Arg]], u2(E), [_|Uc0], Uc1, Bc0, Bc1) ) -->
[_],
e( f(Arg, E, Uc0, Uc1, Bc0, Bc1) ).
e( f([op(add), [Left,Right]], b1(E0,E1) ,Uc0, Uc2, [_|Bc0], Bc2) ) -->
[_,_],
e(f(Left, E0, Uc0, Uc1, Bc0, Bc1) ),
e(f(Right, E1, Uc1, Uc2, Bc1, Bc2) ).
e( f([op(sub), [Left,Right]], b2(E0,E1) ,Uc0, Uc2, [_|Bc0], Bc2) ) -->
[_,_],
e(f(Left, E0, Uc0, Uc1, Bc0, Bc1) ),
e(f(Right, E1, Uc1, Uc2, Bc1, Bc2) ).
e(U,B,EL,Es) :-
length(UL, U),
length(BL, B),
phrase(e(f(EL,Es,UL,[],BL,[])), _).
e_N(N,EL,Es) :-
length([_|Ls], N),
phrase(e(f(EL,Es,_,[],_,[])),Ls).
e_count(E, Count) :-
length([_|Ls], E),
findall(., phrase(e(f(_,_,_,[],_,[])), Ls), Sols),
length(Sols, Count).
which works but it is noted use a list that contains a single term of the form f(...)
, and here f(...)
is not in a list.
Did I go wrong somewhere?
Supplement
References
- Thinking in States by Markus Triska
- Prolog DCG Primer by Markus Triska
- Extra Arguments with Learn Prolog Now!
Variable names convention with implicit state passing
Normally when using implict-state-passing the variables are named
S0
→ S1
→…→ S
However for my uniary-binary tree examples I name them like
S0
→ S1
→…→ Sn
ending with Sn
instead of S
.
e.g.
standard
e(S0,S) :-
here
e(S0,S2) :-
the reason being that this example has a rather rare property of each DCG predicate having increasing length,
e.g.
e([number(0)] , t1 , Uc0 , Uc0, Bc0 , Bc0) -->
e([op(neg),[Arg]] , u1(E) , [_|Uc0], Uc1, Bc0 , Bc1) -->
e([op(add),[Left,Right]], b1(E0,E1) , Uc0 , Uc2, [_|Bc0], Bc2) -->
so ending with xn
gives me one more check on accuracy.
Reference: ISO/IEC DTR 13211–3:2006 Definite clause grammar rules
6.1.3 Variable names convention for terminal-sequences
This TR uses variables named S0, S1, ..., S to represent the terminal-sequences used as arguments when processing grammar rules or when expanding grammar rules into clauses. In this notation, the variables S0, S1, ..., S can be regarded as a sequence of states, with S0 representing the initial state and the variable S representing the final state. Thus, if the variable Si represents the terminal-sequence in a given state, the variable Si+1 will represent the remaining terminal-sequence after parsing Si with a grammar rule.
semicontext notation
had a name until I read mat's answer. Then I found it explained in Markus Triska's DCG document. Since both usedSemicontext notation
together and emphasized that is what I used. We can always create a tag synonym. I have tried to make a few tag synonyms but it appears there are some conditions necessary before one can make a synonym, I believe 5 points for the tag, so I haven't been able to make the ones I want. – Guy Coder