Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems with Prolog's DCG

The project is about translating semi-natural language to SQL tables. The code:

label(S) --> label_h(C), {atom_codes(A, C), string_to_atom(S, A)}, !.

label_h([C|D]) --> letter(C), letters_or_digits(D), !.

letters_or_digits([C|D]) --> letter_or_digit(C), letters_or_digits(D), !.
letters_or_digits([C]) --> letter_or_digit(C), !.
letters_or_digits([]) --> "", !.

letter(C) --> [C], {"a"=<C, C=<"z"}, !.
letter(C) --> [C], {"A"=<C, C=<"Z"}, !.
letter_or_digit(C) --> [C], {"a"=<C, C=<"z"}, !.
letter_or_digit(C) --> [C], {"A"=<C, C=<"Z"}, !.
letter_or_digit(C) --> [C], {"0"=<C, C=<"9"}, !.

table("student").

sbvr2sql --> label(Name), " is an integer.", {assert(fields(Name, "INT"))}.
sbvr2sql --> label(Name), " is a string.", {assert(fields(Name, "VARCHAR(64)"))}.

sbvr2sql(Table, Property)  --> label(Table), " has ", label(Property), ".".

Here is how it works fine:

?- sbvr2sql("age is an integer.", []).
true 

?- sbvr2sql("firstName is a string.", []).
true.

?- sbvr2sql(T, P, "student has firstName.", []).
T = "student",
P = "firstName".

?- fields(F, T).
F = "age",
T = [73, 78, 84] n
F = "firstName",
T = [86, 65, 82, 67, 72, 65, 82, 40, 54|...].

?- sbvr2sql(T, P, "student has firstName.", []), fields(P, _).
T = "student",
P = "firstName".

But it doesn't work here:

?- table(T).
T = [115, 116, 117, 100, 101, 110, 116]. % "student"

?- sbvr2sql(T, P, "student has firstName.", []), table(T).
false.

Apparently it doesn't recognise table("student") as true. It recognises "student" as a label as seen above. What gives?

like image 950
Igor Avatar asked Jan 28 '11 10:01

Igor


1 Answers

I can't reproduce the error, but I suspect it may be in your label/3 rule. When I used the following definition of this rule:

label([C|S]) -->
    [C], {[Sp|_] = " ", C \= Sp, [Dot|_] = ".", C \= Dot}, !,
    label(S).
label([],X,X).

I get correct results:

?- sbvr2sql(TS, PS, "student has firstName.", []), table(TS),
   atom_codes(P,PS), atom_codes(T,TS).
TS = [115, 116, 117, 100, 101, 110, 116],
PS = [102, 105, 114, 115, 116, 78, 97, 109, 101],
P = firstName,
T = student.

In general, I'd recommend tokenizing strings into lists of atoms before doing DCG manipulation. That way, it's much easier to debug because of Prolog's awkward string output.

like image 72
Fred Foo Avatar answered Nov 13 '22 22:11

Fred Foo