Lexical Analyzer Prolog - prolog

I must make a lexical analyzer in Prolog and C++. My for lexical analyzer in C++ is working, but i have some problems with my prolog code. I can't make it to recognize the keywords
This is my prolog code for it without including the keywords which works\
predicates
string_processing
det_lexical_atom_type(char)
is_identif(char)
is_op(char)
is_delim(char)
is_const(char)
p1(string)
clauses
string_processing:-write("Write the expression"),nl,readln(S),p1(S).
p1(S):-frontchar(S,C,R),det_lexical_atom_type(C),p1(R).
p1("#"):-!.
det_lexical_atom_type(C):-is_identif(C),write("\n Is identif",C).
det_lexical_atom_type(C):-is_op(C),write("\n is op",C).
det_lexical_atom_type(C):-is_delim(C),write("\n is delim",C).
det_lexical_atom_type(C):-is_const(C),write("\n is const",C).
det_lexical_atom_type(C):-write("\n Unknown lexical atom").
is_identif(C):-C='A'.
is_op(C):-C='+';C='*'.
is_delim(C):-C='(';C=')'.
is_const(C):-C='0';C='1'.
And this is my prolog code modified to recognize keywords, but it doesn't work .The program stops reading the expression I give right after the first letter and it doesn't continue to recognize the rest of expression. For example is i type T=3+a, it only reads the T and then it stops
predicates
string_processing
is_identif(char)
is_op(char)
is_delim(char)
is_const(char)
is_keyword(string)
p2(string)
determine_lexical_atom_type(char)
determine_keyword(string)
clauses
is_identif(C):-C='A';C='B';C='C';C='D'.
is_op(C):-C='+';C='-';C='/';C='*';C='='.
is_delim(C):-C=';';C=',';C='(';C=')'.
is_const(C):-C='0';C='1';C='2';C='3';C='4';C='5';C='6';C='7';C='8';C='9'.
is_keyword(T):-T="if";T="while";T="do";T="switch";T="for";
T="break";T="until";T="then".
determine_keyword(T):-is_keyword(T),write("\nIs keyword: ",T).
determine_lexical_atom_type(C):-is_identif(C),write("\nIs identif:",C).
determine_lexical_atom_type(C):-is_op(C),write("\nIs operator: ",C).
determine_lexical_atom_type(C):-is_delim(C),write("\nIs delimiter: ",C).
determine_lexical_atom_type(C):-is_const(C),write("\n Is constant ",C).
determine_lexical_atom_type(C):-write("\n Unknown lexical atom").
p2(S):- fronttoken(S,T,R),write("\nT=",T),determine_keyword(T),frontchar(R,C,R1),determine_lexical_atom_type(C),p2(R1).
p2("#"):-!.
string_processing:-write("Write expression"),nl,readln(S),p2(S),nl.

The problem is quite simple:
Just move determine_keyword/1 before fronttoken/3, code fragment is below. Keyword recognition should work after doing that.
p2(S):-
determine_keyword(T), //output var
fronttoken(S,T,R),
write("\nT=",T),
frontchar(R,C,R1),
determine_lexical_atom_type(C),
fail.
p2(_).
determine_keyword/1 generates list of all the keywords on backtracking

Related

Expanding DCGs in Prolog

