Prolog --> operator-operator expected - prolog

I've received some code as an example for a task at uni. I'm trying to get their example to run so I can then look at a working example to make the similar stuff that I need to. I fixed most of the errors in there (they had "-- >" instead of "-->") but it still gives me an error message.
example.pl:4:0: Syntax error: Operator expected
% example.pl compiled 0.00 sec, 240 bytes
true.
expr --> num.
expr --> num, "+", expr.
expr --> num, "-", expr.
num --> [D] { D >= "0", "9" >= D}.
I've never used anything like the last line before, so I don't know what the error is. I googled stuff about the "-->" operator, because I also haven't used that before so thought there could be a link, but I didn't turn up anything useful about it.
I'm using swi-prolog.

You are missing a comma in the last clause: [D], ...

Related

What is the explanation of this code (Prolog)?

I am trying to learn Prolog. I have a problem and the solution for that in Prolog. Though I am unable to understand the code completely.
The call of the code goes like this-
conc(Before,[c|After],[a,b,c,d]) .
This code will return
Before = [a,b]
After = [d]
I have the solution -
conc([],L,L).
conc([X|L1],L2,[X|L3]) :- conc(L1,L2,L3) .
I am not able to understand the flow of the program completely. Let me start with a dry run. I added some write command in order understand the code flow. The code now looks like this -
conc([],L,L):- write("Line1: "), write(L).
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
Initial call is -
conc(Before,[c|After],[a,b,c,d]) .
At this moment, the call goes to line 2 (because, Before is unknown term which is not empty)which is :
conc([X|L1],L2,[X|L3]) :-
write("Line-2: "), write(L1), write(" "),
write(L2), write(" "), write(L3), conc(L1,L2,L3) .
At this point, X=[a], l1= unknown, L2=[c|After] and L3=[b,c,d]. This prints -
Line2: _G481 [c|_G368] [b,c,d]
This will again call the recursion(code line 2) with the following value:
cons(L1, [c|After], [b,c,d]). (L1 is unknown still now)
And, prints -
Line2: _G494 [c|_G368] [c,d]
Now the next call will be :
cons(L1, [c|After], [c,d]).
But , I can see while printing the customized comments in the code, that, at this point the code control goes to #line 1 which I am not able to understand. Because, now,
L1= unknown(just as all the previous calls).
L(parameter 2)= [c|After]
L(parameter 3) = [c,d].
But, the control goes to the #line 1, and it prints :
Line1: [c,d]
I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d].
My question is:
1. After the second call, L1 is undefined as all the calls as before. And, second and third parameters , both are L. So, why, after second call the control goes to the #line1.?
2. Is my understanding correct in this matter ? "I thought prolog executes the code from left to right. So, as per my understanding, while executing the value of L should be [c,d]."
Thanks in advance...
Please help me out!!
You cannot expect to understand everything that is happening here if you look at it procedurally, because there is too much going on at the same time. This is especially true if you are just beginning to learn the language.
A good approach for learning Prolog is to think declaratively, and ask: What are the conditions that make this hold?
In addition, you are currently writing atoms when you actually mean to write variables. Please correct your post to say for example:
cons(L1, [c|After], [c,d])
Note that After is a variable, and after is an atom.
Now, leaving everything else aside, just consider this single goal in isolation. Try it with:
?- cons(L1, [c|After], [c,d]).
In complete accordance with our expectation, we get the solution:
L1 = [],
After = [d]
Thus, it suffices to understand that this goal can be derived in isolation. Also notice the difference between X = [a] and X = a, which you are currently intermingling.

Stuck on translating a cfg to dcg

