bh@anarres.CS.Berkeley.EDU (Brian Harvey) writes:
> Date: 15 Nov 92 21:20:26 GMT
> Organization: University of California, Berkeley
>
> Of course, these examples are entirely equivalent to what could be done
> in Lisp.
Agreed, or in Prolog
> I think you should post examples using some of the more unusual
> POP features, such as pattern matching.
I am tempted. Hope it's not too long.
The Pop-11 pattern matchers (there are two now) are unlike
prolog unification in that they go only one way: i.e. you can have
variables only on the right: so you can't match two variables and
have a later binding of one of them propagate to the other). However
the Pop-11 matchers compensate for this (some would say more than
compensate, others would say less than compensate) by allowing
segment variables in the middle of a list, plus restriction
procedures.
Here's an example of the use of forevery, which uses the
(original) Pop-11 matcher;
vars x, y, z;
vars properties =
[[g is h][e is f] [d is e] [b is c] [a is b] [h is i]];
forevery [[?x is ?y][?y is ?z]] in properties do
;;; extend the list of properties
[[^x is ^z] ^^properties] -> properties;
endforevery;
properties ==>
** [[a is c]
[d is f]
[g is i]
[g is h]
[e is f]
[d is e]
[b is c]
[a is b]
[h is i]]
Using the matcher you can define a very simple parser. In what
follows ?<var> matches a single item in a list ??<var> matches
an arbitrarily long segment of a list. If the <var> is followed
by a colon, then the next item is taken to refer to a restriction
predicate, as in ?word:noun. If a match is successful and the
restriction predicate returns a non-boolean result, then the
result is bound to the variable.
;;; first define recognisers for lexical categories
define recognise(word, category, list) -> result;
lvars word, category, list, result;
if member(word, list) then
[^category ^word] -> result;
else
false -> result
endif;
enddefine;;
;;; define particular recognisers by partially applying recognise
define noun =
recognise(%"noun", [cat dog mouse elephant man mat tree owl]%)
enddefine;
define det =
;;; recogniser for determiners
recognise(%"det", [each all every a the some]%)
enddefine;
define adj =
recognise(%"adj", [happy hungry big rich yellow striped]%)
enddefine;
define verb =
recognise(%"verb", [ate struck chased liked stroked tickled]%)
enddefine;
;;; a utility to check that all elements of a list satisfy a predicate
define all_are(list, pred) -> result;
lvars list, pred, result = false, item;
for item in list do
returnunless(pred(item))
endfor;
true -> result;
enddefine;
;;; now recogniser/parsers for non-terminals
define np(list) -> result;
;;; parse noun phrases
lvars list,result;
vars word1,word2,word3,list1; ;;; pattern variables
if list matches [?word1:det ?word2:noun] then
[np ^word1 ^word2]
elseif list matches [?word1:det ?word2:adj ?word3:noun] then
[np ^word1 ^word2 ^word3]
elseif
list matches [?word1:det ??list1: ^(all_are(%adj%)) ?word2:noun]
then
[np ^word1 [adjs ^list1] ^word2]
else
false
endif -> result
enddefine;
define vp(list) -> result;
;;; parse verb phrases
lvars list, result;
vars word list2;
if list matches [?word:verb ??list2:np] then
[vp ^word ^list2]
else
false
endif -> result;
enddefine;
define sentence(list) -> result;
lvars list,result;
vars list1, list2;
if list matches [??list1:np ??list2:vp] then
[sentence ^list1 ^list2]
else
false
endif -> result
enddefine;
;;; now for a bit of magic
np([the dog]) =>
** [np [det the] [noun dog]]
np([the big dog]) =>
** [np [det the] [adj big] [noun dog]]
np([each hungry yellow cat]) =>
** [np [det each] [adjs [hungry yellow]] [noun cat]]
vp([chased the cat]) =>
** [vp [verb chased] [np [det the] [noun cat]]]
sentence([the dog chased the rich yellow cat]) ==>
** [sentence [np [det the] [noun dog]]
[vp [verb chased]
[np [det the] [adjs [rich yellow]] [noun cat]]]]
sentence([every rich happy elephant tickled some
big striped yellow mouse]) ==>
** [sentence [np [det every] [adjs [rich happy]] [noun elephant]]
[vp [verb tickled]
[np [det some]
[adjs [big striped yellow]]
[noun mouse]]]]
;;; or with a more pictorial display
lib showtree
showtree(sentence([the big cat liked the striped mat]));
/--------\
|sentence|
\---+----/
/----------+----------\
/+-\ /+-\
|np| |vp|
\+-/ \+-/
/------+------\ /------+------\
/-+-\ /-+-\ /-+--\ /-+--\ /+-\
|det| |adj| |noun| |verb| |np|
\-+-/ \-+-/ \-+--/ \-+--/ \+-/
| | | | /------+------\
| | | | /-+-\ /-+-\ /-+--\
the big cat liked |det| |adj| |noun|
\-+-/ \-+-/ \-+--/
| | |
| | |
the striped mat
Actually it looks nicer on a terminal with graphics, but that's
not for a news posting!
Of course, there are better ways to write parsers, but this
illustrates the matcher.
(The parsing example was based on one of Poplog Pop-11's online
"teach" files, most of which contain examples that can be run at the
terminal.)
Aaron
--
Aaron Sloman, School of Computer Science,
The University of Birmingham, B15 2TT, England
EMAIL A.Sloman@cs.bham.ac.uk OR A.Sloman@bham.ac.uk
Phone: +44-(0)21-414-3711 Fax: +44-(0)21-414-4281
|