I'm writing a code generator that converts definite clause grammars to other grammar notations. To do this, I need to expand a grammar rule:
:- initialization(main).
main :-
-->(example,A),writeln(A).
% this should print ([a],example1), but this is a runtime error
example --> [a],example1.
example1 --> [b].
But -->(example, A) doesn't expand the rule, even though -->/2 appears to be defined here. Is there another way to access the definitions of DCG grammar rules?
This is a guess of what your are expecting and why you are having a problem. It just bugs me because I know you are smart and should be able to connect the dots from the comments. (Comments were deleted when this was posted, but the OP did see them.)
This is very specific to SWI-Prolog.
When Prolog code is loaded it automatically goes through term expansion as noted in expand.pl.
Any clause with --> will get expanded based on the rules of dcg_translate_rule/2. So when you use listing/1 on the code after it is loaded, the clauses with --> have already been expanded. So AFAIK you can not see ([a],example1) which is the code before loading then term expansion, but example([a|A], B) :- example(A, B) which is the code after loading and term expansion.
The only way to get the code as you want would be to turn off the term expansion during loading, but then the code that should have been expanded will not and the code will not run.
You could also try and find the source for the loaded code but I also think that is not what you want to do.
Based on this I'm writing a code generator that converts definite clause grammars to other grammar notations. perhaps you need to replace the code for dcg_translate_rule/2 or some how intercept the code on loading and before the term expansion.
HTH
As for the error related to -->(example,A),writeln(A). that is because that is not a valid DCG clause.
As you wrote on the comments, if you want to convert DCGs into CHRs, you need to apply the conversion before the default expansion of DCGs into clauses. For example, assuming your code is saved to a grammars.pl file:
?- assertz(term_expansion((H --> B), '--->'(H,B))).
true.
?- assertz(goal_expansion((H --> B), '--->'(H,B))).
true.
?- [grammars].
[a],example1
true.

ERROR: Stream user_input:8:5 Syntax error: Operator expected in Prolog

I have to write a simple expert system in Prolog for scheduling of classes. In this code part, I want that user add an instructor to system. For this, reading two input value but I am getting this error.
addinstructor() :-
read(id),
read(courseid),
assert(instructor(id, courseid)),
write("added").
Query:
?- addinstructor().
5
cse102.
Then, I am getting operator expected error.
How do i fix this to work my code?
The predicate read/1 reads Prolog terms not raw data. Prolog terms end with a period.
So if instead of entering 5 if you enter 5. you will not get the error.
Instead of using the predicates found in Term reading and writing, e.g. read/1, you should use the predicates in Primitive character I/O for reading characters or Predicates that operate on strings for reading strings, e.g. read_string/3
To answer your next question of how do I implement this, see Prolog - Write out facts and reading a users input and then this.

disjunctive syllogism in prolog