I'm trying to teach myself prolog and implementing an interpreter for a simple arithmetic cfg:
<expression> --> number
<expression> --> ( <expression> )
<expression> --> <expression> + <expression>
<expression> --> <expression> - <expression>
<expression> --> <expression> * <expression>
<expression> --> <expression> / <expression>
So far, I've written this in swi-prolog which hits a number of bugs described below;
expression(N) --> number(Cs), { number_codes(N, Cs) }.
expression(N) --> "(", expression(N), ")".
expression(N) --> expression(X), "+", expression(Y), { N is X + Y }.
expression(N) --> expression(X), "-", expression(Y), { N is X - Y }.
number([D|Ds]) --> digit(D), number(Ds).
number([D]) --> digit(D).
digit(D) --> [D], { code_type(D, digit) }.
Testing with
phrase(expression(X), "12+4").
gives X = 16 which is good. Also
phrase(expression(X), "(12+4)").
works and phrase(expression(X), "12+4+5"). is ok.
But trying
phrase(expression(X), "12-4").
causes "ERROR: Out of local stack" unless I comment out the "+" rule. And while I can add more than two numbers, brackets don't work recursively (ie "(1+2)+3" hangs).
I'm sure the solution is simple, but I haven't been able to figure it out from the online tutorials I've found.
Everything you did is correct in principle. And you're right: the answer is simple.
But.
Left recursion is fatal in definite-clause grammars; the symptom is precisely the behavior you are seeing.
If you set a spy point on expression and use the trace facility, you can watch your stack grow and grow and grow while the parser makes no progress at all.
gtrace.
spy(expression).
phrase(expression(N),"12-4").
If you think carefully about the Prolog execution model, you can see what is happening.
We try to parse "12-4" as an expression.
Our call stack is contains this call to expression from step 1, which I will write expression(1).
We succeed in parsing "12" as an expression, by the first clause for "expression", and we record a choice point in case we need to backtrack later. In fact we need to backtrack immediately, because the parent request involving phrase says we want to parse the entire string, and we haven't: we still have "-4" to go. So we fail and go back to the choice point. We have shown that the first clause of "expression" doesn't succeed so we retry against the second clause.
The call stack: expression(1).
We try to parse "12-4" using the second clause for "expression", but fail immediately (the initial character is not "("). So we fail and retry against the third clause.
Call stack: expression(1).
The third clause asks us to parse an expression off the beginning of the input and then find a "+" and another expression. So we must try now to parse the beginning of the input as an expression.
Call stack: expression(4) expression(1).
We try to parse the beginning of "12-4" as an expression, and succeed with "12", just as in step 1. We record a choice point in case we need to backtrack later.
Call stack: expression(4) expression(1).
We now resume the attempt begun in step 4 to parse "12-4" as an expression against clause 3 of "expression". We've done the first bit; now we must try to parse "-4" as the remainder of the right-hand side of clause 3 of "expression", namely "+", expression(Y). But "-" is not "+", so we fail immediately, and go back to the most recently recorded choice point, the one recorded in step 5. The next thing is to try to find a different way of parsing the beginning of the input as an expression. We resume this search with the second clause of "expression".
Call stack: expression(4) expression(1).
Once again the second clause fails. So we continue with the third clause of "expression". This asks us to look for an expression at the beginning of the input (as part of figuring out whether our current two calls to "expression" can succeed or will fail). So we call "expression" again.
Call stack: expression(7) expression(4) expression(1).
You can see that each time we add a call to expression to the stack, we are going to succeed, look for a plus, fail, and try again, eventually reaching the third clause, at which point we will push another call on the stack and try again.
Short answer: left recursion is fatal in DCGs.
It's also fatal in recursive-descent parsers, and the solution is much the same: don't recur to the left.
A non-left-recursive version of your grammar would be:
expression(N) --> term(N).
expression(N) --> term(X), "+", expression(Y), { N is X + Y }.
expression(N) --> term(X), "-", expression(Y), { N is X - Y }.
term(N) --> number(Cs), { number_codes(N, Cs) }.
term(N) --> "(", expression(N), ")".
However, this makes "-" right associative, and requires the initial term to be reparsed repeatedly in many cases, so a common approach in code intended for production is to do something less like the BNF you started with and more like the following EBNF version:
expression = term {("+"|"-") term}
term = number | "(" expression ")".
The way I learned to write it (long enough ago that I no longer remember whom to credit for it) is something like this (I found it ugly at first, but it grows on you):
expression(N) --> term(X), add_op_sequence(X,N).
add_op_sequence(LHS0, Result) -->
"+", term(Y),
{LHS1 is LHS0 + Y},
add_op_sequence(LHS1,Result).
add_op_sequence(LHS0, Result) -->
"-", term(Y),
{LHS1 is LHS0 - Y},
add_op_sequence(LHS1,Result).
add_op_sequence(N,N) --> [].
term(N) --> number(Cs), { number_codes(N, Cs) }.
term(N) --> "(", expression(N), ")".
The value accumulated so far is passed down in the left-hand argument of add_op_sequence and eventually (when the sequence ends with the empty production) passed back up as a result.
The parsing strategy known as 'left-corner parsing' is a way of dealing with this problem; books on the use of Prolog in natural-language processing will almost invariably discuss it.

String comparison program in swi-prolog always fails

