Ich habe einen adaptiven Parser geschrieben, der englische Phrasen in mathematische Ausdrücke umwandelt. Sie können es problemlos mit Ihren eigenen Übersetzungsregeln erweitern, sodass es zum Erstellen erweiterbarer Benutzeroberflächen in natürlicher Sprache verwendet werden kann.
Dies ist eine mögliche Eingabe:
(A squared) times (b squared) equals c to the power of 3 times the product of 5 and 6
und dies ist seine Ausgabe:
(A * A) * (b * b) = c^3 * 5 * 6
Die Durchführung des Programms wird hier gezeigt:
:- initialization(main).
:- set_prolog_flag(double_quotes, chars). % This is for SWI 7+ to revert to the prior interpretation of quoted strings.
%This is an adaptive parser for SWI-Prolog.
main :-
%Type any kind of input here to see the output! The input must be compatible with the grammar that is defined below.
Input = "(A squared) times (b squared) equals c to the power of 3 times the product of 5 and 6",
iterated_translate(Input,Output), writeln(Input), writeln(Output), writeln('\n'), writeln('\n').
%The grammar is defined here. The variables must be uppercase letters.
%The input in each translation rule is followed by its output.
theList(TheList) :-
%You can easily extend this parser by adding more rules to this list.
TheList =
[['A to the power of B',
'A^B'],
%The next transformation is the final output of 'A to the power of B'.
['A^B',
'A^B'],
['A * B',
'A * B'],
['the product of A and B',
'A times B'],
['A squared',
'the product of A and A'],
['A times B',
'A * B'],
['A = B',
'A = B'],
['A equals B', 'A = B']].
%This is the end of the grammar. The rest of the translator is implemented below.
output_expr(Lang,[Input,[A,B]]) -->
{
theList(TheList),
list_to_output__(TheList,TheList1,[A,B]),
member([Input,Output],
TheList1)
},
input_to_output_(Lang,Input,Output).
atom_is_upper(N) :-
atom_chars(N, [L]),
char_type(L, upper).
atom_is_var(Names_to_vars,Atom,Var) :-
atom(Atom),atom_is_upper(Atom),member([Atom,Var],Names_to_vars).
list_to_output__([],[],_) :- true.
list_to_output__([Start1|Rest1],[Start2|Rest2],Vars) :-
list_to_output_(Start1,Start2,Vars),list_to_output__(Rest1,Rest2,Vars).
list_to_output_([A1_,B1_],[A2,B2],Vars) :- atomic_list_concat(A1,' ',A1_),atomic_list_concat(B1,' ',B1_),list_to_output(A1,A2,Vars),list_to_output(B1,B2,Vars).
list_to_output([],[],_) :- true.
list_to_output([Start1|Rest1],[Start2|Rest2],[A,B]) :-
(Start1='A'->Start2=A;Start1='B'-> Start2=B;Start1=Start2),list_to_output(Rest1,Rest2,[A,B]).
list_to_grammar_(Lang,Start,Rest) -->
{(Start = [A])->(Rest = []->Start1 = expr(Lang,A);Start1 = parentheses_expr(Lang,A));atom_chars(Start,Start1)},Start1.
list_to_grammar(Lang,[Start]) -->
list_to_grammar_(Lang,Start,[]).
list_to_grammar(Lang,[Start|Rest]) -->
list_to_grammar_(Lang,Start,Rest),ws_,list_to_grammar(Lang,Rest).
a_number([A,B]) -->
(a__number(A), ".", a__number(B)).
a_number(A) -->
a__number(A).
a__number([L|Ls]) --> digit(L), a__number_r(Ls).
a__number_r([L|Ls]) --> digit(L), a__number_r(Ls).
a__number_r([]) --> [].
digit(Let) --> [Let], { code_type(Let, digit) }.
symbol([L|Ls]) --> letter(L), symbol_r(Ls).
symbol_r([L|Ls]) --> letter(L), symbol_r(Ls).
symbol_r([]) --> [].
letter(Let) --> [Let], { code_type(Let, alpha) }.
ws --> "";((" ";"\n"),ws).
ws_ --> (" ";"\n"),ws.
input_to_output(Lang,A,B) -->
{Lang = input} ->
A;
{Lang=output} ->
B.
input_to_output_(Lang,A,B) -->
{A_=list_to_grammar(Lang,A),B_=list_to_grammar(Lang,B)},input_to_output(Lang,A_,B_).
parentheses_expr(Lang,["(",A,")"]) -->
("(",(expr(Lang,A)),")").
parentheses_expr(_,symbol(A)) -->
symbol(A).
parentheses_expr(_,a_number(A)) -->
a_number(A).
expr(Lang,A) -->
parentheses_expr(Lang,A);output_expr(Lang,A).
translate(Input1,Output1) :-
phrase(output_expr(input,Ls),Input1),
phrase(output_expr(output,Ls),Output1).
iterated_translate(Input1, Output2) :-
%Keep translating until the input is the same as the output.
translate(Input1,Output1),
(Input1=Output1, Output1 = Output2;iterated_translate(Output1,Output2)).
Mit 'set_prolog_flag/2' sein Sowohl eine * directive * als auch ein * integriertes Prädikat *, warum verwenden Sie die 'initialization/1'-Anweisung, die das Setzen des Flags auf * verzögert. nach * die Quelldatei, die sie enthält, wird kompiliert und geladen? –
Sehr guter Punkt, danke! Ich habe das geändert, um die Richtlinie sofort zu verwenden. – mat