Index: lib/perl/cqpwebCEQL.pm =================================================================== --- lib/perl/cqpwebCEQL.pm (revision 338) +++ lib/perl/cqpwebCEQL.pm (working copy) @@ -94,9 +94,13 @@ # override lemma_pattern rule to provide support for {book/V} notation +## *** local patch: modify lemma_pattern to allow negation *** sub lemma_pattern { my ($self, $lemma) = @_; + # condition is negated if lemma begins with ! (but not if ! is the only character) + my $neg = ($lemma =~ s/^!(?=.)//) ? "!" : ""; # $neg can be interpolated in to the generated CQP queries + # split lemma into headword pattern and optional simple POS constraint my ($hw, $tag, $extra) = split /(?GetParam("combo_attribute"); if (defined $attr) { $regexp =~ s/^"//; $regexp =~ s/"$//; # remove double quotes around regexp so it can be combined with POS constraint - return "$attr=\"($regexp)_${tag_regexp}\""; + return "$attr${neg}=\"($regexp)_${tag_regexp}\""; } else { my $first_attr = $self->GetParam("lemma_attribute") or die "Searches of the form {.../...} are not available.\n"; my $second_attr = $self->GetParam("simple_pos_attribute") or die "Searches of the form {.../...} are not available.\n"; - return "($first_attr=$regexp & $second_attr=\"${tag_regexp}\")"; + return "${neg}($first_attr=$regexp & $second_attr=\"${tag_regexp}\")"; } } else { # no simple POS specified => match the normal lemma attribute. my $attr = $self->GetParam("lemma_attribute") or die "Searches of the form {...} are not available.\n"; - return "$attr=$regexp"; + return "$attr${neg}=$regexp"; } } + +## *** local patch: also override wordform_pattern, pos_tag and simple_pos to support negated constraints *** +sub wordform_pattern { + my ($self, $wf) = @_; + my $neg = ($wf =~ s/^!(?=.)//) ? "!" : ""; # $neg can be interpolated in to the generated CQP queries + my $regexp = $self->Call("wildcard_pattern", $wf); + return "word${neg}=$regexp"; +} + +sub pos_tag { + my ($self, $tag) = @_; + my $neg = ($tag =~ s/^!(?=.)//) ? "!" : ""; # $neg can be interpolated in to the generated CQP queries + my $attr = $self->GetParam("pos_attribute") + or die "no attribute defined for part-of-speech tags (internal error)\n"; + my $regexp = $self->Call("wildcard_pattern", $tag); + return "$attr${neg}=$regexp"; +} + +sub simple_pos { + my ($self, $tag) = @_; + my $neg = ($tag =~ s/^!(?=.)//) ? "!" : ""; # $neg can be interpolated in to the generated CQP queries + my $attr = $self->GetParam("simple_pos_attribute") || $self->GetParam("pos_attribute") + or die "no attribute defined for part-of-speech tags (internal error)\n"; + my $lookup = $self->GetParam("simple_pos"); + die "no simple part-of-speech tags are available for this corpus\n" + unless ref($lookup) eq "HASH"; + my $regexp = $lookup->{$tag}; + if (not defined $regexp) { + my @valid_tags = sort keys %$lookup; + die "'' $tag '' is not a valid simple part-of-speech tag (available tags: '' @valid_tags '')\n"; + } + return "$attr${neg}=\"$regexp\""; +} + + + =head1 COPYRIGHT Copyright (C) 1999-2008 Stefan Evert [http::/purl.org/stefan.evert]