I'm trying to write a program using swi-prolog that randomly asks people for their first or last name and prints "correct" or "incorrect" based on what they type. The current correct answers are "Hello" and "World" but regardless of what the user types, the output is false and correct/incorrect isn't printed.
start:-(Q=['What is your first name?','What is your last name?'],
random_member(N,[0,1]),
nth0(N,Q,X),
writeln(X)),
readln(S),
check_answer(N,S).
check_answer(N,S):-A=['Hello','World'],
nth0(N,A,X),
writeln(X),
(S=#=X)->writeln('correct'),
not(S=#=X)->writeln('incorrect').
I later edited it to:
start:-(Q=['What is your first name?','What is your last name?'],
random_member(N,[0,1]),
nth0(N,Q,X),
writeln(X)),
read(S),
check_answer(N,S).
check_answer(N,S):-A=['Hello','World'],
nth0(N,A,X),
writeln(X),
writeln(S),
((S=#=X))->writeln('correct') ; writeln('incorrect').
I can spot two problems in your code.
a) readln/1 (undocumented) returns a list of items (then peek the first item or use read/1):
?- readln(X).
|: Hello.
X = ['Hello', '.'].
?- readln(X).
|: Hello
X = ['Hello'].
?- readln(X).
|: Hello .
X = ['Hello', '.'].
b) The pair of if then else operator (->) will always fail, because you omit the else branch on both, and the conditions are exclusives. Try
...
((S=#=X)->writeln('correct') ; writeln('incorrect')).
edit there are 2 problems. I wrongly suggested read/1. That read a Prolog term, and then read a variable if we write a variable, i.e. a UppercaseStartingSymbol. My fault. readln seems ok then, but change the pattern to select the first item.
Another problem, unrelated: you misplaced the closed parenthesis in -> 'statement'.
Here the code:
start:-(Q=['What is your first name?','What is your last name?'],
random_member(N,[0,1]),
nth0(N,Q,X),
writeln(X)),
readln(S),
check_answer(N,S).
check_answer(N,[S|_]):-A=['Hello','World'],
nth0(N,A,X),
writeln(X),
writeln(S),
((S=#=X)->writeln('correct') ; writeln('incorrect')).

translate(list1, list2) in prolog

I was trying a functor translate([3,5,1,3],[three,five,one,three]) which does the operation of printing numbers. I get a strange warning while executing like this,
35 ?- translate([1,2,3],[a,b,c]).
ERROR: write/2: stream `a' does not exist
domains
list1=integer*
list2=symbol*
predicates
translate(list1,list2)
means(integer,symbol)
clauses
translate([],[]).
translate([],_):-
write("\nError in Input").
translate(_,[]):-
write("\nError in Input").
translate([Head1|Tail1],[Head2|Tail2]):-
write(Head2," = "),
means(Head1,Name),
write(Name,"\n"),
translate(Tail1,Tail2).
means(0,zero).
means(1,one).
means(2,two).
means(3,three).
means(4,four).
means(5,five).
means(6,six).
means(7,seven).
means(8,eight).
means(9,nine).
What exactly is the problem? This is the expected value.
translate([1,2,3],[a,b,c])
a = one
b = two
c = three
Yes
Variables need to be uppercase:
translate([1,2,3],[A,B,C]).
When you enter the translate([Head1|Tail1],[Head2|Tail2]) clause, a unifies with Head2, and then you try to satisfy write(Head2, "="), which is write(a, "=").
write/2 takes as first argument a Stream and writes the second argument to that Stream.
Presumably you want to use - if you want output at all - something like
writef('Head2 = %w', [Head2])
(I got the formatting from here.)

Parsing numbers with multiple digits in Prolog

I have the following simple expression parser:
expr(+(T,E))-->term(T),"+",expr(E).
expr(T)-->term(T).
term(*(F,T))-->factor(F),"*",term(T).
term(F)-->factor(F).
factor(N)-->nat(N).
factor(E)-->"(",expr(E),")".
nat(0)-->"0".
nat(1)-->"1".
nat(2)-->"2".
nat(3)-->"3".
nat(4)-->"4".
nat(5)-->"5".
nat(6)-->"6".
nat(7)-->"7".
nat(8)-->"8".
nat(9)-->"9".
However this only supports 1-digit numbers. How can I parse numbers with multiple digits in this case?
Use accumulator variables, and pass those in recursive calls. In the following, A and A1 are the accumulator.
digit(0) --> "0".
digit(1) --> "1".
% ...
digit(9) --> "9".
nat(N) --> digit(D), nat(D,N).
nat(N,N) --> [].
nat(A,N) --> digit(D), { A1 is A*10 + D }, nat(A1,N).
Note that the first nat clause initializes the accumulator by consuming a digit, because you don't want to match the empty string.
nat(0).
nat(N):-nat(N-1).
But you use a syntax that I don't know (see my comment above).
Can you provide a sample input?
I think this might work:
nat(N)-->number(N).
If that fails try:
nat(N)-->number(N),!.
The ! is a cut it stops the unification. You can read about it in books/tutorials.

Resources