I am using swi-prolog. I want to model following statements in program.
"Either a or b is criminal. b is not criminal."
After modeling these statements. following query should work.
?-c(X).
X=a.
But,
when I wrote above statements in prolog:
c(a);c(b).
not(c(b)).
this code does not compile and shows error:
No permission to modify static procedure `(;)/2'
How to model above two statements in prolog?
afaik Prolog does not work this way. It tries to match your expression with all statements. So if you want to model "a is a criminal and b is not", then you can write
criminal(a).
not(criminal(b)).
but you can't say criminal(b) and in the next line not(criminal(b)), because this would lead to a contradiction.
the second line of my code ('not(criminal(b))') is actually redundant, because if Prolog doesn't find any matches of your term it will result in false, and backtrack for another solution. This means that you can simply omit all facts of not-criminals in this case.
you can then just ask Prolog which atoms it knows as criminals:
criminal(X).
and it will clearly tell you that
X=a.
whereas b is not part of the solution.

Datalog code not working in DrRacket

I am trying to run this prolog code in DrRacket: http://www.anselm.edu/homepage/mmalita/culpro/graf1.html
#lang datalog
arc(a,b).
arc(b,c).
arc(a,c).
arc(a,d).
arc(b,e).
arc(e,f).
arc(b,f).
arc(f,g).
pathall(X,X,[]).
pathall(X,Y,[X,Z|L]):- arc(X,Z),pathall(Z,Y,L). % error on this line;
pathall(a,g)?
However, it is giving following error:
read: expected a `]' to close `['
I suspect '|' symbol is not being read as head-tail separator of the list. Additionally, [] is also giving error (if subsequent line is removed):
#%app: missing procedure expression;
probably originally (), which is an illegal empty application in: (#%app)
How can these be corrected so that the code works and searches for paths between a and g ?
The Datalog module in DrRacket is not an implementation of Prolog, and the syntax that you have used is not allowed (see the manual for the syntax allowed).
In particular terms cannot be data structures like lists ([]). To run a program like that of above you need a Prolog interpreter with data structures.
What you can do is define for instance a predicate path, like in the example that you have linked:
path(X,Y):- arc(X,Y).
path(X,Y):- arc(X,Z),path(Z,Y).
and, for instance, ask if a path exists or not, as in:
path(a,g)?
or print all the paths to a certain node with
path(X,g)?
etc.

Prolog: Rules with nothing but anonymous variables in the head, and no body

Prolog's grammar uses a <head> :- <body> format for rules as such:
tree(G) :- acyclic(G) , connected(G).
, denoting status of G as a tree depends on status as acyclic and connected.
This grammar can be extended in an implicit fashion to facts. Following the same example:
connected(graphA) suggests connected(graphA):-true.
In this sense, one might loosely define Prolog facts as Prolog rules that are always true.
My question: Is in any context a bodiless rule (one that is presumed to be true under all conditions) ever appropriate? Syntactically such a rule would look as follows.
graph(X). (suggesting graph(X):-true.)
Before answering, to rephrase your question:
In Prolog, would you ever write a rule with nothing but anonymous variables in the head, and no body?
The terminology is kind of important here. Facts are simply rules that have only a head and no body (which is why your question is a bit confusing). Anonymous variables are variables that you explicitly tell the compiler to ignore in the context of a predicate clause (a predicate clause is the syntactical scope of a variable). If you did try to give this predicate clause to the Prolog compiler:
foo(Bar).
you will get a "singleton variable" warning. Instead, you can write
foo(_).
and this tells the compiler that this argument is ignored on purpose, and no variable binding should be attempted with it.
Operationally, what happens when Prolog tries to prove a rule?
First, unification of all arguments in the head of the rule, which might lead to new variable bindings;
Then, it tries to prove the body of the rule using all existing variable bindings.
As you can see, the second step makes this a recursively defined algorithm: proving the body of a rule means proving each rule in it.
To come to your question: what is the operational meaning of this:
foo(_).
There is a predicate foo/1, and it is true for any argument, because there are no variable bindings to be done in the head, and always, because no subgoals need to be proven.
I have seen at least one use of such a rule: look at the very bottom of this section of the SWI-Prolog manual. The small code example goes like this:
term_expansion(my_class(_), Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
my_class(_).
You should read the linked documentation to see the motivation for doing this. The purpose of the code itself is to add at compile time a table of facts to the Prolog database. This is done by term expansion, a mechanism for code transformations, usually used through term_expansion/2. You need the definition of my_class/1 so that term_expansion/2 can pick it up, transform it, and replace it with the expanded code. I strongly suggest you take the snipped above, put it in a file, consult it and use listing/1 to see what is the effect. I get:
?- listing(my_class).
my_class(126).
my_class(33).
my_class(64).
my_class(35).
my_class(36).
true.
NB: In this example, you could replace the two occurrences of my_class(_) with anything. You could have just as well written:
term_expansion(foobar, Clauses) :-
findall(my_class(C),
string_code(_, "~!##$", C),
Clauses).
foobar.
The end result is identical, because the operational meaning is identical. However, using my_class(_) is self-documenting, and makes the intention of the code more obvious, at least to an experienced Prolog developer as the author of SWI-Prolog ;).
A fact is just a bodiless rule, as you call it. And yes, there are plenty of use cases for bodiless facts:
representing static data
base cases for recursion
instead of some curly brace language pseudo code
boolean is_three(integer x) {
if (x == 3) { return true; }
else { return false; }
}
we can simply write
is_three(3).
This is often how the base case of a recursive definition is expressed.
To highlight what I was initially looking for, I'll include the following short answer for those who might find themselves asking my initial question in the future.
An example of a bodiless rule is, as #Anniepoo suggested, a base case for a recursive definition. Look to the example of a predicate, member(X,L) for illustration:
member(X,[X|T]). /* recursive base case*/
member(X,[H|T]):- member(X,T).
Here, the first entry of the member rule represents a terminating base case-- the item of interest X matching to the head of the remaining list.
I suggest visiting #Boris's answer (accepted) for a more complete treatment.

Resources