Initial import of the ircii-pana-1.1-final source tree.
git-svn-id: svn://svn.code.sf.net/p/bitchx/code/tags/ircii-pana-1.1-final@1 13b04d17-f746-0410-82c6-800466cd88b0
This commit is contained in:
340
dll/europa/COPYING
Normal file
340
dll/europa/COPYING
Normal file
@@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
4
dll/europa/CREDITS
Normal file
4
dll/europa/CREDITS
Normal file
@@ -0,0 +1,4 @@
|
||||
Jeremy Tregunna (aka zdt on EFnet #linuxinfo) contributed the pengy database
|
||||
entries from his Pengy bot. This provides a nice knowledgebase that gives
|
||||
Europa a running start towards being useful. Thanks!
|
||||
|
||||
185
dll/europa/Makefile.in
Normal file
185
dll/europa/Makefile.in
Normal file
@@ -0,0 +1,185 @@
|
||||
# dll/europa/Makefile
|
||||
# (c) David Walluck 2000
|
||||
|
||||
SHELL = @SHELL@
|
||||
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
top_srcdir = @top_srcdir@
|
||||
topdir = @topdir@
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
bindir = @bindir@
|
||||
sbindir = @sbindir@
|
||||
libexecdir = @libexecdir@
|
||||
datadir = @datadir@
|
||||
sysconfdir = @sysconfdir@
|
||||
sharedstatedir = @sharedstatedir@
|
||||
localstatedir = @localstatedir@
|
||||
libdir = @libdir@
|
||||
infodir = @infodir@
|
||||
mandir = @mandir@
|
||||
includedir = @includedir@
|
||||
oldincludedir = @oldincludedir@
|
||||
|
||||
local_dir = $(HOME)
|
||||
|
||||
# Where the BitchX binary will be installed.
|
||||
# "make install" will compile and install the program.
|
||||
INSTALL_IRC = @INSTALL_IRC@
|
||||
|
||||
# Where the BitchX library will be. Generally this is the place that
|
||||
# you put the scripts, help pages and translation tables. It is
|
||||
# very important that you set this correctly.
|
||||
IRCLIB = @IRCLIB@
|
||||
|
||||
CC = @CC@
|
||||
DEFS = @INCLUDES@
|
||||
LIBS = @LIBS@
|
||||
|
||||
# Tcl library.
|
||||
TCL_LIBS = @TCL_LIBS@
|
||||
|
||||
# These are for Tcl support.
|
||||
TCL_OBJS = @TCL_OBJS@
|
||||
# You don't have the following, so you'll want to leave this blank.
|
||||
TCL_SRCS = @TCL_SRCS@
|
||||
|
||||
# Set this to -g if you want to be able to debug the client, otherwise
|
||||
# use -O to have the compiler do some optimization instead.
|
||||
CFLAGS = @CFLAGS@
|
||||
|
||||
# Set this to -s if you want the binary to be stripped.
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
# These are for the cd device player.
|
||||
CD_SRCS = @CD_SRCS@
|
||||
CD_OBJS = @CD_OBJS@
|
||||
|
||||
# This is the executable suffix for the target operating system.
|
||||
EXEEXT = @EXEEXT@
|
||||
|
||||
# Extra files.
|
||||
DEFAULT_CTOOLZ_DIR = @DEFAULT_CTOOLZ_DIR@
|
||||
DEFAULT_MSGLOGFILE = @DEFAULT_MSGLOGFILE@
|
||||
DEFAULT_BITCHX_HELP_FILE = @DEFAULT_BITCHX_HELP_FILE@
|
||||
DEFAULT_SCRIPT_HELP_FILE = @DEFAULT_SCRIPT_HELP_FILE@
|
||||
DEFAULT_BITCHX_KICK_FILE = @DEFAULT_BITCHX_KICK_FILE@
|
||||
DEFAULT_BITCHX_QUIT_FILE = @DEFAULT_BITCHX_QUIT_FILE@
|
||||
DEFAULT_BITCHX_IRCNAME_FILE = @DEFAULT_BITCHX_IRCNAME_FILE@
|
||||
|
||||
# Full path of the directory for BitchX help files.
|
||||
HELPDIR = @HELPDIR@
|
||||
|
||||
# Full path of the directory for the BitchX scripts.
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
|
||||
# Default setting for IRCPATH where BitchX will look for
|
||||
# its script files if the environment variable is undefined.
|
||||
# Usually, this should contain the same path as used for INSTALL_SCRIPT in
|
||||
# the Makefile, but it can contain multiple path elements
|
||||
# separated by colons. The path MUST lead to an existing directory,
|
||||
# because the 'global' script is expected to be found there.
|
||||
IRCPATH = @IRCPATH@
|
||||
|
||||
# Path for TRANSLATION variable.
|
||||
TRANSLATION_PATH = @TRANSLATION_PATH@
|
||||
|
||||
# This command will be used to install the BitchX help files. If you don't
|
||||
# want to install them, replace with the following:
|
||||
# INSTALL_HELP_CMD = @echo The help files have not been installed.
|
||||
INSTALL_HELP_CMD = @INSTALL_HELP_CMD@
|
||||
|
||||
# This is where the optional plugins will be copied to.
|
||||
PLUGINDIR = @PLUGINDIR@
|
||||
|
||||
# Plugin flags.
|
||||
SHLIB_LD = @SHLIB_LD@
|
||||
SHLIB_CFLAGS = @SHLIB_CFLAGS@
|
||||
SHLIB_SUFFIX = @SHLIB_SUFFIX@
|
||||
|
||||
# This command will be used to install the BitchX files on Win32/OS2EMX
|
||||
# systems.
|
||||
WINNT_INSTALL = @WINNT_INSTALL@
|
||||
|
||||
# This program allows you to use screen/xterm's to put new BitchX windows
|
||||
# on new screen/xterm windows.
|
||||
INSTALL_WSERV = @INSTALL_WSERV@
|
||||
|
||||
# This program allows you to screen BitchX and reattach to it later.
|
||||
INSTALL_SCRBX = @INSTALL_SCRBX@
|
||||
|
||||
# Set gzip and bzip2 options.
|
||||
GZIP_ENV = @GZIP_ENV@
|
||||
BZIP2 = @BZIP2@
|
||||
|
||||
# Standard programs.
|
||||
RM = @RM@
|
||||
LN = @LN_S@
|
||||
CP = @CP@
|
||||
MV = @MV@
|
||||
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
|
||||
VERSION = @VERSION@
|
||||
_VERSION_ = @_VERSION_@
|
||||
|
||||
MAKE_BIN = @MAKE@
|
||||
MAKE = $(MAKE_BIN) $(MFLAGS)
|
||||
MFLAGS = \
|
||||
'local_dir=$(HOME)' \
|
||||
'INSTALL_IRC=$(INSTALL_IRC)' \
|
||||
'IRCLIB=$(IRCLIB)' \
|
||||
'CC=$(CC)' \
|
||||
'CFLAGS=$(CFLAGS)' \
|
||||
'HELPDIR=$(HELPDIR)' \
|
||||
'INSTALL_WSERV=$(INSTALL_WSERV)' \
|
||||
'IRCPATH=$(IRCPATH)' \
|
||||
'TRANSLATION_PATH=$(TRANSLATION_PATH)' \
|
||||
'LDFLAGS=$(LDFLAGS)' \
|
||||
'LIBS=$(LIBS)' \
|
||||
'LN=$(LN)' \
|
||||
'RM=$(RM)' \
|
||||
'TCL_SRCS=$(TCL_SRCS)' \
|
||||
'TCL_OBJS=$(TCL_OBJS)' \
|
||||
'CD_PLAY=$(CD_PLAY)' \
|
||||
'CD_SRCS=$(CD_SRCS)' \
|
||||
'CD_OBJS=$(CD_OBJS)' \
|
||||
'TCL_LIBS=$(TCL_LIBS)' \
|
||||
'PLUGINDIR=$(PLUGINDIR)' \
|
||||
'_VERSION_=$(_VERSION_)' \
|
||||
'VERSION=$(VERSION)' \
|
||||
'INSTALL_DATA=$(INSTALL_DATA)' \
|
||||
'INSTALL_SCRIPT=$(INSTALL_SCRIPT)' \
|
||||
'EXEEXT=$(EXEEXT)' \
|
||||
'SHLIB_CFLAGS=$(SHLIB_CFLAGS)' \
|
||||
'SHLIB_SUFFIX=$(SHLIB_SUFFIX)'
|
||||
|
||||
## Makefile starts here.
|
||||
|
||||
MYSQL_LIBS = @MYSQL_LIBS@
|
||||
|
||||
PLUGIN_NAME = europa
|
||||
|
||||
all: Makefile europa$(SHLIB_SUFFIX)
|
||||
|
||||
Makefile: Makefile.in
|
||||
cd $(topdir) \
|
||||
&& ./config.status
|
||||
|
||||
europa.o: $(srcdir)/europa.c
|
||||
$(CC) $(DEFS) $(CFLAGS) -c $(srcdir)/europa.c
|
||||
|
||||
europa$(SHLIB_SUFFIX): europa.o ../dllinit.o
|
||||
$(SHLIB_LD) europa.o ../dllinit.o $(SHLIB_CFLAGS) -o europa$(SHLIB_SUFFIX) $(MYSQL_LIBS)
|
||||
|
||||
clean:
|
||||
$(RM) *~ *.o *.a *.dll europa$(SHLIB_SUFFIX) *.def .#*
|
||||
|
||||
distclean: clean
|
||||
$(RM) Makefile
|
||||
|
||||
install:
|
||||
$(INSTALL) $(PLUGIN_NAME)$(SHLIB_SUFFIX) $(PLUGINDIR)
|
||||
139
dll/europa/README
Normal file
139
dll/europa/README
Normal file
@@ -0,0 +1,139 @@
|
||||
Europa v0.01
|
||||
Copyright (c) 1999, Ed Schlunder <zilym@asu.edu>
|
||||
|
||||
This is Free Software licensed under the GNU GPL. Please see COPYING for
|
||||
details.
|
||||
|
||||
WARNING - YOUR MILEAGE MAY VARY. USE AT YOUR OWN RISK. AUTHOR IS NOT
|
||||
RESPONSIBLE FOR ANY DAMAGES INCURRED THROUGH THE USE OF THIS PACKAGE.
|
||||
|
||||
SUMMARY
|
||||
--------------------------------------------------------------------------
|
||||
Europa is a BitchX (popular irc client) plugin to provide easy access to
|
||||
an SQL knowledgebase. This is helpful for use in help channels where
|
||||
common questions repeatedly come up.
|
||||
|
||||
BACKGROUND
|
||||
--------------------------------------------------------------------------
|
||||
For the past 2-3 years, we've been answering people's questions about Linux
|
||||
in the EFnet IRC channel #linuxinfo. Jeremy Tregunna wrote a bot
|
||||
in Perl called 'Penguin' that stored tons of keyword/answers pairs in
|
||||
a database so that channel operators could store commonly asked question
|
||||
answers in. When a Linux newbie came in and asked a question already
|
||||
answered several times before in prior conversations, we simply ask
|
||||
Penguin to please explain the keyword associated with the question, saving
|
||||
us a lot of typing time.
|
||||
|
||||
I've always admired the Penguin bot a lot and wished I could run one
|
||||
myself. However, I don't have access to any IRC servers that allow bots.
|
||||
This led to the developement of Europa, a BitchX plugin that listens to
|
||||
channels you are chatting on and automatically responds when it sees
|
||||
someone giving it a command. This lets you chat on IRC as a normal user
|
||||
like you've always done, but also have a nice SQL knowledgebase available
|
||||
at your (and your friends) finger tips.
|
||||
|
||||
REQUIREMENTS
|
||||
--------------------------------------------------------------------------
|
||||
Europa currently only support MySQL (http://www.mysql.com/) for the
|
||||
database backend. You will need to have MySQL already installed
|
||||
and working to use Europa.
|
||||
|
||||
To use Europa, you need to be using BitchX (http://www.bitchx.org/). In
|
||||
addition, to compile Europa, you will need a copy of the BitchX source
|
||||
code extracted as ../BitchX (relative to Europa's directory).
|
||||
|
||||
INSTALLATION
|
||||
--------------------------------------------------------------------------
|
||||
1. Extract the Europa source code and the BitchX source code:
|
||||
gzip -cd europa-xxx.tar.gz | tar xvf -
|
||||
gzip -cd BitchX-1.0c13.tar.gz | tar xvf -
|
||||
|
||||
These should be extracted this way so that the Europa makefile can
|
||||
access the BitchX include files (see Makefile to see what I mean).
|
||||
|
||||
2. Compile and install BitchX
|
||||
cd BitchX/
|
||||
less INSTALL
|
||||
|
||||
3. Create a database for Europa to use on your mysql server:
|
||||
mysql mysql -u root -p
|
||||
create database europa;
|
||||
insert into user values('%','europa',password('APASSWD'),'N','N','N','N','N','N','N','N','N','N','N','N','N','N','N');
|
||||
insert into db values('%','europa','europa','Y','Y','Y','Y','N','N','N','N','N','N');
|
||||
exit
|
||||
|
||||
mysqladmin reload -u root -p
|
||||
mysql europa -u root -p < knowledgebase.sql
|
||||
|
||||
4. Edit europa.h to match your settings, should be self explanatory.
|
||||
|
||||
5. Compile the Europa source code:
|
||||
make
|
||||
|
||||
6. Copy the resulting europa.so file to your ~/.BitchX/plugins/ directory,
|
||||
or alternatively you could put it in your system wide BitchX plugins
|
||||
directory (/usr/local/lib/bx/plugins/ on my system).
|
||||
|
||||
7. Start up BitchX. Do a "/loaddll europa.so" and you should see
|
||||
Europa load and connect to your SQL knowledgebase.
|
||||
|
||||
You may want to add the command "LOADDLL europa.so" to your
|
||||
~/.BitchX/BitchX.sav file so that Europa loads automatically everytime
|
||||
you start BitchX.
|
||||
|
||||
USING EUROPA
|
||||
--------------------------------------------------------------------------
|
||||
Now that you've got it running, what can you do? Join a channel with
|
||||
some people on it. You may want to start another IRC session so you
|
||||
can talk to yourself (Europa can only see public commands from other
|
||||
clients, someone tell me how to fix that ;-). Suppose the client running
|
||||
Europa has the nick "jonny" and your second session has the nick "jon".
|
||||
A typical chat might look like:
|
||||
|
||||
<jon> jonny: explain winnt
|
||||
<jonny> jon: Windows NT is a fully 32-bit operating system for the i386 and
|
||||
Alpha hardware playforms with superb multi-tasking and server
|
||||
functionality. Written by Microsoft Corporation
|
||||
(http://www.microsoft.com/).
|
||||
<jon> jonny: forget winnt
|
||||
<jonny> jon: winnt forgotten...
|
||||
<jon> jonny learn winnt Windows NT is a 32-bit operating system for the i386
|
||||
and Alpha architectures with superb multitasking and server
|
||||
functionality (yeah, uh-huh, and pigs fly)... See
|
||||
http://www.microsoft.com/ and
|
||||
http://www.cnn.com/TECH/computing/9907/15/nt-mare.idg/
|
||||
<jonny> jon: winnt learned, thanks...
|
||||
|
||||
Public command reference:
|
||||
NICK: explain KEYWORD
|
||||
NICK: forget KEYWORD
|
||||
NICK: learn KEYWORD ANSWER TEXT
|
||||
NICK: shutup
|
||||
-- europa disables saying anything to others
|
||||
NICK: hello
|
||||
-- europa turns back on and talks again
|
||||
|
||||
And thus is the gist of using Europa. Also, Europa installs a new
|
||||
irc command "/explain USER KEYWORD" which lets you send a private
|
||||
message to a specific user containing the answer to KEYWORD. You
|
||||
could also do "/explain #CHANNEL KEYWORD" to send it to a channel
|
||||
you are currently on publically.
|
||||
|
||||
I haven't implemented "/forget KEYWORD" or "/learn KEYWORD ANSWER" yet,
|
||||
sorry.
|
||||
|
||||
FUTURE PLANS
|
||||
--------------------------------------------------------------------------
|
||||
I'd really like to redo Europa in Java and implement some natural
|
||||
language processing capabilities in it. You can see some of my
|
||||
experimenting with interfacing C to Java in the corba/ directory.
|
||||
|
||||
Processing text in C is not particularly easy to do in a safe manner.
|
||||
Doing AI stuff is even harder to do without a nice garbage collector
|
||||
taking care of memory management for you. Normally, I depise Java for
|
||||
just about every project due to its closed sourced nature and buggy Linux
|
||||
support. But this is one case where it might be a good choice, we'll see.
|
||||
|
||||
You can see my previous NLP work in the cse476/ folder. If you actually
|
||||
figure out what the code is doing in there, you'll understand why a
|
||||
garbage collector would be really nice for this and why C isn't.
|
||||
BIN
dll/europa/corba/EuropaAI/Europa.class
Normal file
BIN
dll/europa/corba/EuropaAI/Europa.class
Normal file
Binary file not shown.
13
dll/europa/corba/EuropaAI/Europa.java
Normal file
13
dll/europa/corba/EuropaAI/Europa.java
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* File: ./EuropaAI/Europa.java
|
||||
* From: europa.idl
|
||||
* Date: Thu Dec 23 02:08:42 1999
|
||||
* By: idltojava Java IDL 1.2 Aug 11 1998 02:00:18
|
||||
*/
|
||||
|
||||
package EuropaAI;
|
||||
public interface Europa
|
||||
extends org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity {
|
||||
void inputChat(String text)
|
||||
;
|
||||
}
|
||||
BIN
dll/europa/corba/EuropaAI/EuropaHelper.class
Normal file
BIN
dll/europa/corba/EuropaAI/EuropaHelper.class
Normal file
Binary file not shown.
50
dll/europa/corba/EuropaAI/EuropaHelper.java
Normal file
50
dll/europa/corba/EuropaAI/EuropaHelper.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* File: ./EuropaAI/EuropaHelper.java
|
||||
* From: europa.idl
|
||||
* Date: Thu Dec 23 02:08:42 1999
|
||||
* By: idltojava Java IDL 1.2 Aug 11 1998 02:00:18
|
||||
*/
|
||||
|
||||
package EuropaAI;
|
||||
public class EuropaHelper {
|
||||
// It is useless to have instances of this class
|
||||
private EuropaHelper() { }
|
||||
|
||||
public static void write(org.omg.CORBA.portable.OutputStream out, EuropaAI.Europa that) {
|
||||
out.write_Object(that);
|
||||
}
|
||||
public static EuropaAI.Europa read(org.omg.CORBA.portable.InputStream in) {
|
||||
return EuropaAI.EuropaHelper.narrow(in.read_Object());
|
||||
}
|
||||
public static EuropaAI.Europa extract(org.omg.CORBA.Any a) {
|
||||
org.omg.CORBA.portable.InputStream in = a.create_input_stream();
|
||||
return read(in);
|
||||
}
|
||||
public static void insert(org.omg.CORBA.Any a, EuropaAI.Europa that) {
|
||||
org.omg.CORBA.portable.OutputStream out = a.create_output_stream();
|
||||
write(out, that);
|
||||
a.read_value(out.create_input_stream(), type());
|
||||
}
|
||||
private static org.omg.CORBA.TypeCode _tc;
|
||||
synchronized public static org.omg.CORBA.TypeCode type() {
|
||||
if (_tc == null)
|
||||
_tc = org.omg.CORBA.ORB.init().create_interface_tc(id(), "Europa");
|
||||
return _tc;
|
||||
}
|
||||
public static String id() {
|
||||
return "IDL:EuropaAI/Europa:1.0";
|
||||
}
|
||||
public static EuropaAI.Europa narrow(org.omg.CORBA.Object that)
|
||||
throws org.omg.CORBA.BAD_PARAM {
|
||||
if (that == null)
|
||||
return null;
|
||||
if (that instanceof EuropaAI.Europa)
|
||||
return (EuropaAI.Europa) that;
|
||||
if (!that._is_a(id())) {
|
||||
throw new org.omg.CORBA.BAD_PARAM();
|
||||
}
|
||||
org.omg.CORBA.portable.Delegate dup = ((org.omg.CORBA.portable.ObjectImpl)that)._get_delegate();
|
||||
EuropaAI.Europa result = new EuropaAI._EuropaStub(dup);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
BIN
dll/europa/corba/EuropaAI/EuropaHolder.class
Normal file
BIN
dll/europa/corba/EuropaAI/EuropaHolder.class
Normal file
Binary file not shown.
32
dll/europa/corba/EuropaAI/EuropaHolder.java
Normal file
32
dll/europa/corba/EuropaAI/EuropaHolder.java
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* File: ./EuropaAI/EuropaHolder.java
|
||||
* From: europa.idl
|
||||
* Date: Thu Dec 23 02:08:42 1999
|
||||
* By: idltojava Java IDL 1.2 Aug 11 1998 02:00:18
|
||||
*/
|
||||
|
||||
package EuropaAI;
|
||||
public final class EuropaHolder
|
||||
implements org.omg.CORBA.portable.Streamable{
|
||||
// instance variable
|
||||
public EuropaAI.Europa value;
|
||||
// constructors
|
||||
public EuropaHolder() {
|
||||
this(null);
|
||||
}
|
||||
public EuropaHolder(EuropaAI.Europa __arg) {
|
||||
value = __arg;
|
||||
}
|
||||
|
||||
public void _write(org.omg.CORBA.portable.OutputStream out) {
|
||||
EuropaAI.EuropaHelper.write(out, value);
|
||||
}
|
||||
|
||||
public void _read(org.omg.CORBA.portable.InputStream in) {
|
||||
value = EuropaAI.EuropaHelper.read(in);
|
||||
}
|
||||
|
||||
public org.omg.CORBA.TypeCode _type() {
|
||||
return EuropaAI.EuropaHelper.type();
|
||||
}
|
||||
}
|
||||
BIN
dll/europa/corba/EuropaAI/_EuropaImplBase.class
Normal file
BIN
dll/europa/corba/EuropaAI/_EuropaImplBase.class
Normal file
Binary file not shown.
47
dll/europa/corba/EuropaAI/_EuropaImplBase.java
Normal file
47
dll/europa/corba/EuropaAI/_EuropaImplBase.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* File: ./EuropaAI/_EuropaImplBase.java
|
||||
* From: europa.idl
|
||||
* Date: Thu Dec 23 02:08:42 1999
|
||||
* By: idltojava Java IDL 1.2 Aug 11 1998 02:00:18
|
||||
*/
|
||||
|
||||
package EuropaAI;
|
||||
public abstract class _EuropaImplBase extends org.omg.CORBA.DynamicImplementation implements EuropaAI.Europa {
|
||||
// Constructor
|
||||
public _EuropaImplBase() {
|
||||
super();
|
||||
}
|
||||
// Type strings for this class and its superclases
|
||||
private static final String _type_ids[] = {
|
||||
"IDL:EuropaAI/Europa:1.0"
|
||||
};
|
||||
|
||||
public String[] _ids() { return (String[]) _type_ids.clone(); }
|
||||
|
||||
private static java.util.Dictionary _methods = new java.util.Hashtable();
|
||||
static {
|
||||
_methods.put("inputChat", new java.lang.Integer(0));
|
||||
}
|
||||
// DSI Dispatch call
|
||||
public void invoke(org.omg.CORBA.ServerRequest r) {
|
||||
switch (((java.lang.Integer) _methods.get(r.op_name())).intValue()) {
|
||||
case 0: // EuropaAI.Europa.inputChat
|
||||
{
|
||||
org.omg.CORBA.NVList _list = _orb().create_list(0);
|
||||
org.omg.CORBA.Any _text = _orb().create_any();
|
||||
_text.type(org.omg.CORBA.ORB.init().get_primitive_tc(org.omg.CORBA.TCKind.tk_string));
|
||||
_list.add_value("text", _text, org.omg.CORBA.ARG_IN.value);
|
||||
r.params(_list);
|
||||
String text;
|
||||
text = _text.extract_string();
|
||||
this.inputChat(text);
|
||||
org.omg.CORBA.Any __return = _orb().create_any();
|
||||
__return.type(_orb().get_primitive_tc(org.omg.CORBA.TCKind.tk_void));
|
||||
r.result(__return);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
dll/europa/corba/EuropaAI/_EuropaStub.class
Normal file
BIN
dll/europa/corba/EuropaAI/_EuropaStub.class
Normal file
Binary file not shown.
34
dll/europa/corba/EuropaAI/_EuropaStub.java
Normal file
34
dll/europa/corba/EuropaAI/_EuropaStub.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* File: ./EuropaAI/_EuropaStub.java
|
||||
* From: europa.idl
|
||||
* Date: Thu Dec 23 02:08:42 1999
|
||||
* By: idltojava Java IDL 1.2 Aug 11 1998 02:00:18
|
||||
*/
|
||||
|
||||
package EuropaAI;
|
||||
public class _EuropaStub
|
||||
extends org.omg.CORBA.portable.ObjectImpl
|
||||
implements EuropaAI.Europa {
|
||||
|
||||
public _EuropaStub(org.omg.CORBA.portable.Delegate d) {
|
||||
super();
|
||||
_set_delegate(d);
|
||||
}
|
||||
|
||||
private static final String _type_ids[] = {
|
||||
"IDL:EuropaAI/Europa:1.0"
|
||||
};
|
||||
|
||||
public String[] _ids() { return (String[]) _type_ids.clone(); }
|
||||
|
||||
// IDL operations
|
||||
// Implementation of ::EuropaAI::Europa::inputChat
|
||||
public void inputChat(String text)
|
||||
{
|
||||
org.omg.CORBA.Request r = _request("inputChat");
|
||||
org.omg.CORBA.Any _text = r.add_in_arg();
|
||||
_text.insert_string(text);
|
||||
r.invoke();
|
||||
}
|
||||
|
||||
};
|
||||
BIN
dll/europa/corba/EuropaServant.class
Normal file
BIN
dll/europa/corba/EuropaServant.class
Normal file
Binary file not shown.
BIN
dll/europa/corba/ai-client
Executable file
BIN
dll/europa/corba/ai-client
Executable file
Binary file not shown.
BIN
dll/europa/corba/ai.class
Normal file
BIN
dll/europa/corba/ai.class
Normal file
Binary file not shown.
1
dll/europa/corba/ai.ior
Normal file
1
dll/europa/corba/ai.ior
Normal file
@@ -0,0 +1 @@
|
||||
IOR:000000000000001849444c3a4575726f706141492f4575726f70613a312e300000000001000000000000003c00010000000000136b39737075642e6c6f63616c646f6d61696e000005d7000000000018afabcafe00000002064257a4000000080000000000000000
|
||||
38
dll/europa/corba/ai.java
Normal file
38
dll/europa/corba/ai.java
Normal file
@@ -0,0 +1,38 @@
|
||||
import java.io.*;
|
||||
import org.omg.CORBA.*;
|
||||
import EuropaAI.*;
|
||||
|
||||
class EuropaServant extends _EuropaImplBase {
|
||||
public void inputChat(String text) {
|
||||
System.out.println(text);
|
||||
}
|
||||
}
|
||||
|
||||
public class ai {
|
||||
public static void main(String args[]) {
|
||||
try {
|
||||
ORB orb = ORB.init(args, null);
|
||||
|
||||
// create the servant and register it
|
||||
EuropaServant europaRef = new EuropaServant();
|
||||
orb.connect(europaRef);
|
||||
|
||||
// stringify the europaRef and dump to an ior file
|
||||
String str = orb.object_to_string(europaRef);
|
||||
FileOutputStream fos = new FileOutputStream("ai.ior");
|
||||
PrintStream ps = new PrintStream(fos);
|
||||
ps.print(str);
|
||||
ps.close();
|
||||
|
||||
// wait for invocations from clients
|
||||
java.lang.Object sync = new java.lang.Object();
|
||||
synchronized (sync) {
|
||||
sync.wait();
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error: " + e);
|
||||
e.printStackTrace(System.out);
|
||||
}
|
||||
}
|
||||
}
|
||||
5
dll/europa/corba/europa.idl
Normal file
5
dll/europa/corba/europa.idl
Normal file
@@ -0,0 +1,5 @@
|
||||
module EuropaAI {
|
||||
interface Europa {
|
||||
void inputChat(in string text);
|
||||
};
|
||||
};
|
||||
81
dll/europa/corba/orbit/ai-client.c
Normal file
81
dll/europa/corba/orbit/ai-client.c
Normal file
@@ -0,0 +1,81 @@
|
||||
#include <stdio.h>
|
||||
#include <orb/orbit.h>
|
||||
|
||||
#include "europa.h"
|
||||
|
||||
EuropaAI_Europa ai_client;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
CORBA_Environment ev;
|
||||
CORBA_ORB orb;
|
||||
FILE *ifp;
|
||||
char *ior;
|
||||
char filebuffer[1024];
|
||||
|
||||
/*
|
||||
* Standard initalisation of the orb. Notice that
|
||||
* ORB_init 'eats' stuff off the command line
|
||||
*/
|
||||
|
||||
CORBA_exception_init(&ev);
|
||||
orb = CORBA_ORB_init(&argc, argv, "orbit-local-orb", &ev);
|
||||
|
||||
/*
|
||||
* Get the IOR (object reference). It should be written out
|
||||
* by the echo-server into the file echo.ior. So - if you
|
||||
* are running the server in the same place as the client,
|
||||
* this should be fine!
|
||||
*/
|
||||
|
||||
ifp = fopen("ai.ior","r");
|
||||
if( ifp == NULL ) {
|
||||
g_error("No ai.ior file!");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
fgets(filebuffer,1024,ifp);
|
||||
ior = g_strdup(filebuffer);
|
||||
|
||||
fclose(ifp);
|
||||
|
||||
/*
|
||||
* Actually get the object. So easy!
|
||||
*/
|
||||
ai_client = CORBA_ORB_string_to_object(orb, ior, &ev);
|
||||
if(!ai_client) {
|
||||
printf("Cannot bind to %s\n", ior);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ok. Now we use the echo object...
|
||||
*/
|
||||
printf("Type messages to the server\n. as the only thing on the line stops\n
|
||||
");
|
||||
while( fgets(filebuffer,1024,stdin) ) {
|
||||
if( filebuffer[0] == '.' && filebuffer[1] == '\n' )
|
||||
break;
|
||||
|
||||
/* chop the newline off */
|
||||
filebuffer[strlen(filebuffer)-1] = '\0';
|
||||
|
||||
/* using the echoString method in the Echo object */
|
||||
/* this is defined in the echo.h header, compiled from echo.idl */
|
||||
|
||||
EuropaAI_Europa_inputChat(ai_client, filebuffer, &ev);
|
||||
|
||||
/* catch any exceptions (eg, network is down) */
|
||||
|
||||
if(ev._major != CORBA_NO_EXCEPTION) {
|
||||
printf("we got exception %d from inputChat!\n", ev._major);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Clean up */
|
||||
CORBA_Object_release(ai_client, &ev);
|
||||
CORBA_Object_release((CORBA_Object)orb, &ev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
23
dll/europa/corba/orbit/europa-common.c
Normal file
23
dll/europa/corba/orbit/europa-common.c
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* This file was generated by orbit-idl - DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "europa.h"
|
||||
|
||||
#if (TC_IMPL_TC_EuropaAI_Europa == ORBIT_FILE_ID_europa) && !defined(TC_DEF_TC_EuropaAI_Europa)
|
||||
#define TC_DEF_TC_EuropaAI_Europa 1
|
||||
const struct CORBA_TypeCode_struct TC_EuropaAI_Europa_struct = {
|
||||
|
||||
{{(ORBit_RootObject_Interface *) & ORBit_TypeCode_epv, TRUE, -1},
|
||||
ORBIT_PSEUDO_TYPECODE},
|
||||
|
||||
CORBA_tk_objref, "Europa", "IDL:EuropaAI/Europa:1.0",
|
||||
0, 0,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
CORBA_OBJECT_NIL, 0, -1, 0, 0
|
||||
};
|
||||
#endif
|
||||
CORBA_unsigned_long EuropaAI_Europa__classid = 0;
|
||||
104
dll/europa/corba/orbit/europa-skels.c
Normal file
104
dll/europa/corba/orbit/europa-skels.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* This file was generated by orbit-idl - DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "europa.h"
|
||||
|
||||
void
|
||||
_ORBIT_skel_EuropaAI_Europa_inputChat(POA_EuropaAI_Europa * _ORBIT_servant,
|
||||
GIOPRecvBuffer * _ORBIT_recv_buffer,
|
||||
CORBA_Environment * ev,
|
||||
void (*_impl_inputChat)
|
||||
(PortableServer_Servant _servant,
|
||||
CORBA_char * text,
|
||||
CORBA_Environment * ev))
|
||||
{
|
||||
CORBA_char *text;
|
||||
|
||||
{ /* demarshalling */
|
||||
guchar *_ORBIT_curptr;
|
||||
register CORBA_unsigned_long _ORBIT_tmpvar_2;
|
||||
CORBA_unsigned_long _ORBIT_tmpvar_3;
|
||||
|
||||
_ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
|
||||
if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
|
||||
_ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
|
||||
_ORBIT_tmpvar_3 =
|
||||
(CORBA_unsigned_long)
|
||||
GUINT32_SWAP_LE_BE(*((guint32 *) _ORBIT_curptr));
|
||||
_ORBIT_curptr += 4;
|
||||
text = (void *) _ORBIT_curptr;
|
||||
_ORBIT_curptr += sizeof(text[_ORBIT_tmpvar_2]) * _ORBIT_tmpvar_3;
|
||||
} else {
|
||||
_ORBIT_curptr = ALIGN_ADDRESS(_ORBIT_curptr, 4);
|
||||
_ORBIT_tmpvar_3 = *((CORBA_unsigned_long *) _ORBIT_curptr);
|
||||
_ORBIT_curptr += 4;
|
||||
text = (void *) _ORBIT_curptr;
|
||||
_ORBIT_curptr += sizeof(text[_ORBIT_tmpvar_2]) * _ORBIT_tmpvar_3;
|
||||
}
|
||||
}
|
||||
_impl_inputChat(_ORBIT_servant, text, ev);
|
||||
{ /* marshalling */
|
||||
register GIOPSendBuffer *_ORBIT_send_buffer;
|
||||
|
||||
_ORBIT_send_buffer =
|
||||
giop_send_reply_buffer_use(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer)->
|
||||
connection, NULL,
|
||||
_ORBIT_recv_buffer->message.u.request.
|
||||
request_id, ev->_major);
|
||||
if (ev->_major == CORBA_NO_EXCEPTION) {
|
||||
} else
|
||||
ORBit_send_system_exception(_ORBIT_send_buffer, ev);
|
||||
giop_send_buffer_write(_ORBIT_send_buffer);
|
||||
giop_send_buffer_unuse(_ORBIT_send_buffer);
|
||||
}
|
||||
}
|
||||
static ORBitSkeleton
|
||||
get_skel_EuropaAI_Europa(POA_EuropaAI_Europa * servant,
|
||||
GIOPRecvBuffer * _ORBIT_recv_buffer, gpointer * impl)
|
||||
{
|
||||
gchar *opname = _ORBIT_recv_buffer->message.u.request.operation;
|
||||
|
||||
switch (opname[0]) {
|
||||
case 'i':
|
||||
if (strcmp((opname + 1), "nputChat"))
|
||||
break;
|
||||
*impl = (gpointer) servant->vepv->EuropaAI_Europa_epv->inputChat;
|
||||
return (ORBitSkeleton) _ORBIT_skel_EuropaAI_Europa_inputChat;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
init_local_objref_EuropaAI_Europa(CORBA_Object obj,
|
||||
POA_EuropaAI_Europa * servant)
|
||||
{
|
||||
obj->vepv[EuropaAI_Europa__classid] = servant->vepv->EuropaAI_Europa_epv;
|
||||
}
|
||||
void
|
||||
POA_EuropaAI_Europa__init(PortableServer_Servant servant,
|
||||
CORBA_Environment * env)
|
||||
{
|
||||
static const PortableServer_ClassInfo class_info =
|
||||
{ (ORBit_impl_finder) & get_skel_EuropaAI_Europa,
|
||||
"IDL:EuropaAI/Europa:1.0",
|
||||
(ORBit_local_objref_init) & init_local_objref_EuropaAI_Europa };
|
||||
|
||||
PortableServer_ServantBase__init(((PortableServer_ServantBase *) servant),
|
||||
env);
|
||||
ORBIT_OBJECT_KEY(((PortableServer_ServantBase *) servant)->_private)->
|
||||
class_info = (PortableServer_ClassInfo *) & class_info;
|
||||
if (!EuropaAI_Europa__classid)
|
||||
EuropaAI_Europa__classid = ORBit_register_class(&class_info);
|
||||
}
|
||||
|
||||
void
|
||||
POA_EuropaAI_Europa__fini(PortableServer_Servant servant,
|
||||
CORBA_Environment * env)
|
||||
{
|
||||
PortableServer_ServantBase__fini(servant, env);
|
||||
}
|
||||
114
dll/europa/corba/orbit/europa-stubs.c
Normal file
114
dll/europa/corba/orbit/europa-stubs.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* This file was generated by orbit-idl - DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "europa.h"
|
||||
|
||||
void
|
||||
EuropaAI_Europa_inputChat(EuropaAI_Europa _obj, CORBA_char * text,
|
||||
CORBA_Environment * ev)
|
||||
{
|
||||
register GIOP_unsigned_long _ORBIT_request_id,
|
||||
_ORBIT_system_exception_minor;
|
||||
register CORBA_completion_status _ORBIT_completion_status;
|
||||
register GIOPSendBuffer *_ORBIT_send_buffer;
|
||||
register GIOPRecvBuffer *_ORBIT_recv_buffer;
|
||||
register GIOPConnection *_cnx;
|
||||
|
||||
if (_obj->servant && _obj->vepv && EuropaAI_Europa__classid) {
|
||||
|
||||
((POA_EuropaAI_Europa__epv *) _obj->vepv[EuropaAI_Europa__classid])->
|
||||
inputChat(_obj->servant, text, ev);
|
||||
return;
|
||||
}
|
||||
_cnx = ORBit_object_get_connection(_obj);
|
||||
_ORBIT_retry_request:
|
||||
_ORBIT_send_buffer = NULL;
|
||||
_ORBIT_recv_buffer = NULL;
|
||||
_ORBIT_completion_status = CORBA_COMPLETED_NO;
|
||||
_ORBIT_request_id = GPOINTER_TO_UINT(alloca(0));
|
||||
{ /* marshalling */
|
||||
static const struct
|
||||
{
|
||||
CORBA_unsigned_long len;
|
||||
char opname[10];
|
||||
}
|
||||
_ORBIT_operation_name_data =
|
||||
{
|
||||
10, "inputChat"};
|
||||
static const struct iovec _ORBIT_operation_vec =
|
||||
{ (gpointer) & _ORBIT_operation_name_data, 14 };
|
||||
register CORBA_unsigned_long _ORBIT_tmpvar_0;
|
||||
CORBA_unsigned_long _ORBIT_tmpvar_1;
|
||||
|
||||
_ORBIT_send_buffer =
|
||||
giop_send_request_buffer_use(_cnx, NULL, _ORBIT_request_id,
|
||||
CORBA_TRUE,
|
||||
&(_obj->active_profile->object_key_vec),
|
||||
&_ORBIT_operation_vec,
|
||||
&ORBit_default_principal_iovec);
|
||||
|
||||
_ORBIT_system_exception_minor = ex_CORBA_COMM_FAILURE;
|
||||
if (!_ORBIT_send_buffer)
|
||||
goto _ORBIT_system_exception;
|
||||
_ORBIT_tmpvar_1 = strlen(text) + 1;
|
||||
giop_message_buffer_do_alignment(GIOP_MESSAGE_BUFFER
|
||||
(_ORBIT_send_buffer), 4);
|
||||
{
|
||||
guchar *_ORBIT_t;
|
||||
|
||||
_ORBIT_t = alloca(sizeof(_ORBIT_tmpvar_1));
|
||||
memcpy(_ORBIT_t, &(_ORBIT_tmpvar_1), sizeof(_ORBIT_tmpvar_1));
|
||||
giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER
|
||||
(_ORBIT_send_buffer), (_ORBIT_t),
|
||||
sizeof(_ORBIT_tmpvar_1));
|
||||
}
|
||||
giop_message_buffer_append_mem(GIOP_MESSAGE_BUFFER(_ORBIT_send_buffer),
|
||||
(text),
|
||||
sizeof(text[_ORBIT_tmpvar_0]) *
|
||||
_ORBIT_tmpvar_1);
|
||||
giop_send_buffer_write(_ORBIT_send_buffer);
|
||||
_ORBIT_completion_status = CORBA_COMPLETED_MAYBE;
|
||||
giop_send_buffer_unuse(_ORBIT_send_buffer);
|
||||
_ORBIT_send_buffer = NULL;
|
||||
}
|
||||
{ /* demarshalling */
|
||||
register guchar *_ORBIT_curptr;
|
||||
|
||||
_ORBIT_recv_buffer =
|
||||
giop_recv_reply_buffer_use_2(_cnx, _ORBIT_request_id, TRUE);
|
||||
if (!_ORBIT_recv_buffer)
|
||||
goto _ORBIT_system_exception;
|
||||
_ORBIT_completion_status = CORBA_COMPLETED_YES;
|
||||
if (_ORBIT_recv_buffer->message.u.reply.reply_status !=
|
||||
GIOP_NO_EXCEPTION) goto _ORBIT_msg_exception;
|
||||
_ORBIT_curptr = GIOP_RECV_BUFFER(_ORBIT_recv_buffer)->cur;
|
||||
if (giop_msg_conversion_needed(GIOP_MESSAGE_BUFFER(_ORBIT_recv_buffer))) {
|
||||
} else {
|
||||
}
|
||||
giop_recv_buffer_unuse(_ORBIT_recv_buffer);
|
||||
return;
|
||||
_ORBIT_system_exception:
|
||||
CORBA_exception_set_system(ev, _ORBIT_system_exception_minor,
|
||||
_ORBIT_completion_status);
|
||||
giop_recv_buffer_unuse(_ORBIT_recv_buffer);
|
||||
giop_send_buffer_unuse(_ORBIT_send_buffer);
|
||||
return;
|
||||
_ORBIT_msg_exception:
|
||||
if (_ORBIT_recv_buffer->message.u.reply.reply_status ==
|
||||
GIOP_LOCATION_FORWARD) {
|
||||
if (_obj->forward_locations != NULL)
|
||||
ORBit_delete_profiles(_obj->forward_locations);
|
||||
_obj->forward_locations = ORBit_demarshal_IOR(_ORBIT_recv_buffer);
|
||||
_cnx = ORBit_object_get_forwarded_connection(_obj);
|
||||
giop_recv_buffer_unuse(_ORBIT_recv_buffer);
|
||||
|
||||
goto _ORBIT_retry_request;
|
||||
} else {
|
||||
ORBit_handle_exception(_ORBIT_recv_buffer, ev, NULL, _obj->orb);
|
||||
giop_recv_buffer_unuse(_ORBIT_recv_buffer);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
68
dll/europa/corba/orbit/europa.h
Normal file
68
dll/europa/corba/orbit/europa.h
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* This file was generated by orbit-idl - DO NOT EDIT!
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#define ORBIT_IDL_SERIAL 9
|
||||
#include <orb/orbit.h>
|
||||
|
||||
#ifndef europa_H
|
||||
#define europa_H 1
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/** typedefs **/
|
||||
#if !defined(ORBIT_DECL_EuropaAI_Europa) && !defined(_EuropaAI_Europa_defined)
|
||||
#define ORBIT_DECL_EuropaAI_Europa 1
|
||||
#define _EuropaAI_Europa_defined 1
|
||||
#define EuropaAI_Europa__free CORBA_Object__free
|
||||
typedef CORBA_Object EuropaAI_Europa;
|
||||
extern CORBA_unsigned_long EuropaAI_Europa__classid;
|
||||
#endif
|
||||
|
||||
/** POA structures **/
|
||||
typedef struct
|
||||
{
|
||||
void *_private;
|
||||
void (*inputChat) (PortableServer_Servant _servant, CORBA_char * text,
|
||||
CORBA_Environment * ev);
|
||||
}
|
||||
POA_EuropaAI_Europa__epv;
|
||||
typedef struct
|
||||
{
|
||||
PortableServer_ServantBase__epv *_base_epv;
|
||||
POA_EuropaAI_Europa__epv *EuropaAI_Europa_epv;
|
||||
}
|
||||
POA_EuropaAI_Europa__vepv;
|
||||
typedef struct
|
||||
{
|
||||
void *_private;
|
||||
POA_EuropaAI_Europa__vepv *vepv;
|
||||
}
|
||||
POA_EuropaAI_Europa;
|
||||
extern void POA_EuropaAI_Europa__init(PortableServer_Servant servant,
|
||||
CORBA_Environment * ev);
|
||||
extern void POA_EuropaAI_Europa__fini(PortableServer_Servant servant,
|
||||
CORBA_Environment * ev);
|
||||
|
||||
/** prototypes **/
|
||||
void EuropaAI_Europa_inputChat(EuropaAI_Europa _obj, CORBA_char * text,
|
||||
CORBA_Environment * ev);
|
||||
|
||||
void _ORBIT_skel_EuropaAI_Europa_inputChat(POA_EuropaAI_Europa *
|
||||
_ORBIT_servant,
|
||||
GIOPRecvBuffer *
|
||||
_ORBIT_recv_buffer,
|
||||
CORBA_Environment * ev,
|
||||
void (*_impl_inputChat)
|
||||
(PortableServer_Servant
|
||||
_servant, CORBA_char * text,
|
||||
CORBA_Environment * ev));
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
#undef ORBIT_IDL_SERIAL
|
||||
38
dll/europa/cse476/Makefile
Normal file
38
dll/europa/cse476/Makefile
Normal file
@@ -0,0 +1,38 @@
|
||||
CPP= g++ -Wall -c -g
|
||||
LINK= g++ -g
|
||||
|
||||
all: p1
|
||||
|
||||
p1: p1.o gnode.o list.o grammar.o lexicon.o parse.o
|
||||
$(LINK) p1.o parse.o grammar.o lexicon.o list.o gnode.o -o p1
|
||||
|
||||
t1: t1.o gnode.o list.o
|
||||
$(LINK) t1.o gnode.o list.o -o t1
|
||||
t1.o: t1.cpp
|
||||
$(CPP) t1.cpp
|
||||
t2: t2.o gnode.o list.o
|
||||
$(LINK) t2.o gnode.o list.o -o t2
|
||||
t2.o: t2.cpp
|
||||
$(CPP) t2.cpp
|
||||
t3: t3.o lexicon.o gnode.o list.o
|
||||
$(LINK) t3.o lexicon.o gnode.o list.o -o t3
|
||||
t3.o: t3.cpp
|
||||
$(CPP) t3.cpp
|
||||
t4: t4.o grammar.o lexicon.o gnode.o list.o
|
||||
$(LINK) t4.o grammar.o lexicon.o gnode.o list.o -o t4
|
||||
t4.o: t4.cpp
|
||||
$(CPP) t4.cpp
|
||||
p1.o: p1.cpp
|
||||
$(CPP) p1.cpp
|
||||
grammar.o: grammar.cpp
|
||||
$(CPP) grammar.cpp
|
||||
lexicon.o: lexicon.cpp
|
||||
$(CPP) lexicon.cpp
|
||||
gnode.o: gnode.cpp
|
||||
$(CPP) gnode.cpp
|
||||
list.o: list.cpp
|
||||
$(CPP) list.cpp
|
||||
parse.o: parse.cpp
|
||||
$(CPP) parse.cpp
|
||||
clean:
|
||||
rm -f core p1 t1 t2 t3 t4 *.o *~ *#
|
||||
10
dll/europa/cse476/README
Normal file
10
dll/europa/cse476/README
Normal file
@@ -0,0 +1,10 @@
|
||||
Copyright (c) 1999, Ed Schlunder <zilym@asu.edu>
|
||||
This is free software distributable under the terms of the GNU GPL.
|
||||
See COPYING for details.
|
||||
|
||||
This is some old natural language processing code I wrote for a class I
|
||||
took at ASU (CSE476 appearantly). Its not great (read: buggy and poorly
|
||||
documented) but I'm keeping it around for reference when I get around to
|
||||
writing a new NLP engine for Europa in Java.
|
||||
|
||||
|
||||
230
dll/europa/cse476/gnode.cpp
Normal file
230
dll/europa/cse476/gnode.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <string.h>
|
||||
#include "gnode.h"
|
||||
#include "list.h"
|
||||
|
||||
// takes a string and hacks off leading/trailing spaces and *'s.
|
||||
void trim(char *text) {
|
||||
int i, j, len;
|
||||
|
||||
len = strlen(text);
|
||||
|
||||
// empty strings don't need trimming...
|
||||
if(len == 0) return;
|
||||
|
||||
// find beginning of actual text
|
||||
for(i = 0; i < len; i++)
|
||||
if(text[i] != ' ') break;
|
||||
|
||||
// was there any preceeding white space to clear out?
|
||||
if(i > 0)
|
||||
for(j = 0; text[i] != 0; j++, i++)
|
||||
text[j] = text[i];
|
||||
|
||||
// step from the end backwards to see find where we need to chop
|
||||
for(j = strlen(text); j > 1; j--)
|
||||
if(text[j-1] != ' ') {
|
||||
text[j] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Implementation: genericNode
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
genericNode::genericNode(char *word, List *features) {
|
||||
if(word) {
|
||||
name = new char[strlen(word)];
|
||||
strcpy(name, word);
|
||||
}
|
||||
else
|
||||
word = NULL;
|
||||
|
||||
featureList = features;
|
||||
}
|
||||
|
||||
// Example Phrasal: ((CAT N) (AGR ?a))
|
||||
// Example Lexical: saw ((CAT N) (ROOT SAW1) (AGR 3s))
|
||||
genericNode::genericNode(char *obj) {
|
||||
unsigned int i, j;
|
||||
|
||||
// first try to read in the name field (in lexical objects)
|
||||
for(i = 0; i < strlen(obj); i++)
|
||||
if(obj[i] != ' ') break;
|
||||
|
||||
// maybe this is a phrasal object -- doesn't have a "name" field
|
||||
if(obj[i] == '(') {
|
||||
name = NULL;
|
||||
j = i;
|
||||
}
|
||||
else {
|
||||
// this is a lexical object, pick up the name:
|
||||
for(j = i; j < strlen(obj); j++)
|
||||
if(obj[j] == ' ') break;
|
||||
|
||||
name = new char[j - i + 1];
|
||||
strncpy(name, obj, j - i);
|
||||
name[j - i] = 0;
|
||||
j++;
|
||||
}
|
||||
|
||||
// pick up the object's feature list
|
||||
char *tmp = obj + j;
|
||||
// cout << "[" << tmp << "]" << endl;
|
||||
featureList = makeFeatureList(tmp);
|
||||
}
|
||||
|
||||
ostream& operator<<(ostream &out_file, genericNode const &n) {
|
||||
if(n.name == NULL)
|
||||
out_file << "(nil";
|
||||
else
|
||||
out_file << '(' << n.name;
|
||||
|
||||
if(n.featureList)
|
||||
out_file << ' ' << *n.featureList;
|
||||
|
||||
out_file << ')';
|
||||
|
||||
return out_file;
|
||||
}
|
||||
|
||||
List *unify(genericNode &s, genericNode &g) {
|
||||
List &sFeatures = *s.featureList, &gFeatures = *g.featureList, *currFeature;
|
||||
List *assignList = new List;
|
||||
char *featureName;
|
||||
List *featureValueA, *featureValueB;
|
||||
|
||||
// if a node has no feature list, then we automatically know it can unify
|
||||
if(!sFeatures.GoTop()) return new List;
|
||||
if(!gFeatures.GoTop()) return new List;
|
||||
|
||||
do {
|
||||
// get the current feature
|
||||
currFeature = sFeatures.currItemList();
|
||||
currFeature->GoTop();
|
||||
|
||||
// pull out the feature name and value
|
||||
featureName = currFeature->currItem();
|
||||
currFeature->GoNext();
|
||||
featureValueA = currFeature->currItemList();
|
||||
featureValueB = g.lookupFeature(featureName);
|
||||
|
||||
/*
|
||||
cout << "unify: [" << featureName << "] = " << *featureValueA << "";
|
||||
cout << " with " << *featureValueB << " --> ";
|
||||
*/
|
||||
|
||||
/*
|
||||
if(featureValueB == NULL)
|
||||
// if feature lookup failed, no corresponding feature exists --
|
||||
// automatically agrees...
|
||||
// cout << "yes" << endl;
|
||||
else {
|
||||
*/
|
||||
// if featureB is nothing, no corresponding featuture exists -- agrees
|
||||
if(featureValueB != NULL) {
|
||||
List *assignment = cmpFeatures(*featureValueA, *featureValueB);
|
||||
if(assignment == NULL) {
|
||||
// cout << "no" << endl;
|
||||
delete assignList;
|
||||
return NULL;
|
||||
}
|
||||
// cout << "yes: " << *assignment << endl;
|
||||
if(!assignment->empty())
|
||||
assignList->InsertAfter(assignment);
|
||||
}
|
||||
} while(sFeatures.GoNext());
|
||||
// cout << "assignment list: " << *assignList << endl;
|
||||
return assignList;
|
||||
}
|
||||
|
||||
List *cmpFeatures(List &a, List &b) {
|
||||
char *valueA, *valueB;
|
||||
a.GoTop();
|
||||
|
||||
do {
|
||||
valueA = a.currItem();
|
||||
|
||||
b.GoTop();
|
||||
do {
|
||||
valueB = b.currItem();
|
||||
|
||||
// do we have a match?
|
||||
if(strcmp(valueA, valueB) == 0)
|
||||
return new List;
|
||||
|
||||
// if one of the values is a variable, then it can match anything
|
||||
if(valueA[0] == '?') {
|
||||
List *assignList = new List;
|
||||
assignList->InsertAfter(valueA);
|
||||
assignList->InsertAfter(&b);
|
||||
|
||||
return assignList;
|
||||
}
|
||||
|
||||
if(valueB[0] == '?') {
|
||||
List *assignList = new List;
|
||||
assignList->InsertAfter(valueB);
|
||||
assignList->InsertAfter(&a);
|
||||
|
||||
return assignList;
|
||||
}
|
||||
} while(b.GoNext());
|
||||
} while(a.GoNext());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *genericNode::lookupFeature(const char *name) const {
|
||||
char *tmp;
|
||||
List *featureSeek;
|
||||
|
||||
// if this node has no features, abort search
|
||||
if(featureList == NULL) return NULL;
|
||||
|
||||
featureList->GoTop();
|
||||
do {
|
||||
// pick up current feature
|
||||
featureSeek = featureList->currItemList();
|
||||
featureSeek->GoTop();
|
||||
|
||||
// pick up current feature's name
|
||||
tmp = featureSeek->currItem();
|
||||
|
||||
// is this the feature we were trying to find?
|
||||
if(strcmp(tmp, name) == 0) {
|
||||
// found our feature, pick up the value
|
||||
featureSeek->GoNext();
|
||||
return featureSeek->currItemList();
|
||||
}
|
||||
} while(featureList->GoNext());
|
||||
|
||||
// exhausted the feature list, this feature doesn't exist in this genericNode
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *genericNode::word(void) {
|
||||
return name;
|
||||
}
|
||||
|
||||
genericNode::~genericNode() {
|
||||
// -----------------------
|
||||
// THIS NEEDS IMPLEMENTING
|
||||
// -----------------------
|
||||
delete name;
|
||||
delete featureList;
|
||||
}
|
||||
|
||||
List *genericNode::features(void) {
|
||||
return featureList;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
genericNode *substitute(genericNode *old, List *assign) {
|
||||
genericNode *subst;
|
||||
|
||||
subst = new genericNode(old->name, substitute(old->featureList, assign));
|
||||
return subst;
|
||||
}
|
||||
36
dll/europa/cse476/gnode.h
Normal file
36
dll/europa/cse476/gnode.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef _GNODE_H_
|
||||
#define _GNODE_H_
|
||||
|
||||
#include <iostream.h>
|
||||
|
||||
class List;
|
||||
|
||||
void trim(char *text); // GOOD
|
||||
|
||||
// genericNode -- holds any lexical or phrase object
|
||||
class genericNode {
|
||||
public:
|
||||
// constructor: pass it a string containing a lexical or phrase
|
||||
// object in the format used in our lexicon.txt and grammar.txt
|
||||
genericNode(char *obj); // GOOD
|
||||
genericNode(char *word, List *features); // GOOD except feature doesn't copy
|
||||
~genericNode();
|
||||
|
||||
friend ostream &operator<<(ostream &out_file, const genericNode &n); // GOOD
|
||||
|
||||
// GOOD: sort of.. this routine leaks memory because the lists for
|
||||
// assignment it makes aren't properly deallocated upon unification failure
|
||||
friend List *unify(genericNode &s, genericNode &g);
|
||||
friend List *cmpFeatures(List &a, List &b);
|
||||
List *lookupFeature(const char *name) const;
|
||||
friend genericNode *substitute(genericNode *old, List *assign);
|
||||
|
||||
char *word(void); // GOOD
|
||||
List *features(void);
|
||||
|
||||
private:
|
||||
char *name;
|
||||
List *featureList;
|
||||
};
|
||||
|
||||
#endif
|
||||
143
dll/europa/cse476/grammar.cpp
Normal file
143
dll/europa/cse476/grammar.cpp
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <fstream.h>
|
||||
#include <iostream.h>
|
||||
#include <string.h>
|
||||
#include "grammar.h"
|
||||
#include "gnode.h"
|
||||
|
||||
Grammar::Grammar(char *fileName) {
|
||||
char buffer[1000];
|
||||
ifstream inFile;
|
||||
|
||||
// specify that this is currently an empty grammar rule list
|
||||
rootPtr = currPtr = NULL;
|
||||
|
||||
// try to open the grammar rules file
|
||||
inFile.open(fileName);
|
||||
if(!inFile) {
|
||||
cout << "Grammar rules file can not be opened." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
while(inFile) {
|
||||
inFile.getline(buffer, 999);
|
||||
|
||||
// ignore blank lines
|
||||
if(strlen(buffer) < 2) continue;
|
||||
trim(buffer);
|
||||
insert(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Grammar::insert(char *text) {
|
||||
List *ruleLine = new List;
|
||||
genericNode *obj;
|
||||
char *tmp;
|
||||
int length, level, beg, end;
|
||||
|
||||
length = strlen(text);
|
||||
end = -1;
|
||||
while(end < length) {
|
||||
beg = end + 1;
|
||||
|
||||
// locate opening parenthesis
|
||||
while(beg < length)
|
||||
if(text[beg] == '(') break;
|
||||
else beg++;
|
||||
|
||||
for(level = 0, end = beg + 1; end < length; end++) {
|
||||
if((text[end] == ')') && (level == 0)) break;
|
||||
|
||||
// make sure that items encased within () are kept intact
|
||||
if(text[end] == '(') level++;
|
||||
if(text[end] == ')') level--;
|
||||
}
|
||||
|
||||
end++;
|
||||
tmp = new char[end - beg + 1];
|
||||
strncpy(tmp, text + beg, end - beg);
|
||||
tmp[end - beg] = 0;
|
||||
|
||||
if(strlen(tmp) == 0)
|
||||
break;
|
||||
|
||||
// make a genericNode out of this phrasal object and add it to the ruleLine
|
||||
// cout << '[' << tmp << ']' << endl;
|
||||
obj = new genericNode(tmp);
|
||||
ruleLine->InsertAfter(obj);
|
||||
}
|
||||
|
||||
insert(ruleLine);
|
||||
}
|
||||
|
||||
void Grammar::insert(List *ruleLine) {
|
||||
grammarLine *tmp;
|
||||
|
||||
// cout << "grammarInsert: " << *ruleLine << endl;
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new grammarLine;
|
||||
rootPtr->line = ruleLine;
|
||||
rootPtr->nextPtr = NULL;
|
||||
}
|
||||
else {
|
||||
// find end of list
|
||||
tmp = rootPtr;
|
||||
while(tmp->nextPtr != NULL)
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
// tack a new rule on the end of the list
|
||||
tmp->nextPtr = new grammarLine;
|
||||
tmp = tmp->nextPtr;
|
||||
tmp->line = ruleLine;
|
||||
tmp->nextPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Grammar::~Grammar() {
|
||||
|
||||
}
|
||||
|
||||
List *Grammar::currLine(void) {
|
||||
return currPtr->line;
|
||||
}
|
||||
|
||||
void Grammar::goTop(void) {
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
|
||||
bool Grammar::goNext(void) {
|
||||
if(currPtr)
|
||||
if(currPtr->nextPtr) {
|
||||
currPtr = currPtr->nextPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
List *Grammar::findMatch(genericNode *obj) {
|
||||
searchObj = obj;
|
||||
currPtr = rootPtr;
|
||||
|
||||
return findNext();
|
||||
}
|
||||
|
||||
List *Grammar::findNext(void) {
|
||||
List *assign, *currLine;
|
||||
|
||||
// go through each rule in the grammar and try to match it with the given obj
|
||||
while(currPtr) {
|
||||
currLine = currPtr->line;
|
||||
currLine->GoTop();
|
||||
currLine->GoNext();
|
||||
assign = unify(*currLine->currItemNode(), *searchObj);
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
|
||||
if(assign)
|
||||
return substitute(currLine, assign);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
34
dll/europa/cse476/grammar.h
Normal file
34
dll/europa/cse476/grammar.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _GRAMMAR_H_
|
||||
#define _GRAMMAR_H_
|
||||
|
||||
#include "list.h"
|
||||
#include "gnode.h"
|
||||
|
||||
class Grammar {
|
||||
public:
|
||||
Grammar(char *fileName); // GOOD
|
||||
~Grammar();
|
||||
List *currLine(void);
|
||||
|
||||
List *findMatch(genericNode *obj);
|
||||
List *findNext(void);
|
||||
|
||||
void goTop(void);
|
||||
bool goNext(void);
|
||||
|
||||
private:
|
||||
struct grammarLine;
|
||||
typedef struct grammarLine {
|
||||
List *line;
|
||||
grammarLine *nextPtr;
|
||||
};
|
||||
|
||||
void insert(char *text); // GOOD
|
||||
void insert(List *ruleLine); // GOOD
|
||||
|
||||
grammarLine *rootPtr;
|
||||
grammarLine *currPtr;
|
||||
genericNode *searchObj;
|
||||
};
|
||||
|
||||
#endif
|
||||
12
dll/europa/cse476/grammar.txt
Normal file
12
dll/europa/cse476/grammar.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
((CAT (S)) (INV (-)) (VFORM (?v (pres past))) (AGR (?a))) -> ((CAT (NP)) (AGR (?a))) ((CAT (VP)) (VFORM (?v (pres past))) (AGR (?a)))
|
||||
((CAT (NP)) (AGR (?a))) -> ((CAT (ART)) (AGR (?a))) ((CAT (N)) (AGR (?a)))
|
||||
((CAT (NP)) (AGR (?a))) -> ((CAT (PRO)) (AGR (?a)))
|
||||
((CAT (NP)) (AGR (?a))) -> ((CAT (NAME)) (AGR (?a)))
|
||||
((CAT (VP)) (AGR (?a)) (VFORM (?v))) -> ((CAT (V)) (SUBCAT (_none)) (AGR (?a)) (VFORM (?v)))
|
||||
((CAT (VP)) (AGR (?a)) (VFORM (?v))) -> ((CAT (V)) (SUBCAT (_np)) (AGR (?a)) (VFORM (?v))) ((CAT (NP)))
|
||||
((CAT (VP)) (AGR (?a)) (VFORM (?v))) -> ((CAT (V)) (SUBCAT (_vp:inf)) (AGR (?a)) (VFORM (?v))) ((CAT (VP)) (VFORM (inf)))
|
||||
((CAT (VP)) (AGR (?a)) (VFORM (?v))) -> ((CAT (V)) (SUBCAT (_np_vp:inf)) (AGR (?a)) (VFORM (?v))) ((CAT (NP))) ((CAT (VP)) (VFORM (inf)))
|
||||
((CAT (VP)) (AGR (?a)) (VFORM (?v))) -> ((CAT (V)) (SUBCAT (_adjp)) (AGR (?a)) (VFORM (?v))) ((CAT (ADJP)))
|
||||
((CAT (VP)) (SUBCAT (inf)) (AGR (?a)) (VFORM (inf))) -> ((CAT (TO))) ((CAT (VP)) (VFORM (base)))
|
||||
((CAT (ADJP))) -> ((CAT (ADJ)))
|
||||
((CAT (ADJP))) -> ((CAT (ADJ)) (SUBCAT (_vp:inf))) ((CAT (VP)) (VFORM (inf)))
|
||||
121
dll/europa/cse476/lexicon.cpp
Normal file
121
dll/europa/cse476/lexicon.cpp
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include "lexicon.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Implementation: Lexicon
|
||||
// ---------------------------------------------------------------------------
|
||||
Lexicon::Lexicon(char *fileName) {
|
||||
char buffer[1000];
|
||||
ifstream inFile;
|
||||
|
||||
// specify that this is an empty lexicon currently
|
||||
rootPtr = currPtr = NULL;
|
||||
|
||||
// try to open the lexicon file
|
||||
inFile.open(fileName);
|
||||
if(!inFile) {
|
||||
cout << "Lexicon file can not be opened." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// read in each lexicon entry and insert it into our BST
|
||||
while(inFile) {
|
||||
inFile.getline(buffer, 999);
|
||||
|
||||
// ignore blank lines
|
||||
if(strlen(buffer) < 2) continue;
|
||||
|
||||
insert(new genericNode(buffer));
|
||||
}
|
||||
}
|
||||
|
||||
void Lexicon::insert(genericNode *newWord) {
|
||||
#ifdef DEBUG
|
||||
cout << "insertLexicon: [" << *newWord << "]" << endl;
|
||||
#endif
|
||||
|
||||
// if this is an empty lexicon, insert at the top of the BST
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new lexicalNode;
|
||||
rootPtr->node = newWord;
|
||||
rootPtr->leftPtr = NULL;
|
||||
rootPtr->rightPtr = NULL;
|
||||
}
|
||||
else
|
||||
insert(newWord, rootPtr);
|
||||
}
|
||||
|
||||
void Lexicon::insert(genericNode *newWord, lexicalNode *root) {
|
||||
lexicalNode *tmp;
|
||||
|
||||
// does newWord belong to the right of this node?
|
||||
if(strcmp(root->node->word(), newWord->word()) > 0)
|
||||
// ASSERT: newWord belongs to the right of this word
|
||||
if(root->rightPtr) {
|
||||
// nodes already exist to the right, follow link down and try again
|
||||
insert(newWord, root->rightPtr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
// make a new node to the right
|
||||
tmp = root->rightPtr = new lexicalNode;
|
||||
else
|
||||
if(root->leftPtr) {
|
||||
insert(newWord, root->leftPtr);
|
||||
return;
|
||||
}
|
||||
else
|
||||
tmp = root->leftPtr = new lexicalNode;
|
||||
|
||||
tmp->node = newWord;
|
||||
tmp->leftPtr = NULL;
|
||||
tmp->rightPtr = NULL;
|
||||
}
|
||||
|
||||
Lexicon::~Lexicon() {
|
||||
// -----------------------
|
||||
// THIS NEEDS IMPLEMENTING
|
||||
// -----------------------
|
||||
}
|
||||
|
||||
genericNode *Lexicon::currNode(void) {
|
||||
if(currPtr)
|
||||
return currPtr->node;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
bool Lexicon::lookupNext(void) {
|
||||
if(currPtr->leftPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return lookupWord(currPtr->leftPtr, currPtr->node->word());
|
||||
}
|
||||
|
||||
bool Lexicon::lookupWord(char *word) {
|
||||
return lookupWord(rootPtr, word);
|
||||
}
|
||||
|
||||
bool Lexicon::lookupWord(lexicalNode *root, char *word) {
|
||||
int cmp;
|
||||
|
||||
// if we've hit a dead end, we know this word doesn't exist in the tree
|
||||
if(root == NULL) return false;
|
||||
|
||||
// is this word the one we were looking for?
|
||||
cmp = strcmp(root->node->word(), word);
|
||||
if(cmp == 0) {
|
||||
currPtr = root;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(cmp > 0)
|
||||
return lookupWord(root->rightPtr, word);
|
||||
else
|
||||
return lookupWord(root->leftPtr, word);
|
||||
}
|
||||
34
dll/europa/cse476/lexicon.h
Normal file
34
dll/europa/cse476/lexicon.h
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef _LEXICON_H_
|
||||
#define _LEXICON_H_
|
||||
|
||||
#include "gnode.h"
|
||||
#include "list.h"
|
||||
|
||||
class Lexicon {
|
||||
public:
|
||||
Lexicon(char *fileName); // GOOD
|
||||
~Lexicon();
|
||||
bool lookupWord(char *word);
|
||||
bool lookupNext(void);
|
||||
genericNode *currNode(void); // GOOD
|
||||
|
||||
private:
|
||||
struct lexicalNode;
|
||||
typedef struct lexicalNode {
|
||||
genericNode *node;
|
||||
|
||||
lexicalNode *leftPtr;
|
||||
lexicalNode *rightPtr;
|
||||
};
|
||||
|
||||
void insert(genericNode *newWord); // GOOD
|
||||
void insert(genericNode *newWord, lexicalNode *root); // GOOD
|
||||
|
||||
bool lookupWord(lexicalNode *root, char *word);
|
||||
|
||||
lexicalNode *rootPtr;
|
||||
lexicalNode *currPtr;
|
||||
List *featureSeek;
|
||||
};
|
||||
|
||||
#endif
|
||||
22
dll/europa/cse476/lexicon.txt
Normal file
22
dll/europa/cse476/lexicon.txt
Normal file
@@ -0,0 +1,22 @@
|
||||
a ((CAT (ART)) (ROOT (A1)) (AGR (3s)))
|
||||
be ((CAT (V)) (ROOT (BE1)) (VFORM (base)) (IRREG-PRES (+)) (IRREG-PAST (+)) (SUBCAT (_adjp _np)))
|
||||
cry ((CAT (V)) (ROOT (CRY1)) (VFORM (base)) (SUBCAT (_none)))
|
||||
dog ((CAT (N)) (ROOT (DOG1)) (AGR (3s)))
|
||||
fish ((CAT (N)) (ROOT (FISH1)) (AGR (3s 3p)) (IRREG-PL (+)))
|
||||
happy ((CAT (ADJ)) (SUBCAT (_vp:inf)))
|
||||
he ((CAT (PRO)) (ROOT (HE1)) (AGR (3s)))
|
||||
is ((CAT (V)) (ROOT (BE1)) (VFORM (pres)) (SUBCAT (_adjp _np)) (AGR (3s)))
|
||||
Jack ((CAT (NAME)) (AGR (3s)))
|
||||
Sally ((CAT (NAME)) (AGR (3s)))
|
||||
man ((CAT (N1)) (ROOT (MAN1)) (AGR (3s)))
|
||||
men ((CAT (N)) (ROOT (MAN1)) (AGR (3p)))
|
||||
saw ((CAT (N)) (ROOT (SAW1)) (AGR (3s)))
|
||||
saw ((CAT (V)) (ROOT (SAW2)) (VFORM (base)) (SUBCAT (_np)))
|
||||
saw ((CAT (V)) (ROOT (SEE1)) (VFORM (past)) (SUBCAT (_np)))
|
||||
see ((CAT (V)) (ROOT (SEE1)) (VFORM (base)) (SUBCAT (_np)) (IRREG-PAST (+)) (EN-PASTPRT (+)))
|
||||
seed ((CAT (N)) (ROOT (SEED1)) (AGR (3s)))
|
||||
the ((CAT (ART)) (ROOT (THE1)) (AGR (3s 3p)))
|
||||
to ((CAT (TO)))
|
||||
want ((CAT (V)) (ROOT (WANT1)) (VFORM (base)) (SUBCAT (_np _vp:inf _np_vp:inf)))
|
||||
was ((CAT (V)) (ROOT (BE1)) (VFORM (past)) (AGR (1s 3s)) (SUBCAT (_adjp _np)))
|
||||
were ((CAT (V)) (ROOT (BE)) (VFORM (past)) (AGR (2s 1p 2p 3p)) (SUBCAT (_adjp _np)))
|
||||
569
dll/europa/cse476/list.cpp
Normal file
569
dll/europa/cse476/list.cpp
Normal file
@@ -0,0 +1,569 @@
|
||||
// Copyright (c) 1998-99, Ed Schlunder
|
||||
|
||||
#include <string.h>
|
||||
#include "list.h"
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Class Implementation: List
|
||||
// ---------------------------------------------------------------------------
|
||||
List::List() {
|
||||
rootPtr = NULL;
|
||||
currPtr = NULL;
|
||||
}
|
||||
|
||||
List::~List() {
|
||||
listNode *tmpPtr = rootPtr, *nextPtr;
|
||||
|
||||
// go through the list and delete each node
|
||||
while(tmpPtr) {
|
||||
nextPtr = tmpPtr->nextPtr;
|
||||
if(tmpPtr->item)
|
||||
delete tmpPtr->item;
|
||||
if(tmpPtr->itemList)
|
||||
delete tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode)
|
||||
delete tmpPtr->itemNode;
|
||||
|
||||
delete tmpPtr;
|
||||
tmpPtr = nextPtr;
|
||||
}
|
||||
};
|
||||
|
||||
void List::InsertBefore(char *item) {
|
||||
// this version does char strings
|
||||
|
||||
if(rootPtr == NULL) {
|
||||
// creating the first node in a previously empty list.
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(rootPtr->item, item);
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
// create a new node and insert it before currPtr's node
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
newPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(newPtr->item, item);
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = NULL;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertBefore(List *item) {
|
||||
// this version does Lists
|
||||
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = item;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = item;
|
||||
newPtr->itemNode = NULL;
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertBefore(genericNode *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = item;
|
||||
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->prevPtr = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = item;
|
||||
newPtr->nextPtr = currPtr;
|
||||
newPtr->prevPtr = currPtr->prevPtr;
|
||||
|
||||
currPtr->prevPtr = newPtr;
|
||||
if(newPtr->prevPtr)
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(char *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = NULL;
|
||||
rootPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(rootPtr->item, item);
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = NULL;
|
||||
newPtr->item = new char[strlen(item) + 1];
|
||||
strcpy(newPtr->item, item);
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(List *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = item;
|
||||
rootPtr->itemNode = NULL;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = item;
|
||||
newPtr->itemNode = NULL;
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
void List::InsertAfter(genericNode *item) {
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new listNode;
|
||||
rootPtr->prevPtr = NULL;
|
||||
rootPtr->nextPtr = NULL;
|
||||
rootPtr->item = NULL;
|
||||
rootPtr->itemList = NULL;
|
||||
rootPtr->itemNode = item;
|
||||
|
||||
currPtr = rootPtr;
|
||||
}
|
||||
else {
|
||||
listNode *newPtr = new listNode;
|
||||
|
||||
newPtr->nextPtr = currPtr->nextPtr;
|
||||
newPtr->prevPtr = currPtr;
|
||||
newPtr->item = NULL;
|
||||
newPtr->itemList = NULL;
|
||||
newPtr->itemNode = item;
|
||||
|
||||
if(newPtr->nextPtr)
|
||||
newPtr->nextPtr->prevPtr = newPtr;
|
||||
newPtr->prevPtr->nextPtr = newPtr;
|
||||
|
||||
currPtr = newPtr;
|
||||
}
|
||||
}
|
||||
|
||||
bool List::GoTop(void) {
|
||||
currPtr = rootPtr;
|
||||
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoNext(void) {
|
||||
if(!currPtr)
|
||||
return false;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoPrev(void) {
|
||||
if(!currPtr)
|
||||
return false;
|
||||
|
||||
currPtr = currPtr->prevPtr;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool List::GoItem(int n) {
|
||||
if(!rootPtr) // if empty list, abort
|
||||
return false;
|
||||
|
||||
currPtr = rootPtr;
|
||||
|
||||
while(n--) { // visit each node from the root up to n nodes deep
|
||||
if(!currPtr->nextPtr)
|
||||
break;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
}
|
||||
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
char *List::currItem(void) {
|
||||
if(currPtr)
|
||||
return currPtr->item;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *List::currItemList(void) {
|
||||
if(currPtr)
|
||||
return currPtr->itemList;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
genericNode *List::currItemNode(void) {
|
||||
if(currPtr)
|
||||
return currPtr->itemNode;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void List::Print(void) {
|
||||
listNode *tmpPtr = rootPtr;
|
||||
|
||||
cout << "(";
|
||||
while(tmpPtr) {
|
||||
if(tmpPtr->item)
|
||||
cout << tmpPtr->item << " ";
|
||||
|
||||
if(tmpPtr->itemList)
|
||||
tmpPtr->itemList->Print();
|
||||
|
||||
if(tmpPtr->itemNode)
|
||||
cout << tmpPtr->itemNode;
|
||||
|
||||
tmpPtr = tmpPtr->nextPtr;
|
||||
}
|
||||
cout << "\b) ";
|
||||
}
|
||||
|
||||
|
||||
List *MakeList(char *text) {
|
||||
int length, i, j;
|
||||
char *tmp = text;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
for(i = 0; i < length; i++) {
|
||||
if(text[i] == '{' || text[i] == '(') {
|
||||
// sub-list found
|
||||
for(j = i + 1; j < length; j++)
|
||||
if(text[j] == '}' || text[j] == ')')
|
||||
break;
|
||||
|
||||
tmp = new char[j - i];
|
||||
strncpy(tmp, text + i + 1, j - i - 1);
|
||||
tmp[j - i - 1] = 0;
|
||||
|
||||
l->InsertAfter(MakeList(tmp));
|
||||
delete tmp;
|
||||
i = j + 1;
|
||||
}
|
||||
else if(text[i] != ' ' && text[i] != '\t' && text[i] != '.') {
|
||||
// item found
|
||||
for(j = i + 1; j < length; j++)
|
||||
if(text[j] == ' ' || text[j] == '\t' || text[j] == '.')
|
||||
break;
|
||||
tmp = new char[j - i + 1];
|
||||
strncpy(tmp, text + i, j - i);
|
||||
tmp[j-i] = 0;
|
||||
|
||||
l->InsertAfter(tmp);
|
||||
if(text[j] == '.')
|
||||
l->InsertAfter(".");
|
||||
delete tmp;
|
||||
i = j;
|
||||
}
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
List *MakeFeatList(char *text) {
|
||||
int length, i, j;
|
||||
char *tmp;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
for(i = 0; i < length; i++) {
|
||||
for(j = i; j < length; j++)
|
||||
if(text[j] == ' ')
|
||||
break;
|
||||
|
||||
for(j++; j < length; j++)
|
||||
if(text[j] == ' ' || text[j] == '}')
|
||||
break;
|
||||
|
||||
if(text[j+1] == '{')
|
||||
for(j++; j < length; j++)
|
||||
if(text[j] == '}') {
|
||||
j++;
|
||||
break;
|
||||
}
|
||||
|
||||
tmp = new char[j - i + 1];
|
||||
strncpy(tmp, text + i, j - i);
|
||||
tmp[j - i] = 0;
|
||||
// cout << "Mklist: [" << tmp << "]" << endl;
|
||||
l->InsertAfter(MakeList(tmp));
|
||||
delete tmp;
|
||||
|
||||
i = j;
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Creates a list of features from a string. Example string:
|
||||
// ((CAT NP) (AGR ?a))
|
||||
List *makeFeatureList(char *text) {
|
||||
int length, i, j, level, beg, end;
|
||||
char *tmp, *thisList;
|
||||
List *l = new List;
|
||||
|
||||
length = strlen(text);
|
||||
|
||||
// locate opening parenthesis
|
||||
for(i = 0; i < length; i++)
|
||||
if(text[i] == '(') break;
|
||||
|
||||
// no list given if no opening parenthesis found -- abort
|
||||
if(i == length) return NULL;
|
||||
|
||||
// get -past- the (
|
||||
i++;
|
||||
|
||||
// find end of this list
|
||||
for(level = 1, j = i+1; j < length; j++) {
|
||||
if(text[j] == ')') level--;
|
||||
if(text[j] == '(') level++;
|
||||
}
|
||||
|
||||
j--;
|
||||
|
||||
// make a new string containing a copy of the list text we want to work
|
||||
// with only...
|
||||
thisList = new char[j - i + 1];
|
||||
strncpy(thisList, text + i, j - i);
|
||||
thisList[j - i] = 0;
|
||||
trim(thisList);
|
||||
|
||||
// cout << "thisList: [" << thisList << "]" << endl;
|
||||
|
||||
// step through the list text and take out each item (*tmp)
|
||||
length = strlen(thisList);
|
||||
end = -1;
|
||||
while(end < length) {
|
||||
beg = end + 1;
|
||||
|
||||
// find the end of this item
|
||||
for(level = 0, end = beg; end < length; end++) {
|
||||
if((thisList[end] == ' ') && (level == 0))
|
||||
break;
|
||||
|
||||
// make sure that items encased within ( ) are kept as one piece
|
||||
if(thisList[end] == '(') level++;
|
||||
if(thisList[end] == ')') level--;
|
||||
}
|
||||
|
||||
// make a copy of the text just for this item
|
||||
tmp = new char[end - beg + 1];
|
||||
strncpy(tmp, thisList + beg, end - beg);
|
||||
tmp[end - beg] = 0;
|
||||
|
||||
// is this item a sub list?
|
||||
if(tmp[0] == '(')
|
||||
l->InsertAfter(makeFeatureList(tmp));
|
||||
else
|
||||
l->InsertAfter(tmp);
|
||||
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
// free up memory for temporary list string
|
||||
delete thisList;
|
||||
return l;
|
||||
}
|
||||
|
||||
ostream &operator<<(ostream &out_file, const List &l) {
|
||||
if(&l == NULL) {
|
||||
out_file << "nil";
|
||||
return out_file;
|
||||
}
|
||||
|
||||
listNode *tmpPtr = l.rootPtr;
|
||||
|
||||
// is this an empty list?
|
||||
if(tmpPtr == NULL)
|
||||
out_file << "()";
|
||||
else {
|
||||
out_file << "(";
|
||||
|
||||
// print out first item without a separating space for it
|
||||
if(tmpPtr->item) out_file << tmpPtr->item;
|
||||
if(tmpPtr->itemList) out_file << *tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode) out_file << *tmpPtr->itemNode;
|
||||
|
||||
// step through the linked list of List items and print each one...
|
||||
while((tmpPtr = tmpPtr->nextPtr)) {
|
||||
if(tmpPtr->item) out_file << ' ' << tmpPtr->item;
|
||||
if(tmpPtr->itemList) out_file << ' ' << *tmpPtr->itemList;
|
||||
if(tmpPtr->itemNode) out_file << ' ' << *tmpPtr->itemNode;
|
||||
}
|
||||
out_file << ')';
|
||||
}
|
||||
|
||||
return out_file;
|
||||
}
|
||||
|
||||
bool List::empty(void) {
|
||||
if(rootPtr == NULL)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int List::length(void) {
|
||||
listNode *tmp;
|
||||
int num;
|
||||
|
||||
// count each node in the list and return the count
|
||||
tmp = rootPtr;
|
||||
num = 0;
|
||||
while(tmp) {
|
||||
num++;
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
List *findSubst(char *var, List *assign) {
|
||||
if(assign->GoTop() == false)
|
||||
return NULL;
|
||||
|
||||
do {
|
||||
List *varSubst = assign->currItemList();
|
||||
varSubst->GoTop();
|
||||
|
||||
// is this the variable that we are trying to find?
|
||||
if(strcmp(varSubst->currItem(), var) == 0) {
|
||||
varSubst->GoNext();
|
||||
return varSubst->currItemList();
|
||||
}
|
||||
} while(assign->GoNext());
|
||||
|
||||
// couldn't find var in the variable substitution list
|
||||
return NULL;
|
||||
}
|
||||
|
||||
List *substitute(List *old, List *assign) {
|
||||
List *subst = new List;
|
||||
listNode *tmp;
|
||||
|
||||
tmp = old->rootPtr;
|
||||
while(tmp) {
|
||||
if(tmp->item) {
|
||||
// cout << "recreating item: " << tmp->item << endl;
|
||||
if(tmp->item[0] == '?') {
|
||||
// variable may need to be substituted
|
||||
List *newItem = findSubst(tmp->item, assign);
|
||||
if(newItem == NULL)
|
||||
subst->InsertAfter(tmp->item);
|
||||
else {
|
||||
newItem->GoTop();
|
||||
do {
|
||||
if(newItem->currItem())
|
||||
subst->InsertAfter(newItem->currItem());
|
||||
if(newItem->currItemList())
|
||||
subst->InsertAfter(newItem->currItemList());
|
||||
if(newItem->currItemNode())
|
||||
subst->InsertAfter(newItem->currItemNode());
|
||||
} while(newItem->GoNext());
|
||||
}
|
||||
}
|
||||
else
|
||||
// constants just stay
|
||||
subst->InsertAfter(tmp->item);
|
||||
}
|
||||
|
||||
// just call ourselves recursively for sublists
|
||||
if(tmp->itemList) {
|
||||
// cout << "recreating list: " << *tmp->itemList << endl;
|
||||
subst->InsertAfter(substitute(tmp->itemList, assign));
|
||||
}
|
||||
|
||||
if(tmp->itemNode) {
|
||||
// cout << "recreating genericNode: " << *tmp->itemNode << endl;
|
||||
subst->InsertAfter(new genericNode(NULL, substitute(tmp->itemNode->features(), assign)));
|
||||
}
|
||||
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return subst;
|
||||
}
|
||||
53
dll/europa/cse476/list.h
Normal file
53
dll/europa/cse476/list.h
Normal file
@@ -0,0 +1,53 @@
|
||||
#ifndef _LIST_H_
|
||||
#define _LIST_H_
|
||||
|
||||
#include "gnode.h"
|
||||
|
||||
struct listNode;
|
||||
typedef struct listNode {
|
||||
char *item;
|
||||
List *itemList;
|
||||
genericNode *itemNode;
|
||||
|
||||
listNode *nextPtr; // pointer to next option
|
||||
listNode *prevPtr;
|
||||
};
|
||||
|
||||
class List {
|
||||
public:
|
||||
List();
|
||||
~List();
|
||||
void InsertBefore(char *item);
|
||||
void InsertBefore(List *item);
|
||||
void InsertBefore(genericNode *item);
|
||||
void InsertAfter(char *item);
|
||||
void InsertAfter(List *item);
|
||||
void InsertAfter(genericNode *item);
|
||||
|
||||
// returns true if everything is good, false if operation failed
|
||||
bool GoTop(void); // GOOD
|
||||
bool GoNext(void); // GOOD
|
||||
bool GoPrev(void);
|
||||
bool GoItem(int n);
|
||||
bool empty(void); // GOOD
|
||||
int length(void); // GOOD
|
||||
|
||||
char *currItem(void);
|
||||
List *currItemList(void);
|
||||
genericNode *currItemNode(void);
|
||||
void Print(void);
|
||||
|
||||
friend List *MakeFeatList(char *text);
|
||||
|
||||
friend List *makeFeatureList(char *text); // GOOD
|
||||
friend ostream &operator<<(ostream &out_file, const List &l); // GOOD
|
||||
friend List *substitute(List *old, List *assign);
|
||||
|
||||
private:
|
||||
listNode *rootPtr;
|
||||
listNode *currPtr;
|
||||
};
|
||||
|
||||
List *MakeList(char *text);
|
||||
|
||||
#endif
|
||||
BIN
dll/europa/cse476/p1
Executable file
BIN
dll/europa/cse476/p1
Executable file
Binary file not shown.
97
dll/europa/cse476/p1-junk.cpp
Normal file
97
dll/europa/cse476/p1-junk.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
// CSE476 Bottom Up Chart Parser
|
||||
// Ed Schlunder (zilym@asu.edu)
|
||||
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "grammar.h"
|
||||
#include "lexicon.h"
|
||||
|
||||
Lexicon lex("lexicon.txt");
|
||||
Grammar gra("grammar.txt");
|
||||
|
||||
void procAgenda(genericNode *a) {
|
||||
List *currLine;
|
||||
genericNode *pred;
|
||||
char *category;
|
||||
|
||||
category = a->Feature("CAT");
|
||||
cout << " Unify searching for: " << category << endl;
|
||||
gra.GoTop();
|
||||
do {
|
||||
currLine = gra.currLine();
|
||||
currLine->GoTop();
|
||||
currLine->GoNext();
|
||||
pred = currLine->currItemNode();
|
||||
|
||||
if(unify(a, pred)) {
|
||||
gra.Print();
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
} while(gra.GoNext());
|
||||
cout << endl;
|
||||
}
|
||||
|
||||
// Jack was happy to see a dog
|
||||
void Parse(char *sentence) {
|
||||
List *s = MakeList(sentence);
|
||||
|
||||
cout << "Sentence: ";
|
||||
s->Print();
|
||||
cout << endl;
|
||||
|
||||
s->GoTop();
|
||||
do {
|
||||
if(s->currItem() == NULL)
|
||||
break;
|
||||
|
||||
cout << "Word: " << s->currItem() << endl;
|
||||
if(lex.Lookup(s->currItem())) {
|
||||
cout << " CAT: " << lex.Feature("CAT") << endl;
|
||||
procAgenda(lex.currNode());
|
||||
}
|
||||
else
|
||||
cout << " No lexical entry!" << endl;
|
||||
} while(s->GoNext());
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char sentence[1000];
|
||||
|
||||
cout << "[nlp]$ Jack was happy to see a dog." << endl;
|
||||
Parse("Jack was happy to see a dog.");
|
||||
|
||||
cout << "[nlp]$ " << flush;
|
||||
cin.getline(sentence, 999);
|
||||
while(cin) {
|
||||
Parse(sentence);
|
||||
|
||||
cout << "[nlp]$ " << flush;
|
||||
cin.getline(sentence, 999);
|
||||
}
|
||||
|
||||
cout << endl;
|
||||
|
||||
/*
|
||||
char tmp[100];
|
||||
cin.getline(tmp, 99);
|
||||
while(cin) {
|
||||
cout << "Lexical Lookup: \"" << tmp << "\" ";
|
||||
if(lex.Lookup(tmp)) {
|
||||
cout << " - cat: " << lex.Feature("CAT");
|
||||
cout << " subcat: " << lex.Feature("SUBCAT");
|
||||
while(char *subcat = lex.Feature())
|
||||
cout << ", " << subcat;
|
||||
cout << endl;
|
||||
}
|
||||
else
|
||||
cout << "does not exist" << endl;
|
||||
|
||||
cin.getline(tmp, 99);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
32
dll/europa/cse476/p1.cpp
Normal file
32
dll/europa/cse476/p1.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#include <iostream.h>
|
||||
#include <fstream.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "parse.h"
|
||||
#include "grammar.h"
|
||||
#include "lexicon.h"
|
||||
#include "list.h"
|
||||
#include "gnode.h"
|
||||
|
||||
Grammar grammar("grammar.txt");
|
||||
Lexicon lexicon("lexicon.txt");
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char *sentence = "Jack was happy to see a dog.";
|
||||
|
||||
// cout << "[nlp]$ " << sentence << endl;
|
||||
// parse(sentence);
|
||||
|
||||
sentence = new char[1000];
|
||||
cout << "[nlp]$ " << flush;
|
||||
cin.getline(sentence, 999);
|
||||
// while(cin) {
|
||||
if(strlen(sentence))
|
||||
parse(sentence);
|
||||
|
||||
// cout << "[nlp]$ " << flush;
|
||||
// cin.getline(sentence, 999);
|
||||
// }
|
||||
|
||||
cout << "Bye bye..." << endl;
|
||||
}
|
||||
338
dll/europa/cse476/parse.cpp
Normal file
338
dll/europa/cse476/parse.cpp
Normal file
@@ -0,0 +1,338 @@
|
||||
#include "parse.h"
|
||||
#include "list.h"
|
||||
#include "grammar.h"
|
||||
#include "lexicon.h"
|
||||
|
||||
extern Grammar grammar;
|
||||
extern Lexicon lexicon;
|
||||
Chart chart;
|
||||
ActiveArcList arcs;
|
||||
|
||||
void parse(char *text) {
|
||||
List *s = MakeList(text);
|
||||
int i;
|
||||
|
||||
cout << *s << endl;
|
||||
|
||||
// go through each word and process
|
||||
s->GoTop();
|
||||
i = 1;
|
||||
do {
|
||||
if(lexicon.lookupWord(s->currItem()) == false) {
|
||||
cout << "Can't find [" << s->currItem() << "] in the lexicon..." << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
chart.add(i, i + 1, lexicon.currNode());
|
||||
} while(lexicon.lookupNext());
|
||||
|
||||
processAgenda();
|
||||
|
||||
i++;
|
||||
} while(s->GoNext());
|
||||
}
|
||||
|
||||
void processAgenda(void) {
|
||||
int begLoc, endLoc;
|
||||
genericNode *obj;
|
||||
|
||||
while(chart.process()) {
|
||||
List *newMatch;
|
||||
|
||||
chart.getKey(begLoc, endLoc, obj);
|
||||
|
||||
cout << "find: " << *obj << endl;
|
||||
newMatch = grammar.findMatch(obj);
|
||||
|
||||
if(newMatch) {
|
||||
do {
|
||||
cout << "Grammar search success:\n" << *newMatch << endl;
|
||||
if(newMatch->length() <= 2) {
|
||||
newMatch->GoTop();
|
||||
chart.add(begLoc, endLoc, newMatch->currItemNode());
|
||||
}
|
||||
else {
|
||||
activeArc *newArc;
|
||||
|
||||
newArc = new activeArc;
|
||||
newArc->begLoc = begLoc;
|
||||
newArc->endLoc = endLoc;
|
||||
newArc->numFound = 1;
|
||||
newArc->ruleLine = newMatch;
|
||||
arcs.add(newArc);
|
||||
}
|
||||
} while((newMatch = grammar.findNext()));
|
||||
}
|
||||
else
|
||||
cout << "Grammar search fail" << endl;
|
||||
|
||||
arcs.print();
|
||||
|
||||
// if there is nothing on the active arc list, we can skip checking arcs
|
||||
if(!arcs.goTop())
|
||||
continue;
|
||||
|
||||
do {
|
||||
activeArc *checkArc;
|
||||
|
||||
checkArc = arcs.currArc();
|
||||
if(checkArc->endLoc == begLoc) {
|
||||
// find the current waiting component of this arc
|
||||
checkArc->ruleLine->GoTop();
|
||||
for(int i = 0; i <= checkArc->numFound; i++)
|
||||
checkArc->ruleLine->GoNext();
|
||||
|
||||
cout << "Arc search: " << *checkArc->ruleLine->currItemNode() << ", "
|
||||
<< *obj;
|
||||
List *assign = unify(*checkArc->ruleLine->currItemNode(), *obj);
|
||||
|
||||
// did this arc unify with the current obj?
|
||||
if(!assign) {
|
||||
cout << " = FAIL" << endl;
|
||||
}
|
||||
else {
|
||||
cout << " = " << *assign << endl;
|
||||
// do the variable substitutions
|
||||
assign = substitute(checkArc->ruleLine, assign);
|
||||
|
||||
if(assign->length() > (checkArc->numFound + 2)) {
|
||||
// this arc has been extended, but not completed
|
||||
cout << "Extended arc:\n" << *assign << "\n" << endl;
|
||||
activeArc *newArc = new activeArc;
|
||||
newArc->begLoc = checkArc->begLoc;
|
||||
newArc->endLoc = endLoc;
|
||||
newArc->numFound = checkArc->numFound + 1;
|
||||
newArc->ruleLine = assign;
|
||||
arcs.add(newArc);
|
||||
}
|
||||
else {
|
||||
// this arc has been completed, we can add it to the chart
|
||||
cout << "Completed arc:\n" << *assign << "\n" << endl;
|
||||
assign->GoTop();
|
||||
chart.add(checkArc->begLoc, endLoc, assign->currItemNode());
|
||||
}
|
||||
}
|
||||
}
|
||||
} while(arcs.goNext());
|
||||
}
|
||||
|
||||
chart.print();
|
||||
}
|
||||
|
||||
Chart::Chart() {
|
||||
// mark this chart as being empty
|
||||
rootPtr = currPtr = NULL;
|
||||
}
|
||||
|
||||
void Chart::add(int begLoc, int endLoc, genericNode *obj) {
|
||||
cout << '[' << begLoc << ',' << endLoc << ',' << *obj << ']' << endl;
|
||||
|
||||
if(rootPtr == NULL) {
|
||||
rootPtr = new chartNode;
|
||||
rootPtr->begLoc = begLoc;
|
||||
rootPtr->endLoc = endLoc;
|
||||
rootPtr->obj = obj;
|
||||
rootPtr->processFlag = true;
|
||||
rootPtr->nextPtr = NULL;
|
||||
}
|
||||
else {
|
||||
chartNode *tmp = rootPtr;
|
||||
|
||||
while(tmp->nextPtr != NULL)
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
tmp->nextPtr = new chartNode;
|
||||
tmp = tmp->nextPtr;
|
||||
tmp->begLoc = begLoc;
|
||||
tmp->endLoc = endLoc;
|
||||
tmp->obj = obj;
|
||||
tmp->processFlag = true;
|
||||
tmp->nextPtr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool Chart::process(void) {
|
||||
chartNode *tmp = rootPtr;
|
||||
|
||||
while(tmp != NULL) {
|
||||
if(tmp->processFlag)
|
||||
return true;
|
||||
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Chart::getKey(int &begLoc, int &endLoc, genericNode *&obj) {
|
||||
chartNode *tmp = rootPtr;
|
||||
|
||||
while(tmp != NULL) {
|
||||
if(tmp->processFlag) {
|
||||
// this key hasn't been processed yet, return it and mark as processed
|
||||
begLoc = tmp->begLoc;
|
||||
endLoc = tmp->endLoc;
|
||||
obj = tmp->obj;
|
||||
tmp->processFlag = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = tmp->nextPtr;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void Chart::print(void) {
|
||||
cout << "Chart ";
|
||||
for(int i = 0; i < 160 - 6; i++)
|
||||
cout << '-';
|
||||
cout << endl;
|
||||
|
||||
currPtr = rootPtr;
|
||||
while(currPtr) {
|
||||
cout << '[' << currPtr->begLoc << ',' << currPtr->endLoc << ','
|
||||
<< currPtr->processFlag << ',' << *currPtr->obj << ']' << endl;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
}
|
||||
cout << '\n' << endl;
|
||||
}
|
||||
|
||||
bool Chart::findMatch(genericNode *obj, List *&assign, int begLoc, int &endLoc) {
|
||||
searchObj = obj;
|
||||
currPtr = rootPtr;
|
||||
|
||||
// empty chart has nothing to match -- abort
|
||||
if(currPtr == NULL)
|
||||
return false;
|
||||
|
||||
// go through each rule in the grammar and try to match it with the given obj
|
||||
while(currPtr) {
|
||||
if(currPtr->begLoc == begLoc) {
|
||||
assign = unify(*currPtr->obj, *searchObj);
|
||||
|
||||
if(assign) {
|
||||
endLoc = currPtr->endLoc;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ActiveArcList::ActiveArcList() {
|
||||
rootPtr = currPtr = NULL;
|
||||
}
|
||||
|
||||
void ActiveArcList::add(activeArc *newArc) {
|
||||
List *assign;
|
||||
int endLoc;
|
||||
|
||||
if(rootPtr) {
|
||||
arcNode *tmp = rootPtr;
|
||||
|
||||
// skip down to the last node
|
||||
while(tmp->nextPtr)
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
tmp->nextPtr = new arcNode;
|
||||
tmp = tmp->nextPtr;
|
||||
|
||||
tmp->arc = newArc;
|
||||
tmp->nextPtr = NULL;
|
||||
}
|
||||
else {
|
||||
rootPtr = new arcNode;
|
||||
rootPtr->arc = newArc;
|
||||
rootPtr->nextPtr = NULL;
|
||||
}
|
||||
|
||||
// whenever a new arc is added, we need to try to unify it with
|
||||
// any of the completed objects on the chart to see if it can be extended
|
||||
newArc->ruleLine->GoTop();
|
||||
for(int i = 0; i <= newArc->numFound; i++)
|
||||
newArc->ruleLine->GoNext();
|
||||
|
||||
if(!chart.findMatch(newArc->ruleLine->currItemNode(), assign, newArc->endLoc, endLoc))
|
||||
return;
|
||||
|
||||
assign = substitute(newArc->ruleLine, assign);
|
||||
if(assign->length() > (newArc->numFound + 2)) {
|
||||
cout << "Extended arc: " << newArc->numFound + 1 << "\n" << *assign << "\n" << endl;
|
||||
activeArc *newArc2 = new activeArc;
|
||||
newArc2->begLoc = newArc->begLoc;
|
||||
newArc2->endLoc = endLoc;
|
||||
newArc2->numFound = newArc->numFound + 1;
|
||||
arcs.add(newArc2);
|
||||
}
|
||||
else {
|
||||
// this arc has been completed, we can add it to the chart
|
||||
cout << "Completed arc:\n" << *assign << "\n" << endl;
|
||||
|
||||
chart.print();
|
||||
|
||||
assign->GoTop();
|
||||
chart.add(newArc->begLoc, endLoc, assign->currItemNode());
|
||||
}
|
||||
}
|
||||
|
||||
bool ActiveArcList::goTop(void) {
|
||||
if(rootPtr) {
|
||||
currPtr = rootPtr;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
currPtr = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ActiveArcList::goNext(void) {
|
||||
if(currPtr && currPtr->nextPtr) {
|
||||
currPtr = currPtr->nextPtr;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
currPtr = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
activeArc *ActiveArcList::currArc(void) {
|
||||
if(currPtr)
|
||||
return currPtr->arc;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ActiveArcList::print(void) {
|
||||
cout << "Active Arcs ";
|
||||
for(int i = 0; i < 160-12; i++)
|
||||
cout << '-';
|
||||
cout << endl;
|
||||
|
||||
currPtr = rootPtr;
|
||||
while(currPtr) {
|
||||
cout << '[' << currPtr->arc->begLoc << ',' << currPtr->arc->endLoc << ',';
|
||||
currPtr->arc->ruleLine->GoTop();
|
||||
cout << *currPtr->arc->ruleLine->currItemNode();
|
||||
for(int i = 0; i < currPtr->arc->numFound; i++) {
|
||||
currPtr->arc->ruleLine->GoNext();
|
||||
cout << ' ' << *currPtr->arc->ruleLine->currItemNode();
|
||||
}
|
||||
cout << " o";
|
||||
while(currPtr->arc->ruleLine->GoNext())
|
||||
cout << ' ' << *currPtr->arc->ruleLine->currItemNode();
|
||||
cout << ']' << endl;
|
||||
|
||||
currPtr = currPtr->nextPtr;
|
||||
}
|
||||
|
||||
cout << '\n' << endl;
|
||||
}
|
||||
64
dll/europa/cse476/parse.h
Normal file
64
dll/europa/cse476/parse.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#include "gnode.h"
|
||||
|
||||
void parse(char *text);
|
||||
void processAgenda(void);
|
||||
|
||||
typedef struct activeArc {
|
||||
int begLoc;
|
||||
int endLoc;
|
||||
int numFound;
|
||||
List *ruleLine;
|
||||
};
|
||||
|
||||
class ActiveArcList {
|
||||
public:
|
||||
ActiveArcList();
|
||||
void add(activeArc *newArc);
|
||||
List *findMatch(int begLoc, int endLoc, genericNode *obj);
|
||||
bool goTop(void);
|
||||
bool goNext(void);
|
||||
activeArc *currArc(void);
|
||||
void print(void);
|
||||
|
||||
|
||||
private:
|
||||
struct arcNode;
|
||||
typedef struct arcNode {
|
||||
activeArc *arc;
|
||||
arcNode *nextPtr;
|
||||
};
|
||||
|
||||
arcNode *rootPtr;
|
||||
arcNode *currPtr;
|
||||
};
|
||||
|
||||
class Chart {
|
||||
public:
|
||||
Chart();
|
||||
|
||||
void add(int begLoc, int endLoc, genericNode *obj);
|
||||
void getKey(int &begLoc, int &endLoc, genericNode *&obj);
|
||||
|
||||
// returns true if there are more keys on the agenda that need processing
|
||||
bool process(void); // GOOD
|
||||
|
||||
bool findMatch(genericNode *obj, List *&assign, int begLoc, int &endLoc);
|
||||
List *findNext(void);
|
||||
|
||||
void print(void);
|
||||
|
||||
private:
|
||||
struct chartNode;
|
||||
typedef struct chartNode {
|
||||
int begLoc;
|
||||
int endLoc;
|
||||
genericNode *obj;
|
||||
bool processFlag;
|
||||
|
||||
chartNode *nextPtr;
|
||||
};
|
||||
|
||||
chartNode *rootPtr;
|
||||
chartNode *currPtr;
|
||||
genericNode *searchObj;
|
||||
};
|
||||
53
dll/europa/cse476/parse.txt
Normal file
53
dll/europa/cse476/parse.txt
Normal file
@@ -0,0 +1,53 @@
|
||||
Jack was happy to see a dog.
|
||||
1 2 3 4 5 6 7 8
|
||||
Key List
|
||||
-------------------------------------------------------------------------------------------------
|
||||
- 1 2 Jack NAME ((AGR 3s))
|
||||
- 1 2 NP ((AGR 3s))
|
||||
- 2 3 was V ((ROOT BE1) (VFORM past) (AGR (1s 3s)) (SUBCAT (_adjp _np)))
|
||||
- 3 4 happy ADJ ((SUBCAT _vp:inf))
|
||||
- 3 4 ADJP
|
||||
- 4 5 to TO
|
||||
- 5 6 see V ((ROOT SEE1) (VFORM base) (SUBCAT _np) (IRREG-PAST +) (EN-PASTRT +))
|
||||
- 6 7 a ART ((ROOT A1)(AGR 3s))
|
||||
- 6 7 NP ((AGR 3s))
|
||||
- 5 7 VP ((AGR ?a) (VFORM base))
|
||||
- 4 7 VP ((SUBCAT inf) (AGR ?a) (VFORM inf))
|
||||
- 3 7 ADJP
|
||||
- 2 7 VP ((AGR (1s 3s)) (VFORM past))
|
||||
* 1 7 S ((INV -) (VFORM past) (AGR 3s))
|
||||
|
||||
Chart
|
||||
-------------------------------------------------------------------------------------------------
|
||||
1 2 NAME ((AGR 3s))
|
||||
1 2 NP ((AGR 3s))
|
||||
2 3 V ((ROOT BE1) (VFORM past) (AGR (1s 3s)) (SUBCAT (_adjp _np)))
|
||||
3 4 ADJ ((SUBCAT _vp:inf))
|
||||
3 4 ADJP
|
||||
4 5 TO
|
||||
5 6 V ((ROOT SEE1) (VFORM base) (SUBCAT _np) (IRREG-PAST +) (EN-PASTRT +))
|
||||
6 7 ART ((ROOT A1)(AGR 3s))
|
||||
// 6 7 NP ((AGR 3s))
|
||||
5 7 VP ((AGR ?a) (VFORM base))
|
||||
4 7 VP ((SUBCAT inf) (AGR ?a) (VFORM inf))
|
||||
3 7 ADJP
|
||||
2 7 VP ((AGR (1s 3s)) (VFORM past))
|
||||
1 7 S ((INV -) (VFORM past) (AGR 3s))
|
||||
|
||||
Active Arc List
|
||||
-------------------------------------------------------------------------------------------------
|
||||
1 2 S ((INV -) (VFORM ?v (pres past)) (AGR 3s))
|
||||
-> NP ((AGR 3s)) o VP ((VFORM ?v (pres past)) (AGR 3s))
|
||||
2 3 VP ((AGR (1s 3s)) (VFORM past))
|
||||
-> V ((SUBCAT _np) (AGR (1s 3s)) (VFORM past)) o NP
|
||||
2 3 VP ((AGR (1s 3s)) (VFORM past))
|
||||
-> V ((SUBCAT _adjp) (AGR (1s 3s)) (VFORM past)) o ADJP
|
||||
3 4 ADJP -> ADJ ((SUBCAT _vp:inf)) o VP ((VFORM inf))
|
||||
4 5 VP ((SUBCAT inf) (AGR ?a) (VFORM inf))
|
||||
-> TO ((AGR ?a) (VFORM inf)) o VP ((VFORM base))
|
||||
5 6 VP ((AGR ?a) (VFORM base))
|
||||
-> V ((SUBCAT _np) (AGR ?a) (VFORM base)) o NP
|
||||
6 7 NP ((AGR 3s)) o N ((AGR 3s))
|
||||
6 7 S ((INV -) (VFORM ?v (pres past)) (AGR 3s)
|
||||
-> NP ((AGR 3s)) o VP ((VFORM ?v (pres past)) (AGR 3s))
|
||||
|
||||
59
dll/europa/cse476/parse2.txt
Normal file
59
dll/europa/cse476/parse2.txt
Normal file
@@ -0,0 +1,59 @@
|
||||
Jack was happy to see a dog.
|
||||
1 2 3 4 5 6 7 8
|
||||
Agenda
|
||||
-------------------------------------------------------------------------------------------------
|
||||
- 1 2 Jack NAME ((AGR 3s))
|
||||
- 1 2 NP ((AGR 3s))
|
||||
- 2 3 was V ((ROOT BE1) (VFORM past) (AGR (1s 3s)) (SUBCAT (_adjp _np)))
|
||||
- 3 4 happy ADJ ((SUBCAT _vp:inf))
|
||||
- 3 4 ADJP
|
||||
- 4 5 to TO
|
||||
- 5 6 see V ((ROOT SEE1) (VFORM base) (SUBCAT _np) (IRREG-PAST +) (EN-PASTRT +))
|
||||
- 6 7 a ART ((ROOT A1)(AGR 3s))
|
||||
- 7 8 dog N ((CAT N) (ROOT DOG1) (AGR 3s))
|
||||
- 6 8 NP ((AGR 3s))
|
||||
- 5 8 VP ((AGR 3s) (VFORM base))
|
||||
- 4 8 VP ((SUBCAT inf) (AGR 3s) (VFORM inf))
|
||||
- 3 8 ADJP
|
||||
- 2 3 VP ((AGR (1s 3s)) (VFORM past))
|
||||
* 1 8 S ((INV -) (VFORM past) (AGR 3s))
|
||||
|
||||
Chart
|
||||
-------------------------------------------------------------------------------------------------
|
||||
1 2 NAME ((AGR 3s))
|
||||
1 2 NP ((AGR 3s))
|
||||
2 3 V ((ROOT BE1) (VFORM past) (AGR (1s 3s)) (SUBCAT (_adjp _np)))
|
||||
3 4 ADJ ((SUBCAT _vp:inf))
|
||||
3 4 ADJP
|
||||
4 5 TO
|
||||
5 6 V ((ROOT SEE1) (VFORM base) (SUBCAT _np) (IRREG-PAST +) (EN-PASTRT +))
|
||||
6 7 ART ((ROOT A1)(AGR 3s))
|
||||
7 8 N ((ROOT DOG1) (AGR 3s))
|
||||
6 8 NP ((AGR 3s))
|
||||
5 8 VP ((AGR 3s) (VFORM base))
|
||||
4 8 VP ((SUBCAT inf) (AGR 3s) (VFORM inf))
|
||||
3 8 ADJP
|
||||
2 8 VP ((AGR (1s 3s)) (VFORM past))
|
||||
1 8 S ((INV -) (VFORM past) (AGR 3s))
|
||||
|
||||
|
||||
2 7 VP ((AGR (1s 3s)) (VFORM past))
|
||||
1 7 S ((INV -) (VFORM past) (AGR 3s))
|
||||
|
||||
Active Arc List
|
||||
-------------------------------------------------------------------------------------------------
|
||||
1 2 S ((INV -) (VFORM ?v (pres past)) (AGR 3s))
|
||||
-> NP ((AGR 3s)) o VP ((VFORM ?v (pres past)) (AGR 3s))
|
||||
2 3 VP ((AGR (1s 3s)) (VFORM past))
|
||||
-> V ((SUBCAT _np) (AGR (1s 3s)) (VFORM past)) o NP
|
||||
2 3 VP ((AGR (1s 3s)) (VFORM past))
|
||||
-> V ((SUBCAT _adjp) (AGR (1s 3s)) (VFORM past)) o ADJP
|
||||
3 4 ADJP -> ADJ ((SUBCAT _vp:inf)) o VP ((VFORM inf))
|
||||
4 5 VP ((SUBCAT inf) (AGR ?a) (VFORM inf))
|
||||
-> TO ((AGR ?a) (VFORM inf)) o VP ((VFORM base))
|
||||
5 6 VP ((AGR ?a) (VFORM base))
|
||||
-> V ((SUBCAT _np) (AGR ?a) (VFORM base)) o NP
|
||||
6 7 NP ((AGR 3s)) o N ((AGR 3s))
|
||||
6 7 S ((INV -) (VFORM ?v (pres past)) (AGR 3s)
|
||||
-> NP ((AGR 3s)) o VP ((VFORM ?v (pres past)) (AGR 3s))
|
||||
|
||||
10
dll/europa/cse476/t1.cpp
Normal file
10
dll/europa/cse476/t1.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <iostream.h>
|
||||
#include "gnode.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
genericNode p("((CAT (VP)) (VFORM (inf)))");
|
||||
genericNode l("Jack ((CAT NAME) (AGR 3s))");
|
||||
|
||||
cout << "P: " << p << endl;
|
||||
cout << "L: " << l << endl;
|
||||
}
|
||||
12
dll/europa/cse476/t2.cpp
Normal file
12
dll/europa/cse476/t2.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <iostream.h>
|
||||
#include "gnode.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
genericNode a("((CAT (V)) (SUBCAT (_vp:inf)) (AGR (?a)) (VFORM (?v)))");
|
||||
genericNode b("want ((CAT (V)) (ROOT (WANT1)) (VFORM (base)) (SUBCAT (_np _vp:inf _np_vp:inf)))");
|
||||
|
||||
cout << "A: " << a << endl;
|
||||
cout << "B: " << b << endl;
|
||||
|
||||
cout << "unify(b, a): " << unify(b, a) << endl;
|
||||
}
|
||||
11
dll/europa/cse476/t3.cpp
Normal file
11
dll/europa/cse476/t3.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "lexicon.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Lexicon lex("lexicon.txt");
|
||||
bool res;
|
||||
|
||||
res = lex.lookupWord("want");
|
||||
cout << "lookupWord(\"want\"): " << res << endl;
|
||||
if(res)
|
||||
cout << " gnode: " << *lex.currNode() << endl;
|
||||
}
|
||||
8
dll/europa/cse476/t4.cpp
Normal file
8
dll/europa/cse476/t4.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "grammar.h"
|
||||
#include <iostream.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Grammar gram("grammar.txt");
|
||||
|
||||
cout << "top line:" << endl;
|
||||
}
|
||||
371
dll/europa/europa.c
Normal file
371
dll/europa/europa.c
Normal file
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
Europa - Copyright (c) 1999, Ed Schlunder <zilym@asu.edu>
|
||||
|
||||
This is free software distributable under the terms of the GNU GPL-- See
|
||||
the file COPYING for details.
|
||||
*/
|
||||
|
||||
#define MOD_VERSION "0.01"
|
||||
#define MOD_NAME "Europa"
|
||||
#include "europa.h"
|
||||
|
||||
#include <mysql/mysql.h>
|
||||
|
||||
/* yay! mysql.h and irc.h both define NAME_LEN... */
|
||||
#undef NAME_LEN
|
||||
#include "irc.h"
|
||||
#include "struct.h"
|
||||
#include "server.h"
|
||||
#include "ircaux.h"
|
||||
#include "status.h"
|
||||
#include "screen.h"
|
||||
#include "vars.h"
|
||||
#include "misc.h"
|
||||
#include "output.h"
|
||||
#include "hook.h"
|
||||
#include "module.h"
|
||||
#define INIT_MODULE
|
||||
#include "modval.h"
|
||||
#include "irc_std.h"
|
||||
|
||||
#define MAX_WORD 100
|
||||
#define MAX_WORDS 1000
|
||||
#define MAX_CHANNELS 10
|
||||
#define MAX_QUERY 1000
|
||||
|
||||
int beQuiet = 0;
|
||||
MYSQL mysql;
|
||||
|
||||
/* called when bitchx user enters IRC command "/europa DATA" */
|
||||
BUILT_IN_DLL(europa)
|
||||
{
|
||||
int i;
|
||||
|
||||
put_it("** /europa %s baby!", args);
|
||||
}
|
||||
|
||||
/* print some chat to both the IRC server (other channel members) and the local
|
||||
client window... */
|
||||
void dualOut(const char *str, const char *chan) {
|
||||
put_it("<europa> %s", str);
|
||||
send_to_server("PRIVMSG %s :%s", chan, str);
|
||||
}
|
||||
|
||||
/* a wrapper on dualOut() to do printf-like text formatting on outgoing text */
|
||||
void sout(char *chan, const char *format, ...) {
|
||||
va_list args;
|
||||
char tmp[MAX_WORD * MAX_WORDS];
|
||||
|
||||
if(beQuiet)
|
||||
return;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(tmp, MAX_WORD*MAX_WORDS, format, args);
|
||||
va_end(args);
|
||||
|
||||
dualOut(tmp, chan);
|
||||
}
|
||||
|
||||
void sdunno(char *args[]) {
|
||||
sout(args[1], "%s: Hmm, I don't know that one...", args[0]);
|
||||
}
|
||||
|
||||
void shello(char *chan, char *who) {
|
||||
if(who == NULL)
|
||||
sout(chan, "hey, how's it going?");
|
||||
else
|
||||
sout(chan, "%s: hey, how's it going?", who);
|
||||
}
|
||||
|
||||
/* attempts to find an answer to a keyword that we've been asked about... */
|
||||
char *dbLookup(char *keyword, char *table) {
|
||||
MYSQL_RES *res;
|
||||
MYSQL_ROW row;
|
||||
char query[MAX_QUERY];
|
||||
char *answer, *encodedKeyword = malloc(strlen(keyword) * 2 + 1);
|
||||
|
||||
mysql_escape_string(encodedKeyword, keyword, strlen(keyword));
|
||||
if(snprintf(query, MAX_QUERY,
|
||||
"select answer from %s where keyword like '%s'",
|
||||
table, encodedKeyword) == -1) {
|
||||
put_it("** Europa query overflow (increase MAX_QUERY)");
|
||||
|
||||
free(encodedKeyword);
|
||||
return NULL;
|
||||
}
|
||||
free(encodedKeyword);
|
||||
|
||||
if(mysql_query(&mysql, query))
|
||||
return NULL;
|
||||
|
||||
if(!(res = mysql_store_result(&mysql))) {
|
||||
/* this shouldn't happen... */
|
||||
put_it("** Europa query failure: %s", query);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
row = mysql_fetch_row(res);
|
||||
if(row == NULL) {
|
||||
mysql_free_result(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
answer = strdup(row[0]);
|
||||
|
||||
mysql_free_result(res);
|
||||
return answer;
|
||||
}
|
||||
|
||||
/* args[0] - nick of sender
|
||||
args[1] - channel text was said on
|
||||
args[2] - actual text */
|
||||
void processChat(int argc, char *args[], char *argl[]) {
|
||||
int i;
|
||||
|
||||
if(argc < 3) return;
|
||||
if(strcmp(args[3], "shutup") == 0) {
|
||||
sout(args[1], "%s: okay, okay...", args[0]);
|
||||
beQuiet = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(strcmp(args[3], "hello") == 0 ||
|
||||
strcmp(args[3], "hello?") == 0) {
|
||||
if(beQuiet)
|
||||
beQuiet = 0;
|
||||
else
|
||||
shello(args[1], args[0]);
|
||||
}
|
||||
|
||||
if(argc < 4) return;
|
||||
if(strcmp(args[3], "ex") == 0 ||
|
||||
strcmp(args[3], "explain") == 0) {
|
||||
int pengy = 0;
|
||||
char *answer;
|
||||
|
||||
answer = dbLookup(args[4], "fact");
|
||||
if(answer == NULL) {
|
||||
answer = dbLookup(args[4], "facts");
|
||||
if(answer == NULL) {
|
||||
sdunno(args);
|
||||
return;
|
||||
}
|
||||
pengy = -1;
|
||||
}
|
||||
|
||||
if(pengy)
|
||||
sout(args[1], "%s: %s (from Pengy)", args[0], answer);
|
||||
else
|
||||
sout(args[1], "%s: %s", args[0], answer);
|
||||
|
||||
free(answer);
|
||||
return;
|
||||
}
|
||||
|
||||
if(strcmp(args[3], "learn") == 0) {
|
||||
char query[MAX_QUERY];
|
||||
char *encodedKeyword = malloc(strlen(args[4]) * 2 + 1),
|
||||
*encodedAnswer = malloc(strlen(argl[5]) * 2 + 1);
|
||||
|
||||
mysql_escape_string(encodedKeyword, args[4], strlen(args[4]));
|
||||
mysql_escape_string(encodedAnswer, argl[5], strlen(argl[5]));
|
||||
|
||||
snprintf(query, MAX_QUERY, "insert into fact values('%s','%s')",
|
||||
encodedKeyword, encodedAnswer);
|
||||
|
||||
free(encodedKeyword);
|
||||
free(encodedAnswer);
|
||||
|
||||
if(mysql_query(&mysql, query))
|
||||
put_it("** Europa db query failed: %s", query);
|
||||
else
|
||||
sout(args[1], "%s: %s learned, thanks...", args[0], args[4]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if(strcmp(args[3], "forget") == 0) {
|
||||
char query[MAX_QUERY];
|
||||
char *encodedKeyword = malloc(strlen(args[4]) * 2 + 1);
|
||||
|
||||
mysql_escape_string(encodedKeyword, args[4], strlen(args[4]));
|
||||
snprintf(query, MAX_QUERY,
|
||||
"delete from fact where keyword='%s'", encodedKeyword);
|
||||
free(encodedKeyword);
|
||||
|
||||
if(mysql_query(&mysql, query)) {
|
||||
snprintf(query, MAX_QUERY,
|
||||
"delete from facts where keyword='%s'", args[4]);
|
||||
if(mysql_query(&mysql, query)) {
|
||||
put_it("** Europa db query failed: %s", query);
|
||||
sout(args[1], "%s: I didn't know anything about %s anyway...",
|
||||
args[0], args[4]);
|
||||
}
|
||||
else
|
||||
sout(args[1], "%s: %s forgotten from Pengy db...", args[0], args[4]);
|
||||
}
|
||||
else
|
||||
sout(args[1], "%s: %s forgotten...", args[0], args[4]);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* called by BitchX whenever someone says something in the channel directed to
|
||||
this user... */
|
||||
int public_ar_proc(char *which, char *str, char **unused) {
|
||||
char *local, *args[MAX_WORDS], *argl[MAX_WORDS];
|
||||
int i = 0, total, w = 0;
|
||||
|
||||
/*
|
||||
we want to parse out the text into separate words. args[WORD_N] is
|
||||
a pointer to a single word while argl[WORD_N] is a pointer to the
|
||||
rest of the sentence beginning at word WORD_N.
|
||||
*/
|
||||
argl[0] = str;
|
||||
while(i < strlen(str)) {
|
||||
if(str[i] != ' ') break;
|
||||
i++;
|
||||
}
|
||||
local = strdup(str + i);
|
||||
args[0] = local;
|
||||
|
||||
total = strlen(local);
|
||||
while(i < total && w < MAX_WORDS) {
|
||||
if(local[i] == ' ') {
|
||||
local[i] = 0;
|
||||
w++;
|
||||
while(++i < total)
|
||||
if(local[i] != ' ') break;
|
||||
|
||||
args[w] = local + i;
|
||||
argl[w] = str + i;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
processChat(w, args, argl);
|
||||
|
||||
free(local);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int public_proc(char *which, char *str, char **unused) {
|
||||
char *local, *args[MAX_WORDS], *argl[MAX_WORDS];
|
||||
int i = 0, total, w = 0;
|
||||
|
||||
/*
|
||||
we want to parse out the text into separate words. args[WORD_N] is
|
||||
a pointer to a single word while argl[WORD_N] is a pointer to the
|
||||
rest of the sentence beginning at word WORD_N.
|
||||
*/
|
||||
argl[0] = str;
|
||||
while(i < strlen(str)) {
|
||||
if(str[i] != ' ') break;
|
||||
i++;
|
||||
}
|
||||
local = strdup(str + i);
|
||||
args[0] = local;
|
||||
|
||||
total = strlen(local);
|
||||
while(i < total && w < MAX_WORDS) {
|
||||
if(local[i] == ' ') {
|
||||
local[i] = 0;
|
||||
w++;
|
||||
while(++i < total)
|
||||
if(local[i] != ' ') break;
|
||||
|
||||
args[w] = local + i;
|
||||
argl[w] = str + i;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(w > 1) {
|
||||
if(strstr(argl[2], "hello") != NULL)
|
||||
shello(args[1], args[0]);
|
||||
}
|
||||
|
||||
free(local);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* called when user enters irc command "/explain USER/CHANNEL KEYWORD" */
|
||||
BUILT_IN_DLL(cmdExplain)
|
||||
{
|
||||
char *local, *arg[MAX_WORDS], *argl[MAX_WORDS];
|
||||
int i = 0, total, w = 0;
|
||||
|
||||
argl[0] = args;
|
||||
while(i < strlen(args)) {
|
||||
if(args[i] != ' ') break;
|
||||
i++;
|
||||
}
|
||||
local = strdup(args + i);
|
||||
arg[0] = local;
|
||||
|
||||
total = strlen(local);
|
||||
while(i < total && w < MAX_WORDS) {
|
||||
if(local[i] == ' ') {
|
||||
local[i] = 0;
|
||||
w++;
|
||||
while(++i < total)
|
||||
if(local[i] != ' ') break;
|
||||
|
||||
arg[w] = local + i;
|
||||
argl[w] = args + i;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if(w) {
|
||||
int pengy = 0;
|
||||
char *answer = dbLookup(arg[1], "fact");
|
||||
|
||||
if(answer == NULL) {
|
||||
answer = dbLookup(arg[1], "facts");
|
||||
if(answer == NULL) {
|
||||
put_it("** Europa doesn't know about %s", arg[1]);
|
||||
free(local);
|
||||
return;
|
||||
}
|
||||
|
||||
pengy = -1;
|
||||
}
|
||||
|
||||
if(pengy)
|
||||
sout(arg[0], "%s (from Pengy)", answer);
|
||||
else
|
||||
sout(arg[0], answer);
|
||||
}
|
||||
|
||||
free(local);
|
||||
return;
|
||||
}
|
||||
|
||||
int Europa_Init(IrcCommandDll **intp, Function_ptr *global_table) {
|
||||
initialize_module(MOD_NAME);
|
||||
|
||||
add_module_proc(COMMAND_PROC, MOD_NAME, "europa", NULL, 0, 0, europa, NULL);
|
||||
add_module_proc(COMMAND_PROC, MOD_NAME, "explain", NULL, 0, 0, cmdExplain, NULL);
|
||||
add_module_proc(HOOK_PROC, MOD_NAME, NULL, "*", PUBLIC_AR_LIST, 1, NULL, public_ar_proc);
|
||||
add_module_proc(HOOK_PROC, MOD_NAME, NULL, "*", PUBLIC_LIST, 1, NULL, public_proc);
|
||||
|
||||
put_it("** Europa v%s connecting to database backend...", MOD_VERSION);
|
||||
|
||||
/* connect to the database server */
|
||||
if(!(mysql_connect(&mysql, DBHOST, DBUSER, DBPASSWD))) {
|
||||
put_it("** Server refused login/password.");
|
||||
return 0;
|
||||
}
|
||||
if(mysql_select_db(&mysql, DBNAME)) {
|
||||
put_it("** Server refused connection to '%s' database.", DBNAME);
|
||||
return 0;
|
||||
}
|
||||
|
||||
put_it("** Europa loaded!");
|
||||
return 0;
|
||||
}
|
||||
5
dll/europa/europa.h
Normal file
5
dll/europa/europa.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#define DBNAME "europa"
|
||||
#define DBHOST "localhost"
|
||||
#define DBUSER "europa"
|
||||
#define DBPASSWD "APASSWD"
|
||||
|
||||
6065
dll/europa/knowledgebase.sql
Normal file
6065
dll/europa/knowledgebase.sql
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user