Article View: comp.lang.prolog
Article #1403Re: Can I talk about Parlog here? (Long, 259 lines)
From: Ken Johnson
Date: Wed, 14 Nov 1990 19:37
Date: Wed, 14 Nov 1990 19:37
254 lines
7681 bytes
7681 bytes
In article <EIVERSON.90Nov13182825@aigyptos.nmsu.edu> eiverson@nmsu.edu
(Eric Iverson) writes:
> Is there an efficient parallel parser that works under IC
> Parlog without crashing it?
Here is a version of Conlon's parser written in Strand-88. The changes
needed to convert it to Parlog should be obvious, i.e. I have not tried
to do it. The code was written by Malcolm Brown of Strand Software; I
had nothing to do with it.
% Malcolm Brown
% 22/02/1990
% parallel parser. based on a prolog program given to me by Ken Johnson
% from AIAI in Edinburgh, who in turn took it from Tom Conlon's Parlog book
% pages 241 - 252
% This parser finds all possible parses to an input sentence.
% The module has two entry points:
% 1) parse([list of words], Resulting_Parse)
% 2) parse_form([list of words], form, Resulting_Parse)
% The program is similar in style to the original prolog program with
% the exception of linking the dictionary with the grammer. If a dictionary
% for an expansion cannot be found then a grammar rewrite is looked for in
% grammar database. This takes care of the case:
% parse_form([noun],noun_expression,Parse)
% and there is a rewrite of the form: noun_expression -> noun
%
% The orginal prolog program was roughly 1.75 a4 pages so about 100 lines
% The Parlog program was about 2 pages long so about 120 lines
% The Strand program (without comments, to be comparable) is about 160 lines
%
%--------------------------------------------------
-compile(free).
-exports([parse/2,parse_form/3,expansions_parse/5,splits_parse/4]).
%--------------------------------------------------
parse(S,P):-
parse_form(S,sentence,P).
parse_form([],Form,P):-
P:={Form,[]}.
parse_form([Word],Form,P):-
dictionary(Form,Dict_or_grammar),
terminal_or_not(Dict_or_grammar,Word,P,Found,Form). % check if Form is a terminal
parse_form(Words,Form,P):-
otherwise |
grammar(Form,Expansions),
expansions_parse(Words,Expansions,[],P_list,Res),
check_parse(Res,P_list,Form,P). % check result
% if Form is not a terminal i.e. a rewrite rule has been returned by dictionary
% the parse the Expansions
terminal_or_not({grammar,Expansions},Word,P,Res,Form):-
expansions_parse([Word],Expansions,[],P_list,Res),
check_parse(Res,P_list,Form,P).
terminal_or_not(Dict,Word,P,Found,Form):-
otherwise |
member(Word,Dict,Found),
check_parse(Found,Word,Form,P).
% find out if the parse was successful
check_parse(fail,_,Form,P):-
P:= {Form,[]}. % [] is the failure token.
check_parse(_,P_list,Form,P):-
otherwise |
P:= {Form,P_list}. % return the list of parses
%--------------------------------------------------
expansions_parse(Words,[Exp | Exp_rest],Sofar,P,Res):-
one_expansion(Words,Exp,One_parse),
add_parse(One_parse,Sofar,New_sofar), % add parse if Exp parsed Words
expansions_parse(Words,Exp_rest,New_sofar,P,Res). % try next expansion
expansions_parse(W,[],[],_,Res):- % couldn't parse any expansion
Res := fail.
expansions_parse(_,[],Parses,P,Res):- % found some parses
otherwise |
Res := success,
P:= Parses.
add_parse([],Sofar,New_sofar):-
New_sofar := Sofar. % no parses so short circuit
add_parse(Parse,Sofar,New_sofar):- % got one. add to the list
otherwise |
New_sofar := [Parse | Sofar].
%--------------------------------------------------
% All possible parses resulting from all splits of words are
% inserted into the Parse_stream. Thus each element in this stream
% represents a valid parse of Words using the expansion [Form1,Form2]
one_expansion(Words,[Form1,Form2],Parse):-
gen_splits(Words,Splits),
splits_parse(Splits,Form1,Form2,Parse_stream),
check_split_parse(Parse_stream,Parse). % were any parses found?
one_expansion(Words,[Form],Parse):-
parse_form(Words,Form,Parse1),
check_single_exp(Parse1,Parse).
check_split_parse([[] | Rest], Parse):- % failed parse. look in the tail
check_split_parse(Rest,Parse).
check_split_parse([[Parse1,Parse2]| _ ],Parse):- % got one
Parse := [Parse1,Parse2].
check_split_parse([],Parse):- % no more
Parse := [].
%--------------------------------------------------
check_single_exp({_,[]},P):- % didn't parse
P := [].
check_single_exp(Parse,P):- % did parse
otherwise |
P:= Parse.
%--------------------------------------------------
% In this procedure an individual split is parsed and the result
% is merged with the results of parsing the remaining splits, into
% the return stream. (Note an inefficient, software merge is used here)
splits_parse([pair(Front,Back)|Splits],Form1,Form2,P_stream):-
parse_form(Front,Form1,Parse1),
parse_form(Back,Form2,Parse2),
merge(P_new,Res_stream,P_stream),
check_split(Parse1,Parse2,Res_stream),
splits_parse(Splits,Form1,Form2,P_new).
splits_parse([],_,_,P_stream):-
P_stream := [].
check_split({_,[]},_,Res_stream):- % no parse for Front split
Res_stream := [].
check_split(_,{_,[]},Res_stream):- % no parse for Back split
Res_stream := [].
check_split(P1,P2,Res_stream):- % parsed front and back
otherwise |
Res_stream := [[P1,P2]].
%--------------------------------------------------
gen_splits([Word], Splits):-
Splits:=[].
gen_splits([Word | Words], Splits):-
otherwise |
Splits := [pair([Word],Words) | S1],
gen_splits(Words,Tsplits),
front_insert(Word,Tsplits,S1).
front_insert(_,[],S):-
S:=[].
front_insert(Word,[pair(F,B) | Trest],Splits):-
Splits := [pair([Word|F],B) | S1],
front_insert(Word,Trest,S1).
merge([H|T],B,O):-
O:=[H|O1],
merge(T,B,O1).
merge(A,[H|T],O):-
O:=[H|O2],
merge(A,T,O2).
merge(A,[],O):-
O:=A.
merge([],A,O):-
O:= A.
member(I,[I | _], Res):-
Res := I.
member(I,[_|T],Res):-
otherwise |
member(I,T,Res).
member(_,[],Res):-
Res := fail.
%-------------------------
-mode dictionary(?,^).
dictionary(adverb,[quickly,easily]).
dictionary(determiner,[a,an,the]).
dictionary(adjective,[good,bad,naughty,drunk]).
dictionary(noun,[boy,girl,table,tree,apple,ball]).
dictionary(verb,[likes,kicks,smiles,admires,eats]).
dictionary(Cat,Res):- % not a terminator so try a rule
otherwise |
grammar(Cat,G),
Res := {grammar,G}.
-mode grammar(?,^).
% repeat expansions force the system to find the same solution twice
grammar(noun_expression,[[noun],[adjective,noun_expression]]).
grammar(noun_phrase,[[determiner,noun_expression]]).
grammar(sentence,[[noun_phrase,verb],[noun_phrase,verb_phrase]]).
grammar(verb_expression,[[verb],[adverb,verb]]).
grammar(verb_phrase,[[verb_expression,noun_phrase]]).
grammar(_,Res):-
otherwise |
Res := [].
--
Ken Johnson, AI Applications Inst., 80 South Bridge, Edinburgh EH1 1HN
E-mail ken@aiai.ed.ac.uk, ******************************************
phone 031-225 4464 extension 213 ** `You can resole your boot, but you **
new quotation --> ** can't reboot your soul' [The Oracle] **
Technical Details
Message-ID:
<3757@skye.ed.ac.uk>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!wuarchive!uunet!mcsun!ukc!edcastle!aiai!kenReferences:
<EIVERSON.90Nov12212535@thrinakia.nmsu.edu> <EIVERSON.90Nov13182825@aigyptos.nmsu.edu>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!zaphod.mps.ohio-state.edu!wuarchive!uunet!mcsun!ukc!edcastle!aiai!ken From: ken@aiai.ed.ac.uk (Ken Johnson) Newsgroups: comp.lang.prolog Subject: Re: Can I talk about Parlog here? (Long, 259 lines) Message-ID: <3757@skye.ed.ac.uk> Date: 14 Nov 90 19:37:36 GMT References: <EIVERSON.90Nov12212535@thrinakia.nmsu.edu> <EIVERSON.90Nov13182825@aigyptos.nmsu.edu> Reply-To: ken@aiai.ed.ac.uk (Ken Johnson) Followup-To: comp.lang.prolog Distribution: comp Organization: Bugs-R-Us Lines: 254