#!/usr/bin/perl
use
5.010001;
use
POSIX
qw(setlocale LC_ALL)
;
POSIX::setlocale(LC_ALL,
"C"
);
sub
do_sva_sentence {
my
@v
= @{
$_
[1]};
return
"sva($v[0];$v[1];$v[2])"
}
sub
do_svo_sentence {
my
@v
= @{
$_
[1]};
return
"svo($v[0];$v[1];$v[2])"
}
sub
do_adjunct {
my
@v
= @{
$_
[1]};
return
"adju($v[0];$v[1])"
}
sub
do_adjective {
my
@v
= @{
$_
[1]};
return
"adje(${$v[0]})"
}
sub
do_qualified_subject {
my
@v
= @{
$_
[1]};
return
"s($v[0];$v[1])"
}
sub
do_bare_subject {
my
@v
= @{
$_
[1]};
return
"s($v[0])"
}
sub
do_noun {
my
@v
= @{
$_
[1]};
return
"n(${$v[0]})"
}
sub
do_verb {
my
@v
= @{
$_
[1]};
return
"v(${$v[0]})"
}
sub
do_object {
my
@v
= @{
$_
[1]};
return
"o($v[0];$v[1])"
}
sub
do_article {
my
@v
= @{
$_
[1]};
return
"art(${$v[0]})"
}
sub
do_preposition {
my
@v
= @{
$_
[1]};
return
"pr(${$v[0]})"
}
my
$grammar
= Marpa::R3::Scanless::G->new(
{
semantics_package
=>
'main'
,
source
=> \
<<'END_OF_DSL',
sentence ::= subject verb adjunct action => do_sva_sentence
sentence ::= subject verb object action => do_svo_sentence
adjunct ::= preposition object action => do_adjunct
adjective ::= adjective_noun_lex action => do_adjective
subject ::= adjective noun action => do_qualified_subject
subject ::= noun action => do_bare_subject
noun ::= adjective_noun_lex action => do_noun
verb ::= verb_lex action => do_verb
object ::= article noun action => do_object
article ::= article_lex action => do_article
preposition ::= preposition_lex action => do_preposition
adjective_noun_lex ~ unicorn
verb_lex ~ unicorn
article_lex ~ unicorn
preposition_lex ~ unicorn
unicorn ~ [\d\D]
END_OF_DSL
}
);
my
$expected
=
<<'EOS';
sva(s(n(fruit));v(flies);adju(pr(like);o(art(a);n(banana))))
sva(s(n(time));v(flies);adju(pr(like);o(art(an);n(arrow))))
svo(s(adje(fruit);n(flies));v(like);o(art(a);n(banana)))
svo(s(adje(time);n(flies));v(like);o(art(an);n(arrow)))
EOS
my
@actual
= ();
my
%lexical_class
= (
'preposition_lex'
=>
'like'
,
'verb_lex'
=>
'like flies'
,
'adjective_noun_lex'
=>
'fruit banana time arrow flies'
,
'article_lex'
=>
'a an'
,
);
my
%vocabulary
= ();
for
my
$lexical_class
(
keys
%lexical_class
) {
my
$words
=
$lexical_class
{
$lexical_class
};
for
my
$word
(
split
q{ }
,
$words
) {
push
@{
$vocabulary
{
$word
} },
$lexical_class
;
}
}
for
my
$data
(
'time flies like an arrow'
,
'fruit flies like a banana'
) {
my
$recce
= Marpa::R3::Scanless::R->new( {
grammar
=>
$grammar
} );
die
'Failed to create recognizer'
if
not
$recce
;
my
$lexeme_start
= 0;
$recce
->
read
( \
$data
, 0, 0 );
for
my
$word
(
split
q{ }
,
$data
) {
for
my
$type
( @{
$vocabulary
{
$word
} } ) {
$recce
->lexeme_alternative(
$type
, \
$word
)
or
die
'Recognition failed'
;
}
$recce
->lexeme_complete(
$lexeme_start
,
length
$word
);
$lexeme_start
+=
length
$word
;
}
while
(
defined
(
my
$value_ref
=
$recce
->value() ) ) {
my
$value
=
$value_ref
? ${
$value_ref
} :
'No parse'
;
push
@actual
,
$value
;
}
}
Marpa::R3::Test::is( (
join
"\n"
,
sort
@actual
) .
"\n"
,
$expected
,
'Ambiguous English sentences'
);