├── .gitignore ├── doctopics ├── .emacs.xml.swp ├── .topics.xml.swp ├── SIPB.xml ├── dodona.xml ├── emacs.xml ├── git.xml ├── mitsfs.xml ├── printing.xml ├── topics.xml ├── words.xml ├── yaks.xml └── zephyr.xml ├── dodona ├── dodona.py ├── fuzzystack.py ├── helper.py ├── nlp.py ├── parsetree.py ├── rules.gr ├── session.py ├── vocabulary.gr ├── webUI.py ├── www ├── .README.swp ├── .dodona.css.swp ├── .handler.php.swp ├── README ├── dodona.css ├── dodona.js ├── handler.php ├── index.html └── jquery-1.2.6.min.js ├── xml_parser.py └── zephyrUI.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc 3 | *# 4 | *.# -------------------------------------------------------------------------------- /doctopics/.emacs.xml.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhamrick/dodona/2f11ee2b21cc7de523b3222fbf7a24579262bc3e/doctopics/.emacs.xml.swp -------------------------------------------------------------------------------- /doctopics/.topics.xml.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhamrick/dodona/2f11ee2b21cc7de523b3222fbf7a24579262bc3e/doctopics/.topics.xml.swp -------------------------------------------------------------------------------- /doctopics/SIPB.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SIPB is MIT's volunteer student computing group, improving computing at MIT since 1969. Today, SIPB projects provide innovative services and special expertise to the MIT community. Their office is just outside the Athena cluster in the student center W20, and you are welcome to come by to ask SIPB for help or to hang around, use the computers, and maybe get involved. 5 | 6 | 7 | Student Information Processing Board 8 | 9 | 10 | 11 | scripts.mit.edu: Get your own blog or wiki, or run any web app! 12 | The SIPB scripts server runs CGI scripts out 13 | of your Athena locker. 14 | 15 | xvm.mit.edu: Your own virtual server. Reliable, easy, and flexible. 16 | 17 | debathena.mit.edu: Bringing MIT's Athena environment to Debian 18 | and Ubuntu, first for our laptops, and then 19 | back to the clusters. 20 | 21 | linerva.mit.edu: Remote login access to Athena on a powerful 22 | Debian GNU/Linux server running Debathena. 23 | 24 | Documentation: Helpful and informative documents about various 25 | computing topics at MIT, written by SIPB. 26 | 27 | Computer Help: Have a computing question or need some help? 28 | Come drop by our office. 29 | 30 | 31 | 32 | 33 | IAP classes: Teach or learn. Knowledge is power. 34 | http://sipb.mit.edu/iap/ 35 | 36 | SIPB Cluedumps: Every year, SIPB hosts a number of computer-related 37 | technical talks on a variety of subjects. 38 | 39 | Hackathons: Like coding? Come work on cool projects with us 40 | at SIPB! We're always looking for new members, 41 | so feel free to drop by our Hackathons to help us 42 | improve computing at MIT. 43 | 44 | SIPB Computer Tours: At the beginning of each year, SIPB offers 45 | tours of the MIT computing infrastructure, including 46 | Athena server rooms, interesting labs. 47 | SIPB Computer Stories: Come listen to interesting computer stories 48 | about MIT in this annual event. 49 | 50 | 51 | 52 | 53 | 54 | The SIPB office is W20-557 in the Student Center at 84 Mass Ave. You can call 617/253-7788 (x3-7788) or e-mail sipb@mit.edu with questions. 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /doctopics/dodona.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Overview of A certain zephyrbot 4 | 5 | ... is perhaps higher than intended. 6 | 7 | -------------------------------------------------------------------------------- /doctopics/emacs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The GNU Emacs text editor (Athena's primary supported editor) is an extensible, customizable, self-documenting real-time 5 | display editor. 6 | 7 | 8 | Several versions of Emacs are available on Athena. GNU Emacs 21 (version 21.1.1) is the default version as of Athena 9.1. If you login to an older Athena 9.0 workstation, the default Emacs will be GNU Emacs 20 (version 20.7) Other versions of GNU Emacs are often available in the emacs locker. 9 | Additionally, there is another version of emacs, XEmacs available on Athena. It traditionally has had a nicer X interface, and also a different set of lisp. To run it, use the commands: 10 | add xemacs 11 | xemacs & 12 | 13 | 14 | 15 | There are several ways to choose the size of your Emacs window. 16 | If you start Emacs by just typing: 17 | emacs & 18 | and you are using mwm (the default window manager), you use the mouse or keyboard to choose the window's placement, and then use the keyboard to select the size. The mouse pointer will change to an inverted "L" with a rectangle attached to it, and a little box will pop up in the middle of the screen telling you the position of the L, and the current size of the window, something like this: 19 | (120,115) 20 | 80x24 21 | Move the mouse pointer to where you want the upper-left corner of the new window to be. Now, you can either hit the left mouse button or return to place the window, if that's the size you want. You can also hit the space bar, which will freeze the upper left corner, and any motion you make with the mouse will change the size of the rectangle. After you select the size you want, hit Return or the left mouse button, and the window will appear. 22 | Note: If your workstation's mouse only has two buttons, pressing both buttons simultaneously has the same effect as pressing the middle button. 23 | If you want, you can specify the window's size by providing a "geometry specification". For example, if you type: 24 | emacs -geometry 132x48 & 25 | ...and press the left mouse button, the Emacs window will be 132 columns wide and 48 rows high. 26 | You can also specify the position of the window relative to the upper-left corner of the screen. For example: 27 | emacs -geometry 132x48+50+100 & 28 | ...will create your Emacs window with its upper-left corner located 50 pixels across from the left edge of the screen and 100 pixels down from the top of the screen. In this case, the window appears automatically (you don't need to press any mouse buttons). 29 | You can also resize the window after placing it: see the stock answer `How to MOVE or resize windows' under the XWINDOWS topic in the olc_answers program. 30 | 31 | 32 | 33 | To disable the menu bar, place the following line in your .emacs file: 34 | (menu-bar-mode -1) 35 | To disable the scrollbar, use the following line: 36 | (toggle-scroll-bar -1) 37 | 38 | 39 | 40 | You can use your workstation's mouse to perform some editing operations in Emacs. The table below summarizes these operations. 41 | 42 | Button*: Operation 43 | Left: Move the cursor to the mouse's location. 44 | 45 | Middle: Insert the text from the X cut buffer at the location of the Emacs cursor. 46 | 47 | Right: Copy the text between the cursor and the mouse into the X cut buffer. The text is not deleted from the buffer but is put into the Emacs kill ring. The text may be recalled by using MIDDLE (above) or Ctrl-Y. 48 | 49 | Ctrl-Middle: Cut the text between the cursor and the mouse into the X cut buffer. The text is deleted from the buffer and is put into the Emacs kill ring. The text may be recalled by using MIDDLE (above) or Ctrl-Y. 50 | 51 | Ctrl-Right: Divide the current window into two windows. 52 | 53 | Ctrl-Shift-Right: Return to single-window mode, keeping the window that contains the mouse. 54 | 55 | Ctrl-Shift-Middle: Brings up a pop-up help window, from which various operations or buffers may be selected with the mouse. 56 | 57 | * Note: If your workstation's mouse only has two buttons, pressing both buttons simultaneously has the same effect as pressing the middle button. 58 | 59 | 60 | 61 | If you're logged into a workstation, you can use the arrow keys (though not the numeric keypad arrows) to move the cursor around your window. Additionally, emacs has another set of control characters for movement: 62 | 63 | To move forward one character, type: CTRL-f 64 | To move backward one character, type: CTRL-b 65 | 66 | To move to the next line, type: CTRL-n 67 | To move to the previous line, type: CTRL-p 68 | 69 | To move to the end of a line: CTRL-e 70 | To move to the beginning of a line: CTRL-a 71 | 72 | There are also some useful commands that use the Meta key. On Suns, this is bound to both the Alt key and the diamond-symbol keys; on SGIs, it is bound to the Alt keys. Additionally, the ESC key can be used in place of Alt/Meta. 73 | 74 | (Note that you must hold down Alt and then press the next key; ESC can be pressed and released before hitting the next key). 75 | 76 | To move forward one word: ESC f or M-f 77 | To move backwards one word: ESC b or M-b 78 | To move to the end of a sentence: ESC e or M-e 79 | To move to the beginning of a sentence: ESC a or M-a 80 | To move to the end of the buffer: ESC > or M-> 81 | To move to the beginning of the buffer: ESC < or M-< 82 | 83 | Notice how most of the commands are mnemonic. 84 | 85 | 86 | 87 | The cut and paste behavior of Emacs is similar to most other standard X applications. 88 | 89 | - Dragging with the LEFT mouse button now puts the selected region in the kill ring so you can paste it into other X applications. The old method of clicking at the beginning with the LEFT mouse button and at the end with the RIGHT mouse button still works, but the cursor will end up at the end of the region instead of at the beginning. 90 | 91 | - Double and triple clicks with the LEFT mouse button now select the word or line surrounding where you click. If you drag after the last click, you can select a range of words or lines. 92 | 93 | - Clicking and dragging the RIGHT mouse button now extends a previously mouse-selected region, from the end of the region that is closer to where you click. 94 | 95 | - As before, clicking the RIGHT mouse button in the same place kills the region selected. 96 | 97 | 98 | 99 | Ctrl-<space> or Ctrl-@: Either of these commands will set a mark. A mark is an or an invisible pointer which will be used to mark the starting character of the region you wish to delete or move. If you place the mark in the wrong place, you can set it elsewhere with the same command. 100 | 101 | Ctrl-w: This command will kill all of the text between the mark location and the current emacs cursor position. This text can be retrieved with the following command unless you kill another block of text. 102 | 103 | Meta-w: This command will "save" all of the text between the mark location and the current emacs cursor position; it can then be retrieved with the following command unless you kill/save another block of text. 104 | 105 | Ctrl-y: This command will yank back the text which was deleted most recently with the above command. The text will be placed at the current emacs cursor location. You can yank back the text as many times as you wish. 106 | 107 | Meta-y: When you kill or copy a region of text, it doesn't forget about previous kills. Instead, it keeps track of them in a "stack" fashion. If you want to yank the region you killed before the last one, hit Ctrl-y to yank, and then Meta-y to yank the previous kill *instead* of the one you just retrieved. You can keep hitting Meta-y as many times as you like, if you want to recover something killed a while back. The maximum number of kills remembered at any given time defaults to 30. 108 | 109 | Ctrl-x u: This is the undo command. This is useful if you yank back text at the wrong location or sometimes if you delete something you didn't mean to. Each time you repeat this command, emacs will undo a previous change to your file. 110 | 111 | Please note that when you use Ctrl-w or Meta-w to put a region of text in the kill ring, it will become the current X selection. Likewise, when you use Ctrl-y to grab a region of text from the kill ring, it will use the current selection if you've selected text recently. 112 | 113 | To disable this behavior, place the following lines in your .emacs file: 114 | 115 | (setq interprogram-cut-function nil) 116 | (setq interprogram-paste-function nil) 117 | 118 | 119 | 120 | To replace a character string everywhere that it occurs within the current buffer, there is two ways to do it 121 | 122 | M-x replace-string 123 | 124 | will ask you for the string you want to replace and what you want to replace it with. Once you provide these, it will make the change globally within the buffer. 125 | 126 | M-% 127 | 128 | will also prompt you for the string to search for and the string to replace it. It differs from m-x replace-string in that it asks for verification before making each change. 129 | 130 | In order to enter control characters in either of the above, they will have to be preceded by C-q. For example, ^J is typed as C-q C-j. 131 | 132 | 133 | 134 | The default version of Emacs on Athena has line numbering automatically. If you are using an earlier version, you may have to turn it on. 135 | 136 | The line number is displayed in the "mode line" at the bottom of the screen. If you look down at the bottom of the screen, you should see a section that has "--L#--" where the "#" is the line number your text cursor is currently on. If line numbering currently isn't on in your emacs window, just type: 137 | 138 | Meta-x line-number-mode 139 | 140 | If you wish to turn on line numbering always, you can put the line: 141 | 142 | (setq line-number-mode t) 143 | 144 | in your .emacs file. If you wish to have it always be off, put in: 145 | 146 | (setq line-number-mode nil) 147 | 148 | Similarly, there is a column-number-mode that works the same way. 149 | 150 | ------------------------------------------------------------------ 151 | 152 | There are several other related commands you can also use to determine the line number and perform line number functions. If you want to find out the number of the line where the cursor is, type this: 153 | 154 | M-x what-line 155 | 156 | If you want to move the cursor to a particular line, type this: 157 | 158 | M-x goto-line 159 | 160 | followed by the line number. 161 | 162 | If you want to know how many lines are in a region of text, use: 163 | 164 | M-x count-lines-region 165 | or 166 | M-= 167 | 168 | 169 | 170 | If you want Emacs to be in Auto Fill mode every time you use it, then you need to put the following lines into a file named ~/.emacs: 171 | 172 | (setq default-major-mode 'text-mode) 173 | (setq text-mode-hook 174 | '(lambda nil 175 | (setq fill-column 72) 176 | (auto-fill-mode 1))) 177 | 178 | The first line makes Text Mode the default for all files without another defined mode (such as C Mode). (You can leave that line out if you wish.) The other lines make Auto Fill mode the default for all Text Mode buffers, and make the lines break at the 72nd column. 179 | 180 | 181 | 182 | Unless you have specified otherwise in your '.emacs' file, Emacs will periodically save the file you are editing into the /var/tmp directory on your workstation. 183 | 184 | If: 185 | 1) You somehow delete your file. 186 | 2) Your workstation crashes. 187 | 3) You encounter filesystem errors because you are over quota, or because your fileserver has crashed. 188 | 189 | then the auto-save file could be of help. These files are kept for three days before being deleted. 190 | 191 | To recover the file, start up emacs with the same filename as you did before, on the SAME WORKSTATION as before. For example, suppose you were editing resume.tex when your workstation crashed. When the workstation becomes usable again, login and do: 192 | 193 | emacs resume.tex & 194 | 195 | Note that when you start up Emacs, it will say: 196 | 197 | Auto save file is newer; consider M-x recover-file 198 | 199 | This is a hint that the file needs to be recovered from the auto-save file. Look at the file you now have in Emacs; if it's blank or it's not the version you wanted, then you need to recover. DO NOT just begin typing, or Emacs will soon make another auto-save file and clobber the old one. 200 | 201 | To recover the auto-save file, type: 202 | 203 | M-x recover-file RETURN resume.tex RETURN 204 | 205 | Emacs will then show you the date of the auto-save file, just to be sure, and ask you whether you want to recover it. Type 'yes' to recover, or 'no' if you don't want to. 206 | 207 | If Emacs says: 208 | 209 | Auto save file /var/tmp/#4863.@mit@jruser@resume.tex# not current 210 | 211 | then the file does not exist on your workstation (ie: you may have misspelled it). 212 | 213 | Now save this file under a different name: 214 | 215 | C-x C-w resume.recover 216 | 217 | Emacs will not auto-save this recovered file until you type: 218 | 219 | M-x auto-save-mode 220 | 221 | This is so you can recover from the old auto-save file again, just in case you change your mind. 222 | 223 | Now look at the two files, resume.tex and resume.recover, and take the one you like, or parts of both. 224 | 225 | 226 | 227 | To customize Emacs, you need to write some Lisp code. It's not really that difficult. The code should be put in a file named '.emacs' in your home directory. Every time Emacs starts up, it automatically reads any Lisp code you have put into your '.emacs' file. 228 | 229 | To define a key binding, use an expression of this form: 230 | 231 | (define-key key-map keystrokes function) 232 | 233 | To set an Emacs variable, use an expression of this form: 234 | 235 | (setq variable value) 236 | 237 | The section below gives some typical customizations you might perform in your '.emacs' file. Note that comments in are preceded by semicolon ';' characters. 238 | 239 | 240 | (global-set-key "\M-g" 'goto-line) - Esc-G runs the goto-line function. 241 | 242 | (global-set-key "\C-xt" 'transpose-lines) - Ctrl-x t runs the transpose-lines function. 243 | 244 | (setq default-major-mode 'text-mode) - Default mode is text-mode. 245 | 246 | (setq text-mode-hook '(lambda () (auto-fill-mode 1))) - Enable auto-fill mode whenever using text-mode. 247 | 248 | (setq delete-auto-save-files t) - Delete unnecessary auto-save files. 249 | 250 | (display-time) - Display current time and load average on mode line. 251 | 252 | 253 | 254 | Any X-related code that you want to put in your .emacs file should be enclosed in elisp which causes it to be called only if you're on an X workstation, and not if you're dialed in, like so: 255 | 256 | (if window-system-version 257 | (progn 258 | (require 'x-mouse) 259 | X-RELATED STUFF GOES HERE 260 | )) 261 | 262 | For example: 263 | 264 | (if window-system-version 265 | (progn 266 | (require 'x-mouse) 267 | (setq x-paste-move-point t))) 268 | 269 | 270 | 271 | The function keys (F1-F12) can be bound to functions in a similar fashion as any other key. 272 | 273 | For example, you might set the following three function keys: 274 | 275 | (global-set-key [f1] 'mail) 276 | (global-set-key [f2] 'mh-rmail) 277 | (global-set-key [f3] 'discuss) 278 | 279 | 280 | 281 | Several options are available for users who want emacs to check the spelling of their documents. 282 | 283 | The first is: 284 | 285 | M-x ispell 286 | 287 | (M-x is the ALT or Compose Character key and x key pressed at the same time.) 288 | 289 | Now the following commands are available for the duration of your emacs session: 290 | 291 | M-x ispell-word - Checks word 292 | M-x ispell-buffer - Checks buffer (current file) 293 | M-x ispell-region - Checks region 294 | 295 | When ispell finds a word that is not in its dictionary, it will outline the word in reverse video (from emacs it will respond with a message that says, "Enter letter to replace word; space to flush") If there are "near misses" in the dictionary, ispell will also display the incorrect word and a list of correct alternatives at the top if they exist. 296 | 297 | At this point, you can type one of the following characters: 298 | 299 | r - Replace Word: Ispell asks you for a replacement word. Ispell will NOT check this word. 300 | 301 | # - Replace Word with suggested word: The words at the top of the screen are numbered. If you type a word's number, ispell will use this word as a replacement. 302 | 303 | <space> - Skips Word: Leave this word as is. If this word is encountered again, ispell will stop and prompt you for an action. 304 | 305 | a - Accept Word: Accept this word as correct for remainder of ispell session (or emacs if you are using ispell in emacs). 306 | 307 | i - Add Word: Add this word to your personal dictionary. This is a file in your home directory called .ispell.words which tells ispell to accept the word as correct every time you use ispell (useful for things like your name). 308 | 309 | <CTRL-G> - Quit Ispell: You can quit ispell at any time by pressing <CTRL-G>. This is done by holding down the CTRL key and pressing "G". 310 | 311 | The man page on ispell lists more options and gives more detailed information on this program. 312 | 313 | ----------------------------------------------------------------- 314 | 315 | M-x spell-buffer 316 | 317 | is a similar program to M-x ispell, but runs off of the unix "spell" program instead of the "ispell" program. The main differences are that spell has a larger vocabulary, but ispell offers suggestions for replacements and allows you to add words to your personal dictionary. 318 | 319 | ----------------------------------------------------------------- 320 | 321 | M-x flyspell-mode 322 | 323 | is a command that is more useful to use when starting to write a document; words will be color-coded as you type them, using the ispell package. The first time a word that it doesn't recognize is encountered, it's colored red, while further instances of the word are colored yellow. 324 | 325 | Once a word is marked as misspelled, you can click on it with the middle mouse button to suggest replacements, or use M-TAB to automatically correct it to what ispell thinks it should be. 326 | 327 | 328 | 329 | An Emacs feature called "Tags" provides an indexing mechanism for Lisp, C, or Fortran source files. Before using "Tags" in Emacs, you need to type this command at the system prompt: 330 | 331 | etags filenames 332 | 333 | ...where 'filenames' is a list of one or more names of the files you wish to index. For example, if you are writing a C program that has two source files, named 'file1.c' and 'file2.c', you would type: 334 | 335 | etags file1.c file2.c 336 | 337 | The 'etags' command creates a file named 'TAGS', which is used by the Emacs "Tags" functions. 338 | 339 | Now you can use the "Tags" functions to locate tags (function or routine names) in your source code. 340 | 341 | Some of the useful "Tags" functions are: 342 | 343 | M-. : Find first definition of a tag. 344 | 345 | M-x tags-search : Search for a specified regular expression through the files in the selected tag table. 346 | 347 | M-, : Find next definition of previous tag, next occurrence of specified regular expression. 348 | 349 | For more information about "Tags", read Section 21.10 of the "GNU Emacs Manual" which is in the documentation racks in all public Athena clusters, or on-line by using the Info Browser in Emacs. (See the stock answer "Using the INFO Browser" for more information.) 350 | 351 | 352 | 353 | On VT240 terminals, the keys Ctrl-s and Ctrl-q will not work properly in Emacs. Instead, you should use Ctrl-~ (for Ctrl-s) and Ctrl-\ (for Ctrl-q). 354 | 355 | When you start Emacs on a VT240 terminal, you will see a warning message to remind you of these changes. 356 | 357 | If you accidentally type Ctrl-s on a VT240, your screen may appear to "freeze". Typing Ctrl-q should get you out of this situation. 358 | 359 | 360 | 361 | If your "delete" key on the terminal you're using isn't acting as you expect it to, it is likely that it is sending the "backspace" character instead of the "delete" character that is expected. This is a common problem with PC's and Macs. There are a few things you can do about this (in order of preference): 362 | 363 | - see if you can tell your terminal emulator (the communications program on your MAC or PC) to use "control-?" when you hit the "backspace" key. 364 | 365 | - you tell athena what to expect for the backspace key. To do this, put the following line in your .startup.tty file: 366 | 367 | stty erase "^H" 368 | or stty erase "^?" 369 | 370 | depending on which of these you normally see when you hit your backspace key. 371 | 372 | That will give you backspace capabilities in everything but emacs. In emacs, add the following lines to your .emacs file (create one if you don't have one, as above): 373 | 374 | (setq term-setup-hook 375 | '(lambda () 376 | (setq keyboard-translate-table "\C-@\C-a\C-b\C-c\C-d\C-e\C-f\C-g\C-?") 377 | (global-set-key "\M-h" 'help-for-help))) 378 | 379 | That will fix the backspace key, and set "M-h" to give you help (regularly c-h does that). 380 | 381 | 382 | 383 | To prevent "^M" from appearing at the ends of lines in emacs shell mode, run these two commands: 384 | 385 | unset lineedit edit 386 | stty nl -echo 387 | 388 | You can also have this done automatically every time you start up a shell mode buffer by having a file called ~/.emacs_tcsh with this line in it: 389 | 390 | unset lineedit edit; stty nl -echo 391 | 392 | 393 | 394 | To remove '^M' (control-M) characters from the end of each line in a file, you can use a shell script called 'clean'. 395 | 396 | To use the shell script, you first need to attach the Consultants' Software Library to your workstation. Use this command: 397 | 398 | add consult 399 | 400 | Now you can type this command: 401 | 402 | clean filename > newfilename 403 | 404 | ...where 'filename' is the name of the file containing the '^M' characters, and 'newfilename' is the name of the file that you want the 'clean' script to create. 405 | 406 | The script takes 'filename' as input, changes each ^M to a newline character, and directs the output to the new file called 'newfilename'. You can check that the new file contains no '^M' characters by viewing it with this command: 407 | 408 | cat -v newfilename 409 | 410 | You can also remove all the control-M characters inside Emacs, though it's a little tricky because Emacs tries to be helpful and treat different OS-style line breaks transparently. To use Emacs to make the replacement, follow these steps: 411 | 412 | 1. type: 413 | 414 | C-x RET C undecided-unix RET C-x C-w RET y 415 | 416 | 2. go to the beginning of the document 417 | 418 | 3. type: 419 | 420 | M-x replace-string RET C-q C-m RET RET 421 | 422 | where "RET" means <press the RETURN key> and things like C-q mean "hold control key and press the q" key. 423 | 424 | 425 | 426 | Please see http://web.mit.edu/answers/emacs/emacs_gnu.html 427 | 428 | 429 | 430 | Emacs can be used with a variety of languages other than English. Mule, or the Multilingual Environment, is packaged with emacs on Athena, and can be accessed under the "Options->Mule (Multilingual Environment)" submenu. 431 | 432 | To start inputting in a different language, you will first need to set the language environment in the Mule menu and then toggle to the desired input method. Some useful key bindings that might help (these commands are also accessible through the Mule menu): 433 | 434 | C-\ : Toggle input method (usually between English and the foreign language you selected) 435 | 436 | C-h I : Describe input method (displays the keyboard layout for an input method) 437 | 438 | 439 | 440 | Emacs has an excellent internal help facility. You can give it a keystroke, and it will tell you the name of the command it executes. Or you can give it a word, and it will tell you the names of several commands that include that word. Emacs' help facility has other features, as well. Some of the most useful ones can be found at: http://web.mit.edu/answers/emacs/emacs_help.html 441 | 442 | To activate help, press C-h ? C-h 443 | 444 | 445 | 446 | Emacs comes with a powerful built-in tool for reading manuals on-line, called the Info Browser. These manuals, or Info files, are in a format called "TeXinfo", because they can be viewed in textual format, using the browser, or they can be converted to LaTeX format for printing. Info files exist in numerous places, for nearly all of the programs in the gnu locker, and for many other utilities and packages as well. 447 | 448 | To get started using the Info Browser, type Control-h i in emacs. This will load a menu of info files to choose from, including the Emacs editor and Info browsers themselves. For a tutorial on how to use the info browser, press "h". 449 | 450 | Each Info file is set up like a tree, with each level consisting of several nodes, each of which contain sub-nodes. Nodes are indicated by a star at the beginning of the line. The basic commands for reading through these trees of nodes are: 451 | 452 | m prompts for a menu item, or "node", and goes to it 453 | space move forward a page (in current node) 454 | delete move backward a page (in current node) 455 | n go to next node 456 | p return to previous node 457 | u go up one level above current node 458 | d return to top level menu 459 | q quits Info browser and returns to original buffer 460 | 461 | The Info browser, however, can be customized: you may extend or shrink menus, or enter bookmarks for commonly needed entries. Information on all this is all included in the node entitled Info. 462 | 463 | Probably the most widely used is the Info file for Emacs. You can examine the Emacs Info node by starting up the Info browser, and then typing mEmacs, followed by return, or by moving the cursor to the line that starts with "* Emacs", and hitting m and return. Here, you can find the *entire* GNU Emacs Manual, and any questions you have about Emacs can almost certainly be found here. If you are unsure of where to look, you can try one of the Indexes: 464 | 465 | Indexes, nodes containing large menus 466 | * Key Index:: An item for each standard Emacs key sequence. 467 | * Command Index:: An item for each command name. 468 | * Variable Index:: An item for each documented variable. 469 | * Concept Index:: An item for each concept. 470 | 471 | Simply move the cursor to the Index of your choice, hit m, and return. 472 | 473 | The default top-level node only contains of six entries, but there are, in fact, over 20 currently on Athena. A list of these is kept in the consult locker. To get a more expansive listing of useful manuals at Athena in the top-level node of your Info browser, add this line to your .emacs file: 474 | 475 | (setq Info-directory "/afs/athena/contrib/consult/lib/info") 476 | 477 | Note that some of these nodes may require that you add the appropriate locker first. Details on how to customize this file are in the Info node entitled "Info". 478 | 479 | Also, if you add a locker and it has an Info file, then that node will be automatically added when you start Info. 480 | 481 | 482 | 483 | Sending foreign-language email can be done using emacs-20. It involves three setup steps. (Additionally, it is easiest if you send mail entirely from within emacs, using M-x mh-rmail to read mail, and M-x mh-smail to send mail.) 484 | 485 | 1) Make sure emacs can display your language's fonts. 486 | 487 | By default, emacs should be able to display the fonts. (An easy test to see if emacs can display non-latin fonts is to type C-h h -- emacs will try to show you "hello" in many languages,using the fonts of those languages.) 488 | 489 | If you are unable to display the non-latin fonts, you may need to place a line in your ~/.Xresources file: 490 | 491 | Emacs.Font: -misc-fixed-medium-r-normal-*-*-120-75-75-*-*-*-* 492 | 493 | 2) Configure emacs to allow you to type text in your language. 494 | 495 | For languages whose characters are not found on English keyboards, it is often possible to type them by configuring emacs to use an alternate input method. A properly configured emacs will allow semi-phonetic input of Chinese or Japanese, for example. 496 | 497 | The keyboard command C-\ instructs emacs to switch to an alternate input method. When emacs prompts you to enter what input method you want, you can type TAB to get it to give you a list of input methods which match what you've typed so far. Once you choose an alternate input method, you can switch between it and English whenever you want by typing C-\ 498 | 499 | IMPORTANT NOTE: It's a good idea to switch back to English input before trying to save your file or to exit emacs, because emacs sometimes asks you questions which must be answered in English. 500 | 501 | Before using this "C-\", it may be useful to tell emacs which language you plan on using most often. Typing C-x C-m l will prompt you to enter the language environment you want to use. Again, you can type TAB to see a list of possible choices. Choose what you want to use, and "C-\" will be automatically configured to be the customary input method for that language. 502 | 503 | 504 | 3) Configure emacs to let you send Mime-encoded email. 505 | 506 | You need to make use of a package called "tm" to properly type and send non-ASCII email. To load "tm", your ~/.emacs file should contain the line: 507 | 508 | (load "/afs/sipb/contrib/emacs/packages/tm-install-dir/share/emacs/site-lisp/mime-setup") 509 | 510 | If this line is in your ~/.emacs file when you start emacs, emacs is configured to be able to send Mime-encoded email. 511 | 512 | 513 | 514 | See http://web.mit.edu/answers/emacs/emacs_scheme.html 515 | 516 | 517 | -------------------------------------------------------------------------------- /doctopics/git.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Overview of Git 4 | 5 | Version Control allows a team to collaborate on a file and keep track of old versions. 6 | 7 | The most basic way to do this with git: 8 | 1) Download the file (as about downloading something) : If do not have the file already, clone the file from a server where it is being hosted. 9 | 2) Make your changes the file. 10 | 3) Commit your changes after you are sure enough that you want to consider them a separate version 11 | 4) 'push' your changes to that same server so that others can use your work. You might find that someone else has edited the file in the meantime and has already pushed thier changes. This means you might have edited the same text, leading to conflicts. In that case, you will need to decide which version to choose. 12 | 13 | 14 | If this is an existing project by jflorey and you are just editing it: 15 | you first need to 16 | $ git clone git://github.com/jflorey/project.git 17 | $ cd ./project 18 | $ git pull 19 | It should reply "Already up-to-date". If it responds with an address error, replace git:// with http:// 20 | you are now ready to edit the file. ask dodona about "upload something" in order to push your changes after you are done. 21 | 22 | You first need to create a directory and initiate it as a git repository 23 | $ mkdir ./project 24 | $ cd ./project 25 | afarrell@ender$ git init 26 | 27 | 28 | In order to get working, you first have to 29 | 30 | 31 | In order to get working, you first have to 32 | 33 | 34 | So now you have edited spam.py and created shrubbery.py in your project. How do you upload that back to jflorey's github repository? 35 | You first need to tell git that you want this added to the "list of things I've changed" 36 | afarrell@ender$ git add spam.py shrubbery.py 37 | you can do this for each file after you are done editing it or in one fell swoop. 38 | you can also remove files 39 | afarrell@ender$ git rm foolish.py 40 | Next, you need to commit to a certain set of changes that you want to make: 41 | afarrell@ender$ git commit 42 | this will give you a screen asking you write a commit message. you should write a short blurb explaining what changes you made 43 | to which files. When you are done, hold down ctrl-shift and hit kx. To abort, hit ctrl-c. 44 | you will then see a message like this: 45 | Created commit 819ed4b: your comments here. 46 | 2 files changed, 18 insertions(+), 0 deletions(-) 47 | create mode 100755 shrubbery.py 48 | 49 | now, you can push that set of changes up to the repository. 50 | afarrell@ender$ git push 51 | 52 | If you want to undo a commit before pushing it, you can do 53 | afarrell@ender$ git reset 54 | this will leave you where you were after you edited the files, but before you added them. It also displays 55 | spam.py shrubbery.py needs update 56 | meaning that, those are the files you had edited. 57 | If you want to completely whipe out your changes you want 58 | afarrell@ender$ git reset --hard 59 | if you want to be left where you were after adding the files, but before comitting them, you want: 60 | afarrell@ender$ git reset --soft 61 | 62 | 63 | In order to get working, you first have to 64 | 65 | 66 | 67 | In order to get working, you first have to 68 | 69 | 70 | -------------------------------------------------------------------------------- /doctopics/mitsfs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Overview of mitsfs 4 | 5 | mit science fiction society 6 | 7 | -------------------------------------------------------------------------------- /doctopics/printing.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Athena provides various methods for printing documents and managaging queues. Please 4 | see the subtopics for more information. 5 | 6 | 7 | To print a file to your default printer, type: 8 | 9 | athena% lpr filename 10 | 11 | If you wish to use a different printer than the default: 12 | 13 | athena% lpr -Pprintername filename 14 | 15 | For printername, use the name of the printer to which you want to send the file (look at the printer if you are uncertain of the name). For filename, use the name of the file (or files) you want to print. For example, to print the file mydoc to the printer ajax, type the following: 16 | 17 | athena% lpr -Pajax mydoc 18 | 19 | You can also use the lpr command to send the output from another command directly to the printer without having to create a file. To do this, "pipe" the output of the command through lpr: 20 | 21 | athena% program_name | lpr -Pprintername 22 | 23 | The | is a vertical bar, also known as a "pipe" (Shift-\ on most keyboards). A pipe takes the output from one program and sends it as the input to another program. You can use this method for any program whose output normally goes to "standard output" (i.e., your screen). For example, if you want a printed copy of the list of files in your directory, send the output from the ls command directly to the printer of your choice by typing: 24 | 25 | athena% ls | lpr -Pprintername 26 | 27 | 28 | 29 | 30 | To print a document double-sided, add a numeral 2 to the regular printername in the print command. For example, to print file mydoc in duplex mode on the printer ajax, type: 31 | 32 | athena% lpr -Pajax2 mydoc 33 | 34 | This sends the job to ajax's duplex queue (ajax2), which adds the necessary PostScript code to enable duplex mode. 35 | 36 | You can also use the 2 appendix to specify double-sided output with all other printing commands. For example: 37 | 38 | athena% setenv PRINTER ajax2 39 | athena% ls | lpr -Pajax2 40 | athena% dvips -Pajax2 mydoc.dvi 41 | 42 | By default, when duplex mode is activated, the text is read by flipping the page about a vertical axis, i.e., the top of side one and the top of side two are along the same edge. If you want this to be inverted, so that you would flip the page about a horizontal axis, this is called tumble mode. (Tumble mode is useful if you're printing in landscape orientation - that is, sideways on the paper.) Options for either of these modes are given below. 43 | 44 | To print normal text or a PostScript file, you can use the lpr2 command in the consult locker. To do so, type: 45 | 46 | athena% add consult 47 | athena% lpr2 -d -Pprinter filename 48 | 49 | The -d option turns on duplex mode for the given files. You may also use any other options associated with lpr, such as -h or -z. 50 | 51 | For tumble mode, use -m instead of -d. 52 | 53 | lpr2 does not work with standard input. This means that you cannot pipe things through lpr2 in the fashion that you can pipe them through lpr. 54 | 55 | 56 | 57 | 58 | 59 | The lpr command sends a copy of your job to a print server, a machine that keeps track of printing requests in a list called a print queue. Because you share a printer with other people, the print server takes the jobs submitted to it and sends them out to the printer one by one in order. 60 | 61 | If your file does not print right away, it might be waiting in line for the printer. To find out what print jobs are waiting to be printed, type lpq at your Athena prompt. For a printer different from your default, use: 62 | 63 | athena% lpq -Pprintername 64 | 65 | For example: 66 | 67 | athena% lpq -Pajax 68 | PAPER-PUSHER.MIT.EDU... ajax is ready and printing 69 | Rank Owner Job Files Total Size 70 | active joeuser 2 report.abstract.PS 8069 bytes 71 | 1st janeuser 3 letter.PS 12841 bytes 72 | 2nd joeuser 3 lab.report.PS 19942 bytes 73 | 74 | Specifying ajax or ajax2 shows all the jobs in line for that printer. The lpq command also gives limited information about the physical status of the printer. 75 | 76 | You might also receive Zephyr windowgrams from the print server telling you about problems. For example, if the printer runs out of paper while your job is printing, you may receive a zephyr telling you so. 77 | 78 | 79 | If you want to send your file to a different printer (e.g., if the printer is down or the queue is too long), or if you sent the wrong file or no longer want the printout, you can remove your job from the queue. To remove an entry from the queue: 80 | 81 | athena% lprm jobnumber 82 | 83 | Here, jobnumber is the number in the "Job" column of the lpq information. For example, to remove the file lab.report.PS from the print queue for ajax, jruser would type the following command: 84 | 85 | athena% lprm -Pajax 3 86 | 87 | If you want to remove all of your jobs on the printer, type: 88 | 89 | athena% lprm - 90 | 91 | The final dash is important. 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /doctopics/topics.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /doctopics/words.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Overview of words 4 | 5 | bar baz qux 6 | 7 | -------------------------------------------------------------------------------- /doctopics/yaks.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Overview of yaks 4 | 5 | any seemingly pointless activity which is actually necessary to solve a problem which solves a problem which, several levels of recursion later, solves the real problem you're working on. 6 | 7 | -------------------------------------------------------------------------------- /doctopics/zephyr.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Zephyr is an instant messaging system developed at MIT for Project 4 | Athena. 5 | 6 | Zephyr is an instant messaging system developed at MIT for Project 7 | Athena. 8 | 9 | 10 | -------------------------------------------------------------------------------- /dodona: -------------------------------------------------------------------------------- 1 | python dodona.py -c dodona -------------------------------------------------------------------------------- /dodona.py: -------------------------------------------------------------------------------- 1 | import site 2 | site.addsitedir('/afs/athena.mit.edu/user/b/r/broder/lib/python2.5/site-packages') 3 | import zephyr 4 | from zephyrUI import IO 5 | from fuzzystack import FuzzyStack 6 | from session import Session 7 | from xml_parser import load_topics 8 | import traceback 9 | from optparse import OptionParser 10 | 11 | ################################### 12 | # This file runs Dodona. It keeps 13 | # a list of "sessions", that is, 14 | # the conversations she is having 15 | # with different users. 16 | ################################### 17 | 18 | parser = OptionParser() 19 | parser.add_option("-c", "--class", dest="cls", default="dodona-test", help="set the class which Dodona listens on") 20 | 21 | (options, args) = parser.parse_args() 22 | cls = options.cls 23 | 24 | sessions = {} 25 | # load the data the Dodona pulls from 26 | topics = load_topics("doctopics/topics.xml") 27 | if not cls: cls = "dodona-test" 28 | bot = IO(cls) 29 | print "\nDodona successfully started on class " + cls + "!\n" 30 | 31 | while True: 32 | # recieve a message and return the sender as well 33 | m = bot.receive_from_subs(True) 34 | (mess, sender) = m 35 | sender = sender.partition("@")[0] 36 | # if the session with this sender does not 37 | # already exist, then create it 38 | if not sessions.has_key(sender): 39 | sessions[sender] = Session(sender, topics, bot) 40 | # add the message to the memory 41 | sessions[sender].memory.push("message", mess) 42 | 43 | # parse the message 44 | try: 45 | exit = sessions[sender].question() 46 | except KeyboardInterrupt: 47 | bot.send("Dodona is no longer running.") 48 | raise 49 | except: 50 | print traceback.format_exc() 51 | else: 52 | print "status:", sessions[sender].memory.read("status") 53 | print "exit:", exit 54 | # reset the session and prompt the user to 55 | # ask another question 56 | if exit == "reset": 57 | sessions[sender].clear() 58 | # if the user wants to exit, then delete 59 | # the session 60 | elif exit == "exit": 61 | del sessions[sender] 62 | -------------------------------------------------------------------------------- /fuzzystack.py: -------------------------------------------------------------------------------- 1 | # Fuzzy stack 2 | # 10 Jan 2009 kmill 3 | # Something between a stack, a priority queue, and a dictionary 4 | # Hopefully useful for NLP 5 | 6 | class FuzzyStack : 7 | def __init__(self, depth=4) : 8 | self.data = list() 9 | self.depth = depth 10 | 11 | #returns a string representing the data in dictionary form. 12 | def __str__(self): 13 | d = self.makeDict() 14 | p = "" 15 | for key in d.keys(): 16 | p = p + str(key) + ": " 17 | if isinstance(d[key], dict): 18 | p = p + str(d[key].keys()) + "\n" 19 | else: 20 | p = p + str(d[key]) + "\n" 21 | return p 22 | 23 | # Pushes a new key/value pair onto the dictionary 24 | def push(self, symbol, value) : 25 | # Truncate the stack to the desired length if necessary 26 | if len(self.data) == self.depth : 27 | self.rpop(symbol) 28 | if len(self.data) == self.depth : 29 | self.popoldest() 30 | self.data.insert(0, (symbol, value)); 31 | 32 | # Returns a dictionary of the most relevant keys 33 | def makeDict(self) : 34 | output = dict() 35 | for d in reversed(self.data) : 36 | output[d[0]] = d[1] 37 | return output 38 | 39 | # Retrieve a key 40 | def read(self, symbol) : 41 | d = self.makeDict() 42 | if d.has_key(symbol): return d[symbol] 43 | return None 44 | 45 | # Count the number of records with the given key 46 | def countSymbols(self, symbol) : 47 | return len([0 for d in self.data if d[0] == symbol]) 48 | 49 | # get index^th record with a given key 50 | def readIndex(self, symbol, index) : 51 | return [d[1] for d in self.data if d[0] == symbol][index] 52 | 53 | # An iterator to do the previous function 54 | def values(self, symbol) : 55 | return [d[1] for d in self.data if d[0] == symbol].__iter__() 56 | 57 | # Sees what's on top of the stack 58 | def peek(self) : 59 | return self.data[0]; 60 | 61 | # Pop off the data of a given key 62 | def pop(self, symbol) : 63 | for d in self.data : 64 | if(symbol == d[0]) : 65 | self.data.remove(d) 66 | return d 67 | return False 68 | 69 | # Pop off the oldest occurrance of a key 70 | def rpop(self, symbol) : 71 | index = -1 72 | for i in range(0, len(self.data)) : 73 | if(symbol == self.data[i][0]) : 74 | index = i 75 | if index >= 0 : 76 | return self.data.pop(index) 77 | else : 78 | return None 79 | 80 | # Pop off the key which is farthest down and has the most siblings 81 | def popoldest(self) : 82 | index = -1 83 | maxnum = 0 84 | keys = dict() 85 | for i in range(0, len(self.data)) : 86 | if not keys.has_key(self.data[i][0]) : 87 | keys[self.data[i][0]] = 0 88 | else : 89 | keys[self.data[i][0]] += 1 90 | if keys[self.data[i][0]] >= maxnum : 91 | maxnum = keys[self.data[i][0]] 92 | index = i 93 | if index >= 0 : 94 | return self.data.pop(index) 95 | else : 96 | return None 97 | 98 | -------------------------------------------------------------------------------- /helper.py: -------------------------------------------------------------------------------- 1 | from textwrap import fill 2 | 3 | def print_list(list): 4 | """ 5 | Return a nicely formatted list 6 | (of topics, for example) 7 | """ 8 | list.sort() 9 | printed = "" 10 | for item in list: 11 | 12 | if str(item).startswith("default"): continue 13 | printed = printed + " - " + str(item) + "\n" 14 | return printed 15 | 16 | def custom_fill(s): 17 | """ 18 | Perfoms the same function as fill, except 19 | that custom_fill preserves newlines. 20 | """ 21 | news = "" 22 | while s.partition("\n")[2] != "": 23 | news += fill(s.partition("\n")[0]) + "\n" 24 | s = s.partition("\n")[2] 25 | news += fill(s.partition("\n")[0]) 26 | return news 27 | 28 | def tokenize(mess): 29 | """ 30 | Split the sentence into a list, which contains words and some 31 | punctuation, but no whitespace. 32 | """ 33 | mess = mess.replace(",", " , ") 34 | mess = mess.replace(".", " . ") 35 | mess = mess.replace("?", " ? ") 36 | mess = mess.replace("!", " ! ") 37 | mess = mess.replace("\'s ", " \'s ") 38 | mess = mess.split(" ") 39 | temp = mess 40 | offset = 0 41 | 42 | for w in xrange(len(temp)): 43 | if mess[w-offset] == "": 44 | del mess[w-offset] 45 | offset += 1 46 | 47 | return mess 48 | -------------------------------------------------------------------------------- /nlp.py: -------------------------------------------------------------------------------- 1 | from nltk.parse.featurechart import EarleyChartParser 2 | from nltk.grammar import ContextFreeGrammar, Production 3 | from nltk.grammar import Nonterminal as NT 4 | from nltk.tree import Tree 5 | from parsetree import * 6 | import re 7 | 8 | # sentence types 9 | QUESTION = 1 10 | STATEMENT = 2 11 | COMMAND = 3 12 | 13 | def get_sentence_type(parse): 14 | """ 15 | Determines the sentence type recursively, based on the rules the 16 | tree is built out of. 17 | """ 18 | if isinstance(parse, str): 19 | return 0 20 | 21 | lhs = parse.productions()[0].lhs() 22 | if lhs == NT("Ind_Clause_Ques") or \ 23 | lhs == NT("Ind_Clause_Ques_Aux"): 24 | return QUESTION 25 | elif lhs == NT("Ind_Clause") or \ 26 | lhs == NT("Ind_Clause_Pl"): 27 | if parse.productions()[0].rhs()[0] == NT("VP_Inf"): 28 | return COMMAND 29 | else: 30 | return STATEMENT 31 | 32 | for subtree in parse: 33 | type = get_sentence_type(subtree) 34 | if type: return type 35 | 36 | return 0 37 | 38 | def find_PP(parse): 39 | """ 40 | Finds the first prepositional phrase in the parse. 41 | """ 42 | if isinstance(parse, str): return None 43 | tree = parse.productions()[0] 44 | 45 | if tree.lhs() == NT("PP"): 46 | return parse[-1] 47 | else: 48 | for subtree in parse: 49 | pp = find_PP(subtree) 50 | if pp: return pp 51 | 52 | return None 53 | 54 | def find_noun(parse, exceptions=[]): 55 | """ 56 | Finds the first noun in the parse. 57 | """ 58 | if isinstance(parse, str): return None 59 | tree = parse.productions()[0] 60 | 61 | if (tree.lhs() == NT("NP") or \ 62 | tree.lhs() == NT("NP_1st") or \ 63 | tree.lhs() == NT("NP_2nd") or \ 64 | tree.lhs() == NT("NP_3rd") or \ 65 | tree.lhs() == NT("NP_1st_Pl") or \ 66 | tree.lhs() == NT("NP_3rd_Pl") or \ 67 | tree.lhs() == NT("NP_Obj") or \ 68 | tree.lhs() == NT("Name") or \ 69 | tree.lhs() == NT("Place") or \ 70 | tree.lhs() == NT("Program") or \ 71 | tree.lhs() == NT("Org") or \ 72 | tree.lhs() == NT("Field") or \ 73 | tree.lhs() == NT("Nominal") or \ 74 | tree.lhs() == NT("Command") or \ 75 | tree.lhs() == NT("File_Addr") or \ 76 | tree.lhs() == NT("Web_Addr") or \ 77 | tree.lhs() == NT("CompoundNoun") or \ 78 | tree.lhs() == NT("Noun") or \ 79 | tree.lhs() == NT("Noun_Pl") or \ 80 | tree.lhs() == NT("Nominal") or \ 81 | tree.lhs() == NT("Nominal_Pl")) and \ 82 | " ".join(parse.leaves()) not in exceptions: 83 | return parse 84 | else: 85 | for subtree in parse: 86 | n = find_noun(subtree, exceptions) 87 | if n: return n 88 | 89 | return None 90 | 91 | def find_compound_noun(parse): 92 | """ 93 | Finds the first compound noun in the parse. 94 | """ 95 | if isinstance(parse, str): return None 96 | tree = parse.productions()[0] 97 | 98 | if tree.lhs() == NT("CompoundNoun") or \ 99 | tree.lhs() == NT("CompoundNoun_Pl"): 100 | return parse 101 | else: 102 | for subtree in parse: 103 | c = find_compound_noun(subtree) 104 | if c: return c 105 | 106 | return None 107 | 108 | def find_after_verb(parse): 109 | """ 110 | Finds the first "After_Verb_*" structure in the parse. 111 | """ 112 | if isinstance(parse, str): return None 113 | tree = parse.productions()[0] 114 | 115 | if tree.lhs() == NT("After_Verb_Tr") or \ 116 | tree.lhs() == NT("After_Verb_In"): 117 | return parse 118 | else: 119 | for subtree in parse: 120 | subj = find_after_verb(subtree) 121 | if subj: return subj 122 | 123 | def find_topic(parse, type=None, qword=None): 124 | """ 125 | Finds the topic of a sentence, based on the sentence type: 126 | either QUESTION, STATEMENT, or COMMAND. 127 | """ 128 | 129 | # find the sentence type if it's not specified 130 | if type == None: type = get_sentence_type(parse) 131 | if isinstance(parse, str): return None 132 | tree = parse.productions()[0] 133 | print type, "- tree:", tree 134 | 135 | # for questions 136 | if type == QUESTION: 137 | 138 | # All questions start with the "Ind_Clause_Ques*" structure. 139 | # After that, there are several possibilities: 140 | # - VP_3rd 141 | # - Ind_Clause_Ques_Aux 142 | # - Interrog_Clause 143 | # - Ind_Clause_Inf* 144 | # Depending on which one of these comes next, keep searching 145 | # for the topic. 146 | if tree.lhs() == NT("Ind_Clause_Ques") or \ 147 | tree.lhs() == NT("Ind_Clause_Ques_Aux"): 148 | if not qword: 149 | qword = parse[0].leaves()[0] 150 | print "qword:", qword 151 | 152 | rhs = tree.rhs() 153 | if rhs[-1] == NT("VP_3rd"): 154 | print "VP_3rd" 155 | #return parse[-1][-1], qword 156 | t = find_after_verb(parse[-1][-1]) 157 | if not t: 158 | t = find_PP(parse[-1][-1]) 159 | 160 | return t, qword 161 | 162 | # this acts just like a statement, so call find_topic 163 | # again, but specifying the type=STATEMENT 164 | elif rhs[-1] == NT("Ind_Clause_Ques_Aux"): 165 | print "Ind_Clause_Ques_Aux" 166 | return find_topic(parse[-1][-1], type=STATEMENT), qword 167 | 168 | elif rhs[-1] == NT("Interrog_Clause"): 169 | print "Interrog_Clause" 170 | t = find_after_verb(parse[-1][-1]) 171 | if not t: 172 | t = find_PP(parse[-1][-1]) 173 | return t, qword 174 | 175 | # this acts just like a statement, so call find_topic 176 | # again, but specifying the type=STATEMENT 177 | elif rhs[-1] == NT("Ind_Clause_Inf") or \ 178 | rhs[-1] == NT("Ind_Clause_Inf_3rd"): 179 | print "Ind_Clause_Inf" 180 | return find_topic(parse[-1], type=STATEMENT), qword 181 | else: 182 | for subtree in parse: 183 | subj = find_topic(subtree, type) 184 | if subj: return subj 185 | 186 | # for statements 187 | elif type == STATEMENT: 188 | if tree.lhs() == NT("VP_1st") or \ 189 | tree.lhs() == NT("VP_Inf"): 190 | t = find_after_verb(parse[-1][-1]) 191 | if not t: 192 | t = find_PP(parse[-1][-1]) 193 | return t 194 | else: 195 | for subtree in parse: 196 | subj = find_topic(subtree, type) 197 | if subj: return subj 198 | 199 | # for commands 200 | elif type == COMMAND: 201 | if tree.lhs() == NT("VP_Inf"): 202 | rhs = tree.rhs() 203 | if rhs[-1] == NT("PP"): 204 | return parse[-1] 205 | # elif \ 206 | # rhs[-1] == NT("After_Verb_Tr") or \ 207 | # rhs[-1] == NT("After_Verb_In") or \ 208 | # rhs[-1] == NT("V_Inf_In_Neg") or \ 209 | # rhs[-1] == NT("VP_Inf") or \ 210 | # rhs[-1] == NT("NP_Obj"): 211 | else: 212 | return find_after_verb(parse) 213 | 214 | elif tree.lhs() == NT("PP"): 215 | return parse[-1] 216 | else: 217 | for subtree in parse: 218 | subj = find_topic(subtree, type) 219 | if subj: return subj 220 | 221 | return None 222 | -------------------------------------------------------------------------------- /parsetree.py: -------------------------------------------------------------------------------- 1 | from nltk.parse.featurechart import EarleyChartParser 2 | from nltk.grammar import ContextFreeGrammar, Production 3 | from nltk.grammar import Nonterminal as NT 4 | import random 5 | import traceback 6 | 7 | ####################################### 8 | # The Parser class reads in grammar 9 | # rules and vocab rules from two files, 10 | # and creates a ContextFreeGrammar and 11 | # EarleyChartParser. 12 | ###################################### 13 | 14 | class Parser: 15 | def __init__(self, rules_file="rules.gr", vocab_file="vocabulary.gr"): 16 | """ 17 | Reads in grammar rules (from rules_file) and vocab rules (from 18 | vocab_file) and creates self.cfg (a ContextFreeGrammar) and 19 | self.parser (a EarleyChartParser). 20 | """ 21 | self.rules = [] 22 | test_sentences = [] 23 | 24 | # get the rules from rules_file 25 | grammar = open(rules_file, "r") 26 | line = grammar.readline() 27 | while line: 28 | if line.strip() != "" and not line.strip().startswith("#"): 29 | line = line[2:] 30 | parts = line.partition("\t") 31 | lhs = parts[0].strip() 32 | rhs = [NT(x) for x in parts[2].strip().split(" ")] 33 | self.rules.append(Production(NT(lhs), rhs)) 34 | line = grammar.readline() 35 | grammar.close() 36 | 37 | # get the rules from vocab_file 38 | vocab = open(vocab_file, "r") 39 | line = vocab.readline() 40 | while line: 41 | if line.strip() != "" and not line.strip().startswith("#"): 42 | line = line[2:] 43 | parts = line.partition("\t") 44 | lhs = parts[0].strip() 45 | rhs = parts[2].strip().lower().split(" ") 46 | self.rules.append(Production(NT(lhs), rhs)) 47 | line = vocab.readline() 48 | vocab.close() 49 | 50 | # create the grammar and parser 51 | self.cfg = ContextFreeGrammar(NT("S"), self.rules) 52 | self.parser = EarleyChartParser(self.cfg, trace=0) 53 | 54 | def add_new_vocab_rule(self, rule): 55 | """ 56 | Adds a new vocabulary rule to the set of rules, and 57 | recreates self.cfg and self.parser. 58 | """ 59 | self.rules.append(Production(NT(rule[0]), rule[1])) 60 | self.cfg = ContextFreeGrammar(NT("S"), self.rules) 61 | self.parser = EarleyChartParser(self.cfg, trace=0) 62 | 63 | def parse_file(self, file): 64 | """ 65 | Parses sentences in a file. 66 | """ 67 | sens = open(file, "r") 68 | line = sens.readline() 69 | while line: 70 | test_sentences.append(line.strip().split(" ")) 71 | line = sens.readline() 72 | sens.close() 73 | 74 | for sen in test_sentences: 75 | parse = self.parser.nbest_parse(sen, trace=0) 76 | if parse: print parse[0] 77 | else: print "failure" 78 | 79 | def parse_sent(self, sen): 80 | """ 81 | Parses a single sentence. Returns the parse, or returns a 82 | tuple (None, foreign_words). 83 | """ 84 | foreign = [] 85 | try: 86 | parse = self.parser.nbest_parse(sen.strip().split(" "), trace=0) 87 | except: 88 | sen = sen.strip().split(" ") 89 | for word in sen: 90 | if not self.cfg.covers([word]): foreign.append(word) 91 | parse = None 92 | 93 | if parse: 94 | #for p in parse: print p 95 | return parse[0] 96 | else: 97 | print "failure" 98 | return None, foreign 99 | 100 | def parse_NP(self, sen): 101 | """ 102 | Parses a partial sentence (that is, usually a noun phrase. 103 | Returns the parse, or returns a tuple. 104 | """ 105 | try: 106 | cfg_temp = ContextFreeGrammar(NT("NP"), self.rules) 107 | parser_temp = EarleyChartParser(cfg_temp, trace=0) 108 | parse = parser_temp.nbest_parse(sen.strip().split(" "), trace=0) 109 | except: 110 | print traceback.format_exc() 111 | else: 112 | if parse: 113 | return parse[0] 114 | 115 | print "failure" 116 | return None 117 | 118 | def rand_sent(self): 119 | """ 120 | Creates a random sentence from self.cfg. 121 | """ 122 | poss = self.cfg.productions(lhs=NT("S")) 123 | if len(poss) > 1: 124 | index = random.randint(0,len(poss)-1) 125 | elif len(poss) == 1: index = 0 126 | else: 127 | print left 128 | return None 129 | 130 | sen = [] 131 | print poss[index] 132 | for nt in poss[index].rhs(): 133 | if isinstance(nt, NT): 134 | sen.append(rand_sent(nt)) 135 | else: sen.append(nt) 136 | 137 | return " ".join(sen) 138 | -------------------------------------------------------------------------------- /rules.gr: -------------------------------------------------------------------------------- 1 | 1 START S 2 | 3 | 1 S Noun Comma Ind_Clause_Ques PuncQ 4 | 1 S Noun Comma Ind_Clause_Ques_Aux PuncQ 5 | 1 S Noun Comma Ind_Clause Punc 6 | 1 S Ind_Clause Punc 7 | 1 S Ind_Clause_Ques PuncQ 8 | 1 S Ind_Clause_Ques_Aux PuncQ 9 | 1 S Ind_Clause Comma Noun PuncQ 10 | 1 S Ind_Clause_Ques Comma Noun PuncQ 11 | 1 S Ind_Clause_Ques_Aux Comma Noun PuncQ 12 | 1 S Ind_Clause Comma Subord_Conj Ind_Clause Punc 13 | 1 S Noun Comma Ind_Clause Comma Subord_Conj Ind_Clause Punc 14 | 1 S Ind_Clause Subord_Conj Ind_Clause Punc 15 | 1 S Noun Comma Ind_Clause Subord_Conj Ind_Clause Punc 16 | 17 | 1 Ind_Clause_Ques Interrog_Det VP_3rd 18 | 1 Ind_Clause_Ques Interrog_Det VP_3rd Prep 19 | 20 | 1 Ind_Clause_Ques Interrog_Det Ind_Clause_Ques_Aux 21 | 1 Ind_Clause_Ques Interrog_Proadverb Ind_Clause_Ques_Aux 22 | 23 | 1 Ind_Clause_Ques Interrog_Proadverb Interrog_Clause 24 | 1 Ind_Clause_Ques Interrog_Proadverb AdjP Interrog_Clause 25 | 1 Ind_Clause_Ques Interrog_Clause 26 | 27 | 1 Ind_Clause_Ques Interrog_Proadverb AdjP Aux Ind_Clause_Inf 28 | 1 Ind_Clause_Ques Interrog_Proadverb AdjP Aux_3rd Ind_Clause_Inf_3rd 29 | 1 Ind_Clause_Ques Interrog_Det Modal_Past Ind_Clause_Inf 30 | 1 Ind_Clause_Ques Interrog_Det NP Modal_Past Ind_Clause_Inf 31 | 32 | 1 Ind_Clause_Ques Interrog_Proadverb Aux 33 | 34 | 1 Ind_Clause_Ques_Aux Aux Ind_Clause_Inf_2nd 35 | 1 Ind_Clause_Ques_Aux Aux Ind_Clause_Inf 36 | 1 Ind_Clause_Ques_Aux Aux_3rd Ind_Clause_Inf_3rd 37 | 38 | 1 Ind_Clause NP_1st VP_1st 39 | 1 Ind_Clause NP_2nd VP_2nd 40 | 1 Ind_Clause NP_3rd VP_3rd 41 | 1 Ind_Clause VP_Inf 42 | 1 Ind_Clause_Pl NP_1st_Pl VP_1st_Pl 43 | 1 Ind_Clause_Pl NP_3rd_Pl VP_3rd_Pl 44 | 45 | 1 Ind_Clause_Inf NP VP_Inf 46 | 1 Ind_Clause_Inf_3rd NP_3rd VP_Inf 47 | 48 | 1 Interrog_Clause Passive_Interrog_In 49 | 1 Interrog_Clause Passive_Interrog_Tr 50 | 51 | 1 Passive_1stSing_Pres Be_1stSing_Pres 52 | 1 Passive_2ndSing_Pres Be_2ndSing_Pres 53 | 1 Passive_3rdSing_Pres Be_3rdsing_Pres 54 | 1 Passive_1stPlur_Pres Be_1stPlur_Pres 55 | 1 Passive_3rdPlur_Pres Be_2ndPlur_Pres 56 | 1 Passive_1stSing_Past Be_1stSing_Past 57 | 1 Passive_2ndSing_Past Be_2ndSing_Past 58 | 1 Passive_3rdSing_Past Be_3rdsing_Past 59 | 1 Passive_1stPlur_Past Be_1stPlur_Past 60 | 1 Passive_3rdPlur_Past Be_2ndPlur_Past 61 | 62 | 1 Passive_1stSing_Pres Modal_Pres 63 | 1 Passive_2ndSing_Pres Modal_Pres 64 | 1 Passive_3rdSing_Pres Modal_Pres 65 | 1 Passive_1stPlur_Pres Modal_Pres 66 | 1 Passive_3rdPlur_Pres Modal_Pres 67 | 1 Passive_1stSing_Past Modal_Past 68 | 1 Passive_2ndSing_Past Modal_Past 69 | 1 Passive_3rdSing_Past Modal_Past 70 | 1 Passive_1stPlur_Past Modal_Past 71 | 1 Passive_3rdPlur_Past Modal_Past 72 | 73 | 1 Passive_1stSing_Pres Modal_Pres_Neg 74 | 1 Passive_2ndSing_Pres Modal_Pres_Neg 75 | 1 Passive_3rdSing_Pres Modal_Pres_Neg 76 | 1 Passive_1stPlur_Pres Modal_Pres_Neg 77 | 1 Passive_3rdPlur_Pres Modal_Pres_Neg 78 | 1 Passive_1stSing_Past Modal_Past_Neg 79 | 1 Passive_2ndSing_Past Modal_Past_Neg 80 | 1 Passive_3rdSing_Past Modal_Past_Neg 81 | 1 Passive_1stPlur_Past Modal_Past_Neg 82 | 1 Passive_3rdPlur_Past Modal_Past_Neg 83 | 84 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st V_Pres_Part_In 85 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd V_Pres_Part_In 86 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd V_Pres_Part_In 87 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl V_Pres_Part_In 88 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl V_Pres_Part_In 89 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st V_Pres_Part_Tr 90 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd V_Pres_Part_Tr 91 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd V_Pres_Part_Tr 92 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl V_Pres_Part_Tr 93 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl V_Pres_Part_Tr 94 | 95 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st V_Pres_Part_In 96 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd V_Pres_Part_In 97 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd V_Pres_Part_In 98 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl V_Pres_Part_In 99 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl V_Pres_Part_In 100 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st V_Pres_Part_Tr 101 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd V_Pres_Part_Tr 102 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd V_Pres_Part_Tr 103 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl V_Pres_Part_Tr 104 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl V_Pres_Part_Tr 105 | 106 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st VP_Inf 107 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd VP_Inf 108 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd VP_Inf 109 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl VP_Inf 110 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl VP_Inf 111 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st VP_Inf 112 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd VP_Inf 113 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd VP_Inf 114 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl VP_Inf 115 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl VP_Inf 116 | 117 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st VP_Inf 118 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd VP_Inf 119 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd VP_Inf 120 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl VP_Inf 121 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl VP_Inf 122 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st VP_Inf 123 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd VP_Inf 124 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd VP_Inf 125 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl VP_Inf 126 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl VP_Inf 127 | 128 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st 129 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd 130 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd 131 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl 132 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl 133 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st 134 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd 135 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd 136 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl 137 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl 138 | 139 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st 140 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd 141 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd 142 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl 143 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl 144 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st 145 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd 146 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd 147 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl 148 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl 149 | 150 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st AdjP 151 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd AdjP 152 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd AdjP 153 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl AdjP 154 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl AdjP 155 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st AdjP 156 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd AdjP 157 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd AdjP 158 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl AdjP 159 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl AdjP 160 | 161 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st AdjP 162 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd AdjP 163 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd AdjP 164 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl AdjP 165 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl AdjP 166 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st AdjP 167 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd AdjP 168 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd AdjP 169 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl AdjP 170 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl AdjP 171 | 172 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st AdjP After_Verb_In 173 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd AdjP After_Verb_In 174 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd AdjP After_Verb_In 175 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl AdjP After_Verb_In 176 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl AdjP After_Verb_In 177 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st AdjP After_Verb_In 178 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd AdjP After_Verb_In 179 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd AdjP After_Verb_In 180 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl AdjP After_Verb_In 181 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl AdjP After_Verb_In 182 | 183 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st AdjP After_Verb_In 184 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd AdjP After_Verb_In 185 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd AdjP After_Verb_In 186 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl AdjP After_Verb_In 187 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl AdjP After_Verb_In 188 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st AdjP After_Verb_In 189 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd AdjP After_Verb_In 190 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd AdjP After_Verb_In 191 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl AdjP After_Verb_In 192 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl AdjP After_Verb_In 193 | 194 | 1 Passive_Interrog_In Passive_1stSing_Pres NP_1st After_Verb_In 195 | 1 Passive_Interrog_In Passive_2ndSing_Pres NP_2nd After_Verb_In 196 | 1 Passive_Interrog_In Passive_3rdSing_Pres NP_3rd After_Verb_In 197 | 1 Passive_Interrog_In Passive_1stPlur_Pres NP_1st_Pl After_Verb_In 198 | 1 Passive_Interrog_In Passive_3rdPlur_Pres NP_3rd_Pl After_Verb_In 199 | 1 Passive_Interrog_Tr Passive_1stSing_Pres NP_1st After_Verb_In 200 | 1 Passive_Interrog_Tr Passive_2ndSing_Pres NP_2nd After_Verb_In 201 | 1 Passive_Interrog_Tr Passive_3rdSing_Pres NP_3rd After_Verb_In 202 | 1 Passive_Interrog_Tr Passive_1stPlur_Pres NP_1st_Pl After_Verb_In 203 | 1 Passive_Interrog_Tr Passive_3rdPlur_Pres NP_3rd_Pl After_Verb_In 204 | 205 | 1 Passive_Interrog_In Passive_1stSing_Past NP_1st After_Verb_In 206 | 1 Passive_Interrog_In Passive_2ndSing_Past NP_2nd After_Verb_In 207 | 1 Passive_Interrog_In Passive_3rdSing_Past NP_3rd After_Verb_In 208 | 1 Passive_Interrog_In Passive_1stPlur_Past NP_1st_Pl After_Verb_In 209 | 1 Passive_Interrog_In Passive_3rdPlur_Past NP_3rd_Pl After_Verb_In 210 | 1 Passive_Interrog_Tr Passive_1stSing_Past NP_1st After_Verb_In 211 | 1 Passive_Interrog_Tr Passive_2ndSing_Past NP_2nd After_Verb_In 212 | 1 Passive_Interrog_Tr Passive_3rdSing_Past NP_3rd After_Verb_In 213 | 1 Passive_Interrog_Tr Passive_1stPlur_Past NP_1st_Pl After_Verb_In 214 | 1 Passive_Interrog_Tr Passive_3rdPlur_Past NP_3rd_Pl After_Verb_In 215 | 216 | 1 VP VP_1st 217 | 1 VP VP_2nd 218 | 1 VP VP_3rd 219 | 1 VP_Pl VP_1st_Pl 220 | 1 VP_Pl VP_2nd_Pl 221 | 1 VP_Pl VP_3rd_Pl 222 | 1 VP Adv VP 223 | 1 VP VP Adv 224 | 1 VP_Pl Adv VP_Pl 225 | 1 VP_Pl VP_Pl Adv 226 | 227 | 1 VP_1st Being_1stSing_Pres AdjP 228 | 1 VP_2nd Being_2ndSing_Pres AdjP 229 | 1 VP_3rd Being_3rdSing_Pres AdjP 230 | 1 VP_1st_Pl Being_1stPlur_Pres AdjP 231 | 1 VP_2nd_Pl Being_2ndPlur_Pres AdjP 232 | 1 VP_3rd_Pl Being_3rdPlur_Pres AdjP 233 | 1 VP_1st Being_1stSing_Pres AdjP PP 234 | 1 VP_2nd Being_2ndSing_Pres AdjP PP 235 | 1 VP_3rd Being_3rdSing_Pres AdjP PP 236 | 1 VP_1st_Pl Being_1stPlur_Pres AdjP PP 237 | 1 VP_2nd_Pl Being_2ndPlur_Pres AdjP PP 238 | 1 VP_3rd_Pl Being_3rdPlur_Pres AdjP PP 239 | 240 | 1 VP_1st Exp_1stSing_Pres Infl Ind_Clause 241 | 1 VP_2nd Exp_2ndSing_Pres Infl Ind_Clause 242 | 1 VP_3rd Exp_3rdSing_Pres Infl Ind_Clause 243 | 1 VP_1st_Pl Exp_1stPlur_Pres Infl Ind_Clause 244 | 1 VP_2nd_Pl Exp_2ndPlur_Pres Infl Ind_Clause 245 | 1 VP_3rd_Pl Exp_3rdPlur_Pres Infl Ind_Clause 246 | 1 V_Inf_Tr Exp_Inf Infl Ind_Clause 247 | 1 V_Inf_In Exp_Inf Infl Ind_Clause 248 | 1 V_Inf_Tr Exp_Inf Interrog_Proadverb Ind_Clause 249 | 1 V_Inf_Tr Exp_Inf Interrog_Proadverb Nominal 250 | 1 V_Inf_Tr Exp_Pres_Part Infl Ind_Clause 251 | 1 V_Inf_In Exp_Pres_Part Infl Ind_Clause 252 | 1 V_Inf_Tr Exp_Past_Part Infl Ind_Clause 253 | 1 V_Inf_In Exp_Past_Part Infl Ind_Clause 254 | 255 | 1 VP_1st Causal_1stSing_Pres NP_Obj V_Past_Part_Tr 256 | 1 VP_1st Causal_1stSing_Pres NP_Obj V_Past_Part_Tr PP 257 | 1 VP_1st Causal_1stSing_Pres NP_Obj V_Past_Part_In 258 | 1 VP_1st Causal_1stSing_Pres NP_Obj V_Past_Part_In PP 259 | 260 | 1 VP_2nd Causal_2ndSing_Pres NP_Obj V_Past_Part_Tr 261 | 1 VP_2nd Causal_2ndSing_Pres NP_Obj V_Past_Part_Tr PP 262 | 1 VP_2nd Causal_2ndSing_Pres NP_Obj V_Past_Part_In 263 | 1 VP_2nd Causal_2ndSing_Pres NP_Obj V_Past_Part_In PP 264 | 265 | 1 VP_3rd Causal_3rdSing_Pres NP_Obj V_Past_Part_Tr 266 | 1 VP_3rd Causal_3rdSing_Pres NP_Obj V_Past_Part_Tr PP 267 | 1 VP_3rd Causal_3rdSing_Pres NP_Obj V_Past_Part_In 268 | 1 VP_3rd Causal_3rdSing_Pres NP_Obj V_Past_Part_In PP 269 | 270 | 1 VP_1st_Pl Causal_1stPlur_Pres NP_Obj V_Past_Part_Tr 271 | 1 VP_1st_Pl Causal_1stPlur_Pres NP_Obj V_Past_Part_Tr PP 272 | 1 VP_1st_Pl Causal_1stPlur_Pres NP_Obj V_Past_Part_In 273 | 1 VP_1st_Pl Causal_1stPlur_Pres NP_Obj V_Past_Part_In PP 274 | 275 | 1 VP_2nd_Pl Causal_2ndPlur_Pres NP_Obj V_Past_Part_Tr 276 | 1 VP_2nd_Pl Causal_2ndPlur_Pres NP_Obj V_Past_Part_Tr PP 277 | 1 VP_2nd_Pl Causal_2ndPlur_Pres NP_Obj V_Past_Part_In 278 | 1 VP_2nd_Pl Causal_2ndPlur_Pres NP_Obj V_Past_Part_In PP 279 | 280 | 1 VP_3rd_Pl Causal_3rdPlur_Pres NP_Obj V_Past_Part_Tr 281 | 1 VP_3rd_Pl Causal_3rdPlur_Pres NP_Obj V_Past_Part_Tr PP 282 | 1 VP_3rd_Pl Causal_3rdPlur_Pres NP_Obj V_Past_Part_In 283 | 1 VP_3rd_Pl Causal_3rdPlur_Pres NP_Obj V_Past_Part_In PP 284 | 285 | 1 VP_1st Causal_1stSing_Pres V_Past_Part_Tr 286 | 1 VP_1st Causal_1stSing_Pres V_Past_Part_Tr PP 287 | 1 VP_1st Causal_1stSing_Pres V_Past_Part_In 288 | 1 VP_1st Causal_1stSing_Pres V_Past_Part_In PP 289 | 290 | 1 VP_2nd Causal_2ndSing_Pres V_Past_Part_Tr 291 | 1 VP_2nd Causal_2ndSing_Pres V_Past_Part_Tr PP 292 | 1 VP_2nd Causal_2ndSing_Pres V_Past_Part_In 293 | 1 VP_2nd Causal_2ndSing_Pres V_Past_Part_In PP 294 | 295 | 1 VP_3rd Causal_3rdSing_Pres V_Past_Part_Tr 296 | 1 VP_3rd Causal_3rdSing_Pres V_Past_Part_Tr PP 297 | 1 VP_3rd Causal_3rdSing_Pres V_Past_Part_In 298 | 1 VP_3rd Causal_3rdSing_Pres V_Past_Part_In PP 299 | 300 | 1 VP_1st_Pl Causal_1stPlur_Pres V_Past_Part_Tr 301 | 1 VP_1st_Pl Causal_1stPlur_Pres V_Past_Part_Tr PP 302 | 1 VP_1st_Pl Causal_1stPlur_Pres V_Past_Part_In 303 | 1 VP_1st_Pl Causal_1stPlur_Pres V_Past_Part_In PP 304 | 305 | 1 VP_2nd_Pl Causal_2ndPlur_Pres V_Past_Part_Tr 306 | 1 VP_2nd_Pl Causal_2ndPlur_Pres V_Past_Part_Tr PP 307 | 1 VP_2nd_Pl Causal_2ndPlur_Pres V_Past_Part_In 308 | 1 VP_2nd_Pl Causal_2ndPlur_Pres V_Past_Part_In PP 309 | 310 | 1 VP_3rd_Pl Causal_3rdPlur_Pres V_Past_Part_Tr 311 | 1 VP_3rd_Pl Causal_3rdPlur_Pres V_Past_Part_Tr PP 312 | 1 VP_3rd_Pl Causal_3rdPlur_Pres V_Past_Part_In 313 | 1 VP_3rd_Pl Causal_3rdPlur_Pres V_Past_Part_In PP 314 | 315 | 1 VP_1st Causal_1stSing_Past NP_Obj V_Past_Part_Tr 316 | 1 VP_1st Causal_1stSing_Past NP_Obj V_Past_Part_Tr PP 317 | 1 VP_1st Causal_1stSing_Past NP_Obj V_Past_Part_In 318 | 1 VP_1st Causal_1stSing_Past NP_Obj V_Past_Part_In PP 319 | 320 | 1 VP_2nd Causal_2ndSing_Past NP_Obj V_Past_Part_Tr 321 | 1 VP_2nd Causal_2ndSing_Past NP_Obj V_Past_Part_Tr PP 322 | 1 VP_2nd Causal_2ndSing_Past NP_Obj V_Past_Part_In 323 | 1 VP_2nd Causal_2ndSing_Past NP_Obj V_Past_Part_In PP 324 | 325 | 1 VP_3rd Causal_3rdSing_Past NP_Obj V_Past_Part_Tr 326 | 1 VP_3rd Causal_3rdSing_Past NP_Obj V_Past_Part_Tr PP 327 | 1 VP_3rd Causal_3rdSing_Past NP_Obj V_Past_Part_In 328 | 1 VP_3rd Causal_3rdSing_Past NP_Obj V_Past_Part_In PP 329 | 330 | 1 VP_1st_Pl Causal_1stPlur_Past NP_Obj V_Past_Part_Tr 331 | 1 VP_1st_Pl Causal_1stPlur_Past NP_Obj V_Past_Part_Tr PP 332 | 1 VP_1st_Pl Causal_1stPlur_Past NP_Obj V_Past_Part_In 333 | 1 VP_1st_Pl Causal_1stPlur_Past NP_Obj V_Past_Part_In PP 334 | 335 | 1 VP_2nd_Pl Causal_2ndPlur_Past NP_Obj V_Past_Part_Tr 336 | 1 VP_2nd_Pl Causal_2ndPlur_Past NP_Obj V_Past_Part_Tr PP 337 | 1 VP_2nd_Pl Causal_2ndPlur_Past NP_Obj V_Past_Part_In 338 | 1 VP_2nd_Pl Causal_2ndPlur_Past NP_Obj V_Past_Part_In PP 339 | 340 | 1 VP_3rd_Pl Causal_3rdPlur_Past NP_Obj V_Past_Part_Tr 341 | 1 VP_3rd_Pl Causal_3rdPlur_Past NP_Obj V_Past_Part_Tr PP 342 | 1 VP_3rd_Pl Causal_3rdPlur_Past NP_Obj V_Past_Part_In 343 | 1 VP_3rd_Pl Causal_3rdPlur_Past NP_Obj V_Past_Part_In PP 344 | 345 | 1 VP_1st Causal_1stSing_Past V_Past_Part_Tr 346 | 1 VP_1st Causal_1stSing_Past V_Past_Part_Tr PP 347 | 1 VP_1st Causal_1stSing_Past V_Past_Part_In 348 | 1 VP_1st Causal_1stSing_Past V_Past_Part_In PP 349 | 350 | 1 VP_2nd Causal_2ndSing_Past V_Past_Part_Tr 351 | 1 VP_2nd Causal_2ndSing_Past V_Past_Part_Tr PP 352 | 1 VP_2nd Causal_2ndSing_Past V_Past_Part_In 353 | 1 VP_2nd Causal_2ndSing_Past V_Past_Part_In PP 354 | 355 | 1 VP_3rd Causal_3rdSing_Past V_Past_Part_Tr 356 | 1 VP_3rd Causal_3rdSing_Past V_Past_Part_Tr PP 357 | 1 VP_3rd Causal_3rdSing_Past V_Past_Part_In 358 | 1 VP_3rd Causal_3rdSing_Past V_Past_Part_In PP 359 | 360 | 1 VP_1st_Pl Causal_1stPlur_Past V_Past_Part_Tr 361 | 1 VP_1st_Pl Causal_1stPlur_Past V_Past_Part_Tr PP 362 | 1 VP_1st_Pl Causal_1stPlur_Past V_Past_Part_In 363 | 1 VP_1st_Pl Causal_1stPlur_Past V_Past_Part_In PP 364 | 365 | 1 VP_2nd_Pl Causal_2ndPlur_Past V_Past_Part_Tr 366 | 1 VP_2nd_Pl Causal_2ndPlur_Past V_Past_Part_Tr PP 367 | 1 VP_2nd_Pl Causal_2ndPlur_Past V_Past_Part_In 368 | 1 VP_2nd_Pl Causal_2ndPlur_Past V_Past_Part_In PP 369 | 370 | 1 VP_3rd_Pl Causal_3rdPlur_Past V_Past_Part_Tr 371 | 1 VP_3rd_Pl Causal_3rdPlur_Past V_Past_Part_Tr PP 372 | 1 VP_3rd_Pl Causal_3rdPlur_Past V_Past_Part_In 373 | 1 VP_3rd_Pl Causal_3rdPlur_Past V_Past_Part_In PP 374 | 375 | 1 V_Inf_In_Neg Not Exp_Inf Infl Ind_Clause 376 | 1 V_Inf_In_Neg Not Exp_Inf 377 | 378 | 1 VP_1st Verbal_1st_In After_Verb_In 379 | 1 VP_1st Verbal_1st_Tr After_Verb_Tr 380 | 1 VP_1st Verbal_1st_In 381 | 382 | 1 VP_2nd Verbal_2nd_In After_Verb_In 383 | 1 VP_2nd Verbal_2nd_Tr After_Verb_Tr 384 | 1 VP_2nd Verbal_2nd_In 385 | 386 | 1 VP_3rd Verbal_3rd_In After_Verb_In 387 | 1 VP_3rd Verbal_3rd_Tr After_Verb_Tr 388 | 1 VP_3rd Verbal_3rd_In 389 | 390 | 1 VP_1st_Pl Verbal_1st_Pl_In After_Verb_In 391 | 1 VP_1st_Pl Verbal_1st_Pl_Tr After_Verb_Tr 392 | 1 VP_1st_Pl Verbal_1st_Pl_In 393 | 394 | 1 VP_2nd_Pl Verbal_2nd_Pl_In After_Verb_In 395 | 1 VP_2nd_Pl Verbal_2nd_Pl_Tr After_Verb_Tr 396 | 1 VP_2nd_Pl Verbal_2nd_Pl_In 397 | 398 | 1 VP_3rd_Pl Verbal_3rd_Pl_In After_Verb_In 399 | 1 VP_3rd_Pl Verbal_3rd_Pl_Tr After_Verb_Tr 400 | 1 VP_3rd_Pl Verbal_3rd_Pl_In 401 | 402 | 1 VP_Inf V_Inf_Tr After_Verb_Tr 403 | 1 VP_Inf V_Inf_In After_Verb_In 404 | 1 VP_Inf V_Inf_In 405 | 1 VP_Inf V_Inf_Tr 406 | 1 VP_Inf Causal_Inf NP_Obj V_Past_Part_Tr 407 | 1 VP_Inf Causal_Inf NP_Obj V_Past_Part_In 408 | 1 VP_Inf Causal_Inf NP_Obj V_Past_Part_Tr PP 409 | 1 VP_Inf Causal_Inf NP_Obj V_Past_Part_In PP 410 | 1 VP_Inf Causal_Inf V_Past_Part_Tr 411 | 1 VP_Inf Causal_Inf V_Past_Part_In 412 | 1 VP_Inf Causal_Inf V_Past_Part_Tr PP 413 | 1 VP_Inf Causal_Inf V_Past_Part_In PP 414 | 1 VP_Inf V_Inf_In_Neg 415 | 1 VP_Inf Adv VP_Inf 416 | 1 VP_Inf V_Inf_Tr Adv After_Verb_Tr 417 | 1 VP_Inf V_Inf_In Adv After_Verb_In 418 | 1 VP_Inf V_Inf_In Adv 419 | 1 VP_Inf V_Inf_Tr Adv 420 | 1 VP_Inf Causal_Inf Adv NP_Obj V_Past_Part_Tr 421 | 1 VP_Inf Causal_Inf Adv NP_Obj V_Past_Part_In 422 | 1 VP_Inf Causal_Inf Adv NP_Obj V_Past_Part_Tr PP 423 | 1 VP_Inf Causal_Inf Adv NP_Obj V_Past_Part_In PP 424 | 1 VP_Inf Causal_Inf Adv V_Past_Part_Tr 425 | 1 VP_Inf Causal_Inf Adv V_Past_Part_In 426 | 1 VP_Inf Causal_Inf Adv V_Past_Part_Tr PP 427 | 1 VP_Inf Causal_Inf Adv V_Past_Part_In PP 428 | 1 VP_Inf V_Inf_In_Neg 429 | 430 | 1 After_Verb_Tr NP_Obj NP_Obj 431 | 1 After_Verb_Tr NP_Obj NP_Obj PP 432 | 1 After_Verb_Tr NP_Obj PP NP_Obj 433 | 1 After_Verb_Tr NP_Obj 434 | 1 After_Verb_Tr NP_Obj PP 435 | 1 After_Verb_Tr Prep 436 | 1 After_Verb_Tr PP 437 | 438 | 1 After_Verb_In Prep 439 | 1 After_Verb_In PP 440 | 441 | 1 Infinitive To V_Inf_Tr 442 | 1 Infinitive To V_Inf_In 443 | 444 | 1 Verbal_1st_In Verbal_1st_In Infinitive 445 | 1 Verbal_1st_Tr Verbal_1st_Tr Infinitive 446 | 1 Verbal_2nd_In Verbal_2nd_In Infinitive 447 | 1 Verbal_2nd_Tr Verbal_2nd_Tr Infinitive 448 | 1 Verbal_3rd_In Verbal_3rd_In Infinitive 449 | 1 Verbal_3rd_Tr Verbal_3rd_Tr Infinitive 450 | 1 Verbal_1st_Pl_In Verbal_1st_In Infinitive 451 | 1 Verbal_1st_Pl_Tr Verbal_1st_Tr Infinitive 452 | 1 Verbal_2nd_Pl_In Verbal_2nd_In Infinitive 453 | 1 Verbal_2nd_Pl_Tr Verbal_2nd_Tr Infinitive 454 | 1 Verbal_3rd_Pl_In Verbal_3rd_In Infinitive 455 | 1 Verbal_3rd_Pl_Tr Verbal_3rd_Tr Infinitive 456 | 457 | 1 Verbal_1st_In V_1stSing_Pres_In 458 | 1 Verbal_1st_In V_1stSing_Past_In 459 | 1 Verbal_2nd_In V_2ndSing_Pres_In 460 | 1 Verbal_2nd_In V_2ndSing_Past_In 461 | 1 Verbal_3rd_In V_3rdSing_Pres_In 462 | 1 Verbal_3rd_In V_3rdSing_Past_In 463 | 1 Verbal_1st_Pl_In V_1stPlur_Pres_In 464 | 1 Verbal_1st_In V_1stSing_Past_In 465 | 1 Verbal_2nd_Pl_In V_2ndPlur_Pres_In 466 | 1 Verbal_2nd_In V_2ndSing_Past_In 467 | 1 Verbal_3rd_Pl_In V_3rdPlur_Pres_In 468 | 1 Verbal_3rd_In V_3rdSing_Past_In 469 | 470 | 1 Verbal_1st_Tr V_1stSing_Pres_Tr 471 | 1 Verbal_1st_Tr V_1stSing_Past_Tr 472 | 1 Verbal_2nd_Tr V_2ndSing_Pres_Tr 473 | 1 Verbal_2nd_Tr V_2ndSing_Past_Tr 474 | 1 Verbal_3rd_Tr V_3rdSing_Pres_Tr 475 | 1 Verbal_3rd_Tr V_3rdSing_Past_Tr 476 | 1 Verbal_1st_Pl_Tr V_1stPlur_Pres_Tr 477 | 1 Verbal_1st_Tr V_1stSing_Past_Tr 478 | 1 Verbal_2nd_Pl_Tr V_2ndPlur_Pres_Tr 479 | 1 Verbal_2nd_Tr V_2ndSing_Past_Tr 480 | 1 Verbal_3rd_Pl_Tr V_3rdPlur_Pres_Tr 481 | 1 Verbal_3rd_Tr V_3rdSing_Past_Tr 482 | 483 | 1 Verbal_1st_Tr Modal_Pres V_Inf_Tr 484 | 1 Verbal_2nd_Tr Modal_Pres V_Inf_Tr 485 | 1 Verbal_3rd_Tr Modal_Pres V_Inf_Tr 486 | 1 Verbal_1st_Pl_Tr Modal_Pres V_Inf_Tr 487 | 1 Verbal_2nd_Pl_Tr Modal_Pres V_Inf_Tr 488 | 1 Verbal_3rd_Pl_Tr Modal_Pres V_Inf_Tr 489 | 490 | 1 Verbal_1st_In Modal_Pres V_Inf_In 491 | 1 Verbal_2nd_In Modal_Pres V_Inf_In 492 | 1 Verbal_3rd_In Modal_Pres V_Inf_In 493 | 1 Verbal_1st_Pl_In Modal_Pres V_Inf_In 494 | 1 Verbal_2nd_Pl_In Modal_Pres V_Inf_In 495 | 1 Verbal_3rd_Pl_In Modal_Pres V_Inf_In 496 | 497 | 1 Verbal_1st_Tr Modal_Past Have V_Past_Part_Tr 498 | 1 Verbal_2nd_Tr Modal_Past Have V_Past_Part_Tr 499 | 1 Verbal_3rd_Tr Modal_Past Have V_Past_Part_Tr 500 | 1 Verbal_1st_Pl_Tr Modal_Past Have V_Past_Part_Tr 501 | 1 Verbal_2nd_Pl_Tr Modal_Past Have V_Past_Part_Tr 502 | 1 Verbal_3rd_Pl_Tr Modal_Past Have V_Past_Part_Tr 503 | 504 | 1 Verbal_1st_In Modal_Past Have V_Past_Part_In 505 | 1 Verbal_2nd_In Modal_Past Have V_Past_Part_In 506 | 1 Verbal_3rd_In Modal_Past Have V_Past_Part_In 507 | 1 Verbal_1st_Pl_In Modal_Past Have V_Past_Part_In 508 | 1 Verbal_2nd_Pl_In Modal_Past Have V_Past_Part_In 509 | 1 Verbal_3rd_Pl_In Modal_Past Have V_Past_Part_In 510 | 511 | 1 Verbal_1st_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 512 | 1 Verbal_2nd_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 513 | 1 Verbal_3rd_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 514 | 1 Verbal_1st_Pl_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 515 | 1 Verbal_2nd_Pl_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 516 | 1 Verbal_3rd_Pl_Tr Modal_Past Have Be_Past_Part V_Pres_Part_Tr 517 | 518 | 1 Verbal_1st_In Modal_Past Have Be_Past_Part V_Pres_Part_In 519 | 1 Verbal_2nd_In Modal_Past Have Be_Past_Part V_Pres_Part_In 520 | 1 Verbal_3rd_In Modal_Past Have Be_Past_Part V_Pres_Part_In 521 | 1 Verbal_1st_Pl_In Modal_Past Have Be_Past_Part V_Pres_Part_In 522 | 1 Verbal_2nd_Pl_In Modal_Past Have Be_Past_Part V_Pres_Part_In 523 | 1 Verbal_3rd_Pl_In Modal_Past Have Be_Past_Part V_Pres_Part_In 524 | 525 | 1 Verbal_1st_Tr Modal_Pres_Neg V_Inf_Tr 526 | 1 Verbal_2nd_Tr Modal_Pres_Neg V_Inf_Tr 527 | 1 Verbal_3rd_Tr Modal_Pres_Neg V_Inf_Tr 528 | 1 Verbal_1st_Pl_Tr Modal_Pres_Neg V_Inf_Tr 529 | 1 Verbal_2nd_Pl_Tr Modal_Pres_Neg V_Inf_Tr 530 | 1 Verbal_3rd_Pl_Tr Modal_Pres_Neg V_Inf_Tr 531 | 532 | 1 Verbal_1st_In Modal_Pres_Neg V_Inf_In 533 | 1 Verbal_2nd_In Modal_Pres_Neg V_Inf_In 534 | 1 Verbal_3rd_In Modal_Pres_Neg V_Inf_In 535 | 1 Verbal_1st_Pl_In Modal_Pres_Neg V_Inf_In 536 | 1 Verbal_2nd_Pl_In Modal_Pres_Neg V_Inf_In 537 | 1 Verbal_3rd_Pl_In Modal_Pres_Neg V_Inf_In 538 | 539 | 1 Verbal_1st_Tr Modal_Past_Neg Have V_Past_Part_Tr 540 | 1 Verbal_2nd_Tr Modal_Past_Neg Have V_Past_Part_Tr 541 | 1 Verbal_3rd_Tr Modal_Past_Neg Have V_Past_Part_Tr 542 | 1 Verbal_1st_Pl_Tr Modal_Past_Neg Have V_Past_Part_Tr 543 | 1 Verbal_2nd_Pl_Tr Modal_Past_Neg Have V_Past_Part_Tr 544 | 1 Verbal_3rd_Pl_Tr Modal_Past_Neg Have V_Past_Part_Tr 545 | 546 | 1 Verbal_1st_In Modal_Past_Neg Have V_Past_Part_In 547 | 1 Verbal_2nd_In Modal_Past_Neg Have V_Past_Part_In 548 | 1 Verbal_3rd_In Modal_Past_Neg Have V_Past_Part_In 549 | 1 Verbal_1st_Pl_In Modal_Past_Neg Have V_Past_Part_In 550 | 1 Verbal_2nd_Pl_In Modal_Past_Neg Have V_Past_Part_In 551 | 1 Verbal_3rd_Pl_In Modal_Past_Neg Have V_Past_Part_In 552 | 553 | 1 Verbal_1st_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 554 | 1 Verbal_2nd_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 555 | 1 Verbal_3rd_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 556 | 1 Verbal_1st_Pl_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 557 | 1 Verbal_2nd_Pl_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 558 | 1 Verbal_3rd_Pl_Tr Modal_Past_Neg Have Be_Past_Part V_Pres_Part_Tr 559 | 560 | 1 Verbal_1st_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 561 | 1 Verbal_2nd_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 562 | 1 Verbal_3rd_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 563 | 1 Verbal_1st_Pl_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 564 | 1 Verbal_2nd_Pl_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 565 | 1 Verbal_3rd_Pl_In Modal_Past_Neg Have Be_Past_Part V_Pres_Part_In 566 | 567 | 1 Verb_As_Noun_Obj V_Pres_Part_Tr NP_Obj 568 | 1 Verb_As_Noun_Obj V_Pres_Part_Tr 569 | 1 Verb_As_Noun_Obj V_Pres_Part_In 570 | 1 Verb_As_Noun V_Pres_Part_Tr NP_Obj 571 | 1 Verb_As_Noun V_Pres_Part_Tr 572 | 1 Verb_As_Noun V_Pres_Part_In 573 | 1 Verb_As_Noun To V_Inf_Tr NP_Obj 574 | 1 Verb_As_Noun To V_Inf_Tr 575 | 1 Verb_As_Noun To V_Inf_In 576 | 577 | 1 PP Prep NP_Obj 578 | 579 | 1 NP NP PP 580 | 1 NP NP_1st 581 | 1 NP NP_2nd 582 | 1 NP NP_3rd 583 | 1 NP NP_1st_Pl 584 | 1 NP NP_3rd_Pl 585 | 1 NP NP Noun_Conj NP 586 | 1 NP Interrog_Pronoun Ind_Clause 587 | 588 | 1 NP_1st Pers_Pro_1st 589 | 1 NP_2nd Pers_Pro_2nd 590 | 1 NP_3rd Pers_Pro_3rd 591 | 1 NP_1st_Pl Pers_Pro_1st_Pl 592 | 1 NP_3rd_Pl Pers_Pro_3rd_Pl 593 | 594 | 1 NP_3rd Name 595 | 1 NP_3rd Place 596 | 1 NP_3rd Program 597 | 1 NP_3rd Org 598 | 1 NP_3rd Field 599 | 1 NP_3rd Nominal 600 | 1 NP_3rd Command 601 | 1 NP_3rd File_Addr 602 | 1 NP_3rd Web_Addr 603 | 1 NP_3rd Indef_Article Nominal 604 | 1 NP_3rd Def_Article Nominal 605 | 1 NP_3rd Poss_Pers_Pro_Subj Nominal 606 | 1 NP_3rd Quant_Part Nominal 607 | 1 NP_3rd Quant_Part Def_Article Nominal 608 | 1 NP_3rd Quant_Sing Nominal 609 | 1 NP_3rd Quant_Part Of Def_Article Nominal 610 | 1 NP_3rd Verb_As_Noun 611 | 1 NP_3rd NP_3rd Adj_Infl VP_3rd 612 | 1 NP_3rd NP 's NP 613 | 614 | 1 NP_3rd_Pl Nominal_Pl 615 | 1 NP_3rd_Pl Def_Article_Pl Nominal_Pl 616 | 1 NP_3rd_Pl Poss_Pers_Pro_Subj Nominal_Pl 617 | 1 NP_3rd_Pl Quant_Plur Nominal 618 | 1 NP_3rd_Pl Quant_Plur Def_Article_Pl Nominal 619 | 1 NP_3rd_Pl Quant_Plur Of Def_Article_Pl Nominal_Pl 620 | 1 NP_3rd_Pl NP_3rd_Pl Adj_Infl VP_3rd_Pl 621 | 1 NP_3rd_Pl NP Noun_Conj NP 622 | 623 | 1 NP_Obj NP_Obj PP 624 | 1 NP_Obj NP_Obj Noun_Conj NP_Obj 625 | 1 NP_Obj Obj_Pers_Pro 626 | 1 NP_Obj Indef_Article Nominal 627 | 1 NP_Obj Def_Article Nominal 628 | 1 NP_Obj Poss_Pers_Pro_Subj Nominal 629 | 1 NP_Obj Def_Article_Pl Nominal_Pl 630 | 1 NP_Obj Poss_Pers_Pro_Subj Nominal_Pl 631 | 1 NP_Obj Nominal_Pl 632 | 1 NP_Obj Nominal 633 | 1 NP_Obj Name 634 | 1 NP_Obj Place 635 | 1 NP_Obj Program 636 | 1 NP_Obj Org 637 | 1 NP_Obj Field 638 | 1 NP_Obj Command 639 | 1 NP_Obj File_Addr 640 | 1 NP_Obj Web_Addr 641 | 1 NP_Obj Verb_As_Noun_Obj 642 | 1 NP_Obj Quant_Part Nominal 643 | 1 NP_Obj Quant_Part Def_Article Nominal 644 | 1 NP_Obj Quant_Part Of Def_Article Nominal 645 | 1 NP_Obj Quant_Sing Nominal 646 | 1 NP_Obj Quant_Plur Nominal_Pl 647 | 1 NP_Obj Quant_Plur Def_Article_Pl Nominal_Pl 648 | 1 NP_Obj Quant_Plur Of Def_Article_Pl Nominal_Pl 649 | 1 NP_Obj NP_Obj Adj_Infl VP 650 | 1 NP_Obj NP_Obj Adj_Infl VP_Pl 651 | 1 NP_Obj NP_Obj 's NP_Obj 652 | 1 NP_Obj Interrog_Pronoun Ind_Clause 653 | 654 | 1 Nominal Noun 655 | 1 Nominal CompoundNoun 656 | 1 Nominal AdjP Nominal 657 | 1 Nominal Color Nominal 658 | 1 Nominal Quote_Single Word Quote_Single 659 | 1 Nominal Quote_Double Word Quote_Double 660 | 661 | 1 Nominal_Pl Noun_Pl 662 | 1 Nominal_Pl CompoundNoun_Pl 663 | 1 Nominal_Pl AdjP Nominal_Pl 664 | 1 Nominal_Pl Color Nominal_Pl 665 | 666 | 1 CompoundNoun Noun Noun 667 | 1 CompoundNoun Noun Noun Noun 668 | 1 CompoundNoun Program Noun 669 | 1 CompoundNoun Program Noun Noun 670 | 1 CompoundNoun Program Program Noun 671 | 1 CompoundNoun Place Noun 672 | 1 CompoundNoun Place Noun Noun 673 | 1 CompoundNoun Org Noun 674 | 1 CompoundNoun Org Noun Noun 675 | 1 CompoundNoun_Pl Noun Noun_Pl 676 | 1 CompoundNoun_Pl Noun Noun Noun_Pl 677 | 1 CompoundNoun_Pl Program Noun_Pl 678 | 1 CompoundNoun_Pl Program Noun Noun_Pl 679 | 1 CompoundNoun_Pl Program Program Noun_Pl 680 | 1 CompoundNoun_Pl Place Noun_Pl 681 | 1 CompoundNoun_Pl Place Noun Noun_Pl 682 | 1 CompoundNoun_Pl Org Noun_Pl 683 | 1 CompoundNoun_Pl Org Noun Noun_Pl 684 | 685 | 1 AdjP Color 686 | 1 AdjP Num 687 | 1 AdjP Num_Sing 688 | 1 AdjP Adj_Pos 689 | 1 AdjP Adj_State 690 | 1 AdjP Adj_Dir 691 | 1 AdjP Poss_Adj 692 | 693 | 1 Modal_Pres_Neg_Neg Modal_Pres_Neg Not 694 | 1 Modal_Past_Neg Modal_Past Not 695 | 696 | ############## Aliases ################ 697 | 698 | 1 V_1stSing_Pres_Tr V_Base_Pres_Tr 699 | 1 V_2ndSing_Pres_Tr V_Base_Pres_Tr 700 | 1 V_1stPlur_Pres_Tr V_Base_Pres_Tr 701 | 1 V_2ndPlur_Pres_Tr V_Base_Pres_Tr 702 | 1 V_3rdPlur_Pres_Tr V_Base_Pres_Tr 703 | 704 | 1 V_1stSing_Pres_In V_Base_Pres_In 705 | 1 V_2ndSing_Pres_In V_Base_Pres_In 706 | 1 V_1stPlur_Pres_In V_Base_Pres_In 707 | 1 V_2ndPlur_Pres_In V_Base_Pres_In 708 | 1 V_3rdPlur_Pres_In V_Base_Pres_In 709 | 710 | 1 V_1stSing_Past_Tr V_Base_Past_Tr 711 | 1 V_2ndSing_Past_Tr V_Base_Past_Tr 712 | 1 V_3rdSing_Past_Tr V_Base_Past_Tr 713 | 1 V_1stPlur_Past_Tr V_Base_Past_Tr 714 | 1 V_2ndPlur_Past_Tr V_Base_Past_Tr 715 | 1 V_3rdPlur_Past_Tr V_Base_Past_Tr 716 | 717 | 1 V_1stSing_Past_In V_Base_Past_In 718 | 1 V_2ndSing_Past_In V_Base_Past_In 719 | 1 V_3rdSing_Past_In V_Base_Past_In 720 | 1 V_1stPlur_Past_In V_Base_Past_In 721 | 1 V_2ndPlur_Past_In V_Base_Past_In 722 | 1 V_3rdPlur_Past_In V_Base_Past_In 723 | 724 | 1 Being_1stSing_Pres Being_Base_Pres 725 | 1 Being_2ndSing_Pres Being_Base_Pres 726 | 1 Being_1stPlur_Pres Being_Base_Pres 727 | 1 Being_2ndPlur_Pres Being_Base_Pres 728 | 1 Being_3rdPlur_Pres Being_Base_Pres 729 | 730 | 1 Being_1stSing_Past Being_Base_Past 731 | 1 Being_2ndSing_Past Being_Base_Past 732 | 1 Being_3rdSing_Past Being_Base_Past 733 | 1 Being_1stPlur_Past Being_Base_Past 734 | 1 Being_2ndPlur_Past Being_Base_Past 735 | 1 Being_3rdPlur_Past Being_Base_Past 736 | 737 | 1 Exp_1stSing_Pres Exp_Base_Pres 738 | 1 Exp_2ndSing_Pres Exp_Base_Pres 739 | 1 Exp_1stPlur_Pres Exp_Base_Pres 740 | 1 Exp_2ndPlur_Pres Exp_Base_Pres 741 | 1 Exp_3rdPlur_Pres Exp_Base_Pres 742 | 743 | 1 Exp_1stSing_Past Exp_Base_Past 744 | 1 Exp_2ndSing_Past Exp_Base_Past 745 | 1 Exp_3rdSing_Past Exp_Base_Past 746 | 1 Exp_1stPlur_Past Exp_Base_Past 747 | 1 Exp_2ndPlur_Past Exp_Base_Past 748 | 1 Exp_3rdPlur_Past Exp_Base_Past 749 | 750 | 1 V_1stSing_Pres_In Be_1stSing_Pres 751 | 1 V_2ndSing_Pres_In Be_2ndSing_Pres 752 | 1 V_3rdSing_Pres_In Be_3rdSing_Pres 753 | 1 V_1stPlur_Pres_In Be_1stPlur_Pres 754 | 1 V_2ndPlur_Pres_In Be_2ndPlur_Pres 755 | 1 V_3rdPlur_Pres_In Be_3rdPlur_Pres 756 | 1 V_1stSing_Pres_Tr Be_1stSing_Pres 757 | 1 V_2ndSing_Pres_Tr Be_2ndSing_Pres 758 | 1 V_3rdSing_Pres_Tr Be_3rdSing_Pres 759 | 1 V_1stPlur_Pres_Tr Be_1stPlur_Pres 760 | 1 V_2ndPlur_Pres_Tr Be_2ndPlur_Pres 761 | 1 V_3rdPlur_Pres_Tr Be_3rdPlur_Pres 762 | 763 | 1 V_1stSing_Past_In Be_1stSing_Past 764 | 1 V_2ndSing_Past_In Be_2ndSing_Past 765 | 1 V_3rdSing_Past_In Be_3rdSing_Past 766 | 1 V_1stPlur_Past_In Be_1stPlur_Past 767 | 1 V_2ndPlur_Past_In Be_2ndPlur_Past 768 | 1 V_3rdPlur_Past_In Be_3rdPlur_Past 769 | 1 V_1stSing_Past_Tr Be_1stSing_Past 770 | 1 V_2ndSing_Past_Tr Be_2ndSing_Past 771 | 1 V_3rdSing_Past_Tr Be_3rdSing_Past 772 | 1 V_1stPlur_Past_Tr Be_1stPlur_Past 773 | 1 V_2ndPlur_Past_Tr Be_2ndPlur_Past 774 | 1 V_3rdPlur_Past_Tr Be_3rdPlur_Past 775 | 776 | 1 Causal_1stSing_Pres Causal_Base_Pres 777 | 1 Causal_2ndSing_Pres Causal_Base_Pres 778 | 1 Causal_1stPlur_Pres Causal_Base_Pres 779 | 1 Causal_2ndPlur_Pres Causal_Base_Pres 780 | 1 Causal_3rdPlur_Pres Causal_Base_Pres 781 | 782 | 1 Causal_1stSing_Past Causal_Base_Past 783 | 1 Causal_2ndSing_Past Causal_Base_Past 784 | 1 Causal_3rdSing_Past Causal_Base_Past 785 | 1 Causal_1stPlur_Past Causal_Base_Past 786 | 1 Causal_2ndPlur_Past Causal_Base_Past 787 | 1 Causal_3rdPlur_Past Causal_Base_Past 788 | 789 | 1 V_Pres_Part_In Go_Pres_Part To V_Inf_In 790 | 1 V_Pres_Part_Tr Go_Pres_Part To V_Inf_Tr 791 | 792 | 1 V_Pres_Part_In Adv V_Pres_Part_In 793 | 1 V_Pres_Part_In V_Pres_Part_In Adv 794 | 1 V_Pres_Part_Tr Adv V_Pres_Part_Tr 795 | 1 V_Pres_Part_Tr V_Pres_Part_Tr Adv 796 | 797 | 1 Word Name 798 | 1 Word Place 799 | 1 Word Event 800 | 1 Word Program 801 | 1 Word Command 802 | 1 Word Org 803 | 1 Word Field 804 | 1 Word Noun 805 | 1 Word Noun_Pl 806 | 1 Word Noun_Part 807 | 1 Word Pers_Pro_1st 808 | 1 Word Pers_Pro_2nd 809 | 1 Word Pers_Pro_3rd 810 | 1 Word Pers_Pro_1st_Pl 811 | 1 Word Pers_Pro_3rd_Pl 812 | 1 Word Poss_Pers_Pro_Obj 813 | 1 Word Poss_Pers_Pro_Subj 814 | 1 Word Obj_Pers_Pro 815 | 1 Word Reflex_Pers_Pro 816 | 1 Word Pronoun 817 | 1 Word Color 818 | 1 Word Num 819 | 1 Word Num_Sing 820 | 1 Word Adj_Pos 821 | 1 Word Adj_State 822 | 1 Word Adj_Dir 823 | 1 Word Super 824 | 1 Word Poss_Adj 825 | 1 Word Adv 826 | 1 Word Coord_Conj 827 | 1 Word Subord_Conj 828 | 1 Word Corr_Conj_First 829 | 1 Word Corr_Conj_Last 830 | 1 Word Quant_Plur 831 | 1 Word Quant_Part 832 | 1 Word Quant_Sing 833 | 1 Word Def_Article 834 | 1 Word Def_Article_Pl 835 | 1 Word Indef_Article 836 | 1 Word Interrog_Det 837 | 1 Word Interrog_Det_Poss 838 | 1 Word Interrog_Pronoun 839 | 1 Word Interrog_Proadverb 840 | 1 Word Infl 841 | 1 Word Adj_Infl 842 | 1 Word V_Inf_Tr 843 | 1 Word V_Pres_Part_Tr 844 | 1 Word V_Past_Part_Tr 845 | 1 Word V_1stSing_Pres_Tr 846 | 1 Word V_2ndSing_Pres_Tr 847 | 1 Word V_3rdSing_Pres_Tr 848 | 1 Word V_1stPlur_Pres_Tr 849 | 1 Word V_2ndPlur_Pres_Tr 850 | 1 Word V_3rdPlur_Pres_Tr 851 | 1 Word V_1stSing_Past_Tr 852 | 1 Word V_2ndSing_Past_Tr 853 | 1 Word V_3rdSing_Past_Tr 854 | 1 Word V_1stPlur_Past_Tr 855 | 1 Word V_2ndPlur_Past_Tr 856 | 1 Word V_3rdPlur_Past_Tr 857 | 1 Word V_Inf_In 858 | 1 Word V_Pres_Part_In 859 | 1 Word V_Past_Part_In 860 | 1 Word V_1stSing_Pres_In 861 | 1 Word V_2ndSing_Pres_In 862 | 1 Word V_3rdSing_Pres_In 863 | 1 Word V_1stPlur_Pres_In 864 | 1 Word V_2ndPlur_Pres_In 865 | 1 Word V_3rdPlur_Pres_In 866 | 1 Word V_1stSing_Past_In 867 | 1 Word V_2ndSing_Past_In 868 | 1 Word V_3rdSing_Past_In 869 | 1 Word V_1stPlur_Past_In 870 | 1 Word V_2ndPlur_Past_In 871 | 1 Word V_3rdPlur_Past_In 872 | 1 Word Modal_Pres 873 | 1 Word Modal_Pres_Neg 874 | 1 Word Have 875 | 1 Word Modal_Past 876 | 1 Word Modal_Past_Neg 877 | 1 Word Aux_3rd 878 | 1 Word Aux 879 | 1 Word Be_Inf 880 | 1 Word Be_Pres_Part 881 | 1 Word Be_Past_Part 882 | 1 Word Be_1stSing_Pres 883 | 1 Word Be_2ndSing_Pres 884 | 1 Word Be_3rdSing_Pres 885 | 1 Word Be_1stPlur_Pres 886 | 1 Word Be_2ndPlur_Pres 887 | 1 Word Be_3rdPlur_Pres 888 | 1 Word Be_1stSing_Past 889 | 1 Word Be_2ndSing_Past 890 | 1 Word Be_3rdSing_Past 891 | 1 Word Be_1stPlur_Past 892 | 1 Word Be_2ndPlur_Past 893 | 1 Word Be_3rdPlur_Past 894 | 1 Word Being_Inf 895 | 1 Word Being_Pres_Part 896 | 1 Word Being_Past_Part 897 | 1 Word Being_1stSing_Pres 898 | 1 Word Being_2ndSing_Pres 899 | 1 Word Being_3rdSing_Pres 900 | 1 Word Being_1stPlur_Pres 901 | 1 Word Being_2ndPlur_Pres 902 | 1 Word Being_3rdPlur_Pres 903 | 1 Word Being_1stSing_Past 904 | 1 Word Being_2ndSing_Past 905 | 1 Word Being_3rdSing_Past 906 | 1 Word Being_1stPlur_Past 907 | 1 Word Being_2ndPlur_Past 908 | 1 Word Being_3rdPlur_Past 909 | 1 Word Causal_Inf 910 | 1 Word Causal_Pres_Part 911 | 1 Word Causal_Past_Part 912 | 1 Word Causal_1stSing_Pres 913 | 1 Word Causal_2ndSing_Pres 914 | 1 Word Causal_3rdSing_Pres 915 | 1 Word Causal_1stPlur_Pres 916 | 1 Word Causal_2ndPlur_Pres 917 | 1 Word Causal_3rdPlur_Pres 918 | 1 Word Causal_1stSing_Past 919 | 1 Word Causal_2ndSing_Past 920 | 1 Word Causal_3rdSing_Past 921 | 1 Word Causal_1stPlur_Past 922 | 1 Word Causal_2ndPlur_Past 923 | 1 Word Causal_3rdPlur_Past 924 | 1 Word Exp_Inf 925 | 1 Word Exp_Pres_Part 926 | 1 Word Exp_Past_Part 927 | 1 Word Exp_1stSing_Pres 928 | 1 Word Exp_2ndSing_Pres 929 | 1 Word Exp_3rdSing_Pres 930 | 1 Word Exp_1stPlur_Pres 931 | 1 Word Exp_2ndPlur_Pres 932 | 1 Word Exp_3rdPlur_Pres 933 | 1 Word Exp_1stSing_Past 934 | 1 Word Exp_2ndSing_Past 935 | 1 Word Exp_3rdSing_Past 936 | 1 Word Exp_1stPlur_Past 937 | 1 Word Exp_2ndPlur_Past 938 | 1 Word Exp_3rdPlur_Past 939 | 1 Word Do_Inf 940 | 1 Word Do_Pres_Part 941 | 1 Word Do_Past_Part 942 | 1 Word Do_1stSing_Pres 943 | 1 Word Do_2ndSing_Pres 944 | 1 Word Do_3rdSing_Pres 945 | 1 Word Do_1stPlur_Pres 946 | 1 Word Do_2ndPlur_Pres 947 | 1 Word Do_3rdPlur_Pres 948 | 1 Word Do_1stSing_Past 949 | 1 Word Do_2ndSing_Past 950 | 1 Word Do_3rdSing_Past 951 | 1 Word Do_1stPlur_Past 952 | 1 Word Do_2ndPlur_Past 953 | 1 Word Do_3rdPlur_Past 954 | 1 Word Comma 955 | 1 Word Punc 956 | 1 Word PuncQ 957 | 1 Word Prep 958 | 1 Word File_Addr 959 | 1 Word Web_Addr 960 | 1 Word Of -------------------------------------------------------------------------------- /session.py: -------------------------------------------------------------------------------- 1 | import site 2 | site.addsitedir('/afs/athena.mit.edu/user/b/r/broder/lib/python2.5/site-packages') 3 | 4 | import zephyr 5 | from fuzzystack import FuzzyStack 6 | from helper import print_list, tokenize 7 | from nlp import get_sentence_type, find_topic, find_compound_noun, find_PP, find_noun, QUESTION, STATEMENT, COMMAND 8 | from xml_parser import update_files 9 | from parsetree import Parser 10 | 11 | ####################################### 12 | # The Session class stores a "session", 13 | # or conversation, between Dodona and 14 | # the user. 15 | ####################################### 16 | 17 | class Session: 18 | def __init__(self, name, topics, bot): 19 | self.memory = FuzzyStack(20) 20 | self.memory.push("data", topics) 21 | self.memory.push("name", name) 22 | self.name = name 23 | self.topics = topics 24 | self.parser = Parser() 25 | self.bot = bot 26 | 27 | def _topic(self, top, d=None, k=None, ques_word=None): 28 | if d == None: d = self.topics 29 | subtop = None 30 | 31 | nouns = set() 32 | n = find_noun(top) 33 | while n: 34 | noun = " ".join(n.leaves()) 35 | nouns.add(noun) 36 | n = find_noun(top, nouns) 37 | 38 | nouns = list(nouns) 39 | if "me" in nouns: nouns.remove("me") 40 | if "you" in nouns: nouns.remove("you") 41 | print "Nouns: " + str(nouns) 42 | ans = None 43 | 44 | for topic in nouns: 45 | for subtopic in nouns: 46 | # check to see if topic is a key in the knowledge 47 | # dictionary, and that the the entry corresponding 48 | # to topic is also a dictionary 49 | if d.has_key(topic) and isinstance(d[topic], dict): 50 | 51 | # if subtopic is a key in the entry corresponding 52 | # to topic, then set the subtopic entry as the answer. 53 | if d[topic].has_key(subtopic): 54 | print "TOPIC:", topic 55 | print "SUBTOPIC:", subtopic 56 | ans = d[topic][subtopic] 57 | 58 | # check to see if the current topic stored in memory is 59 | # the same as the topic we found. 60 | elif topic == k: 61 | 62 | # is the subtopic we found a key in the dictionary? 63 | # if so, set it's entry as the anser. 64 | if d.has_key(subtopic): 65 | print "TOPIC:", topic 66 | print "SUBTOPIC:", subtopic 67 | ans = d[subtopic] 68 | 69 | if not ans: 70 | for topic in nouns: 71 | 72 | # if the topic is a key in the dictionary 73 | if d.has_key(topic): 74 | 75 | # if the entry matching topic is a dictionary, then 76 | # we should ask what subtopic they want to know about 77 | if isinstance(d[topic], dict): 78 | print "TOPIC:", topic 79 | ans = d[topic]['default'] + "\n" + \ 80 | "Multiple keywords match your query. " + \ 81 | "What did you mean to ask about?\n\n" + \ 82 | print_list(d[topic].keys()) 83 | self.memory.push("topic", topic) 84 | self.memory.push("data", d[topic]) 85 | 86 | # otherwise, just give them the entry that corresponds 87 | # to topic 88 | else: 89 | print "TOPIC:", topic 90 | ans = d[topic] 91 | 92 | # if the topic we found is the same as the topic in 93 | # memory, then ask (again) which subtopic they 94 | # want to ask about 95 | elif topic == k: 96 | print "TOPIC:", topic 97 | ans = d['default'] + "\n" + \ 98 | "Multiple keywords match your query. " + \ 99 | "What did you mean to ask about?\n\n" + \ 100 | print_list(d.keys()) 101 | 102 | if not ans: 103 | if nouns == [] and ques_word == "what": 104 | print "TOPIC: knowledge" 105 | ans = "I know about:\n" + print_list(self.topics.keys()) 106 | elif "what you know" in nouns or \ 107 | "knowledge" in nouns: 108 | print "TOPIC: knowledge" 109 | ans = "I know about:\n" + print_list(self.topics.keys()) 110 | else: 111 | l = nouns.pop(0) 112 | if len(nouns) > 0: 113 | for n in xrange(len(nouns)-1): 114 | l += ", " + nouns[n] 115 | 116 | l += ", or " + nouns[-1] 117 | ans = "Sorry, I don't know about " + l + "." 118 | 119 | return ans 120 | 121 | def _AI(self, mess, d = None, k = None): 122 | """ 123 | Parses the message, and attempts to locate a topic. If it is 124 | able to find a topic, it tells the user about the topic, 125 | otherwise it prints a message saying that it can't parse the 126 | sentence, or it doesn't know about the topic. 127 | """ 128 | 129 | # make sure the dictionary is set to something 130 | if d == None: d = self.topics 131 | 132 | # parse the sentence, and print the parse 133 | parse = self.parser.parse_sent(mess) 134 | print "PARSE:\n", parse 135 | ans = None 136 | 137 | # if the parse is returned as a tuple, then we know 138 | # that the parse failed. 139 | if isinstance(parse, tuple): 140 | 141 | # if the second value in the tuple is valid, then there were 142 | # words that were not in the grammar. Tell the user about the 143 | # words, and then enter a function to learn the foreign words. 144 | if parse[1]: 145 | self.bot.send("Sorry, I don't understand the following words: " + \ 146 | ", ".join(parse[1]) + ".", self.name) 147 | self.memory.push("topic", list(parse[1])) 148 | return self._learn() 149 | 150 | # otherwise, we just couldn't parse the sentence 151 | else: 152 | parse = self.parser.parse_NP(mess) 153 | print "NP PARSE:\n", parse 154 | if parse: 155 | ans = self._topic(parse, d=d, k=k) 156 | else: 157 | ans = "Sorry, I couldn't parse what you just said." 158 | 159 | # otherwise, the parse succeeded 160 | else: 161 | # find the sentence type: STATEMENT, QUESTION, or COMMAND 162 | type = get_sentence_type(parse) 163 | print "TYPE: " + str(type) 164 | 165 | # based on the sentence type, find the topic of the sentence. 166 | # we don't yet know what the subtopic is, so just set it to 167 | # None. 168 | top = find_topic(parse, type) 169 | print top 170 | 171 | # if the sentence is a question and find_topic() found a 172 | # topic, then top is a tuple, and we need to store the 173 | # parts separately. 174 | ques_word = None 175 | if type == QUESTION and top: 176 | ques_word = top[1] 177 | top = top[0] 178 | 179 | # if a topic was found, then we want to look for a 180 | # prepositional phrase. For example, we want to be able 181 | # to get TOPIC=emacs, SUBTOPIC=keys from "keys in emacs" 182 | if top: 183 | ans = self._topic(top, d=d, k=k, ques_word=ques_word) 184 | 185 | # otherwise, we couldn't find a topic from the sentence, so 186 | # tell them so 187 | else: 188 | if type == QUESTION and ques_word == "what": 189 | print "TOPIC: knowledge" 190 | ans = "I know about:\n" + print_list(self.topics.keys()) 191 | else: 192 | print "TOPIC: None found" 193 | ans = "Sorry, I couldn't determine the topic of what you are asking me." 194 | 195 | # print the answer out to the terminal, and send the answer 196 | # to the user. 197 | print ans 198 | self.bot.send(ans, self.name) 199 | 200 | def _add_new_word(self, word, pos): 201 | """ 202 | Adds a new vocabulary word and rule to vocabulary.gr and 203 | to the ContextFreeGrammar. 204 | """ 205 | vocab = open("vocabulary.gr", "a") 206 | vocab.write("\n1\t" + pos + "\t" + word) 207 | vocab.close() 208 | self.parser.add_new_vocab_rule([pos, [word]]) 209 | 210 | def _part_of_speech(self, mess, step): 211 | """ 212 | Part of Dodona's word-learning algorithm. Learns the 213 | part of speech for the word, and either moves to the next step 214 | (for example, if the word is a verb, we want to know all 215 | conjugations of that verb) or ends the learning process. 216 | """ 217 | word = self.memory.pop("topic")[1] 218 | name = self.name 219 | 220 | # first step 221 | if step == "first": 222 | 223 | # plural noun 224 | if mess.find("plural noun") != -1: 225 | self._add_new_word(word, "Noun_Pl") 226 | self.memory.pop("status") 227 | return self._learn() 228 | 229 | # noun 230 | elif mess.find("noun") != -1: 231 | self._add_new_word(word, "Noun") 232 | self.memory.pop("status") 233 | return self._learn() 234 | 235 | # adjective 236 | elif mess.find("adjective") != -1: 237 | self._add_new_word(word, "Adj_State") 238 | self.memory.pop("status") 239 | return self._learn() 240 | 241 | # adverb 242 | elif mess.find("adverb") != -1: 243 | self._add_new_word(word, "Adv") 244 | self.memory.pop("status") 245 | return self._learn() 246 | 247 | # intransitive verb 248 | elif mess.find("intransitive verb") != -1: 249 | self.bot.send("What is the infinitive for the verb " + word + "?", name) 250 | self.memory.pop("status") 251 | self.memory.push("status", "pos_verb1in") 252 | self.memory.push("topic", word) 253 | 254 | # transitive verb 255 | elif mess.find("transitive verb") != -1: 256 | self.bot.send("What is the infinitive for the verb " + word + "?", name) 257 | self.memory.pop("status") 258 | self.memory.push("status", "pos_verb1tr") 259 | self.memory.push("topic", word) 260 | 261 | # preposition 262 | elif mess.find("preposition") != -1: 263 | self._add_new_word(word, "Prep") 264 | self.memory.pop("status") 265 | return self._learn() 266 | 267 | # anything else 268 | else: 269 | self.memory.pop("status") 270 | return self._learn() 271 | 272 | # step 2, stores the infinitive 273 | elif step.startswith("verb1"): 274 | if step.endswith("in"): 275 | self._add_new_word(mess, "V_Inf_In") 276 | self.memory.pop("status") 277 | self.memory.push("status", "pos_verb2in") 278 | elif step.endswith("tr"): 279 | self._add_new_word(mess, "V_Inf_Tr") 280 | self.memory.pop("status") 281 | self.memory.push("status", "pos_verb2tr") 282 | 283 | self.memory.push("topic", word) 284 | self.bot.send("What is the present participle for the verb " + word + "?", name) 285 | return None 286 | 287 | # step 3, stores the present participle 288 | elif step.startswith("verb2"): 289 | if step.endswith("in"): 290 | self._add_new_word(mess, "V_Pres_Part_In") 291 | self.memory.pop("status") 292 | self.memory.push("status", "pos_verb3in") 293 | elif step.endswith("tr"): 294 | self._add_new_word(mess, "V_Pres_Part_Tr") 295 | self.memory.pop("status") 296 | self.memory.push("status", "pos_verb3tr") 297 | 298 | self.memory.push("topic", word) 299 | self.bot.send("What is the past participle for the verb " + word + "?", name) 300 | return None 301 | 302 | # step 4, stores the past participle 303 | elif step.startswith("verb3"): 304 | if step.endswith("in"): 305 | self._add_new_word(mess, "V_Past_Part_In") 306 | self.memory.pop("status") 307 | self.memory.push("status", "pos_verb4in") 308 | elif step.endswith("tr"): 309 | self._add_new_word(mess, "V_Past_Part_Tr") 310 | self.memory.pop("status") 311 | self.memory.push("status", "pos_verb4tr") 312 | 313 | self.memory.push("topic", word) 314 | self.bot.send("What is the 1st person singular present for the verb " + word + "?", name) 315 | return None 316 | 317 | # step 5, stores the present base 318 | elif step.startswith("verb4"): 319 | if step.endswith("in"): 320 | self._add_new_word(mess, "V_Base_Pres_In") 321 | self.memory.pop("status") 322 | self.memory.push("status", "pos_verb5in") 323 | elif step.endswith("tr"): 324 | self._add_new_word(mess, "V_Base_Pres_Tr") 325 | self.memory.pop("status") 326 | self.memory.push("status", "pos_verb5tr") 327 | 328 | self.memory.push("topic", word) 329 | self.bot.send("What is the 3rd person singular present for the verb " + word + "?", name) 330 | return None 331 | 332 | # step 6, stores the 3rd person singular 333 | elif step.startswith("verb5"): 334 | if step.endswith("in"): 335 | self._add_new_word(mess, "V_3rdSing_Pres_In") 336 | self.memory.pop("status") 337 | self.memory.push("status", "pos_verb6in") 338 | elif step.endswith("tr"): 339 | self._add_new_word(mess, "V_3rdSing_Pres_Tr") 340 | self.memory.pop("status") 341 | self.memory.push("status", "pos_verb6tr") 342 | 343 | self.memory.push("topic", word) 344 | self.bot.send("What is the 1st person singular past for the verb " + word + "?", name) 345 | return None 346 | 347 | # step 7, stores the past base 348 | elif step.startswith("verb6"): 349 | if step.endswith("in"): 350 | self._add_new_word(mess, "V_Base_Past_In") 351 | elif step.endswith("tr"): 352 | self._add_new_word(mess, "V_Base_Past_Tr") 353 | 354 | self.memory.pop("status") 355 | return self._learn() 356 | 357 | def _learn(self): 358 | """ 359 | Begins the learning process. Asks the user what 360 | part of speech the word is, and keeps track of the 361 | remaining words which we still need to learn about 362 | """ 363 | name = self.name 364 | unknown_all = list(self.memory.pop("topic"))[1] 365 | if len(unknown_all) > 0: 366 | unknown = unknown_all[0] 367 | del unknown_all[0] 368 | pos = ["Noun", \ 369 | "Plural Noun", \ 370 | "Adjective", \ 371 | "Adverb", \ 372 | "Transitive Verb", \ 373 | "Intransitive Verb", \ 374 | "Preposition", \ 375 | "Other"] 376 | 377 | self.bot.send("Which of the following parts of speech is \'" + \ 378 | unknown + "\'?\n" + print_list(pos), name) 379 | self.memory.push("topic", unknown_all) 380 | self.memory.push("topic", unknown) 381 | self.memory.pop("status") 382 | self.memory.push("status", "pos_first") 383 | return None 384 | else: 385 | self.memory.pop("status") 386 | return "reset" 387 | 388 | def clear(self): 389 | """ 390 | Clears (resets) the session and the 391 | memory, but does not kill it. 392 | """ 393 | self.memory = FuzzyStack(20) 394 | self.memory.push("data", self.topics) 395 | 396 | def question(self): 397 | """ 398 | Parses the user's most recent message, 399 | and decides what to do based on the 400 | content and the current status. 401 | """ 402 | name = self.name 403 | mess = self.memory.read("message") 404 | m = tokenize(mess) 405 | mess = " ".join(m) 406 | 407 | if mess == None: return "reset" 408 | 409 | # if the user wants to exit, then 410 | # return True (kill the session) 411 | if mess.startswith("exit") or \ 412 | "bye" in m or \ 413 | "goodbye" in m: 414 | self.bot.send("Glad to be of help :)", name) 415 | return "exit" 416 | 417 | # if the user says "nevermind", then 418 | # clear the session 419 | if mess.find("nevermind") != -1: 420 | self.bot.send("Ok.", name) 421 | self.clear() 422 | return "reset" 423 | 424 | # if the user greets Dodona, then respond 425 | # in kind. 426 | if "hi" in m or \ 427 | "hey" in m or \ 428 | "hello" in m != -1: 429 | self.bot.send("Hello, " + name + "!") 430 | return None 431 | 432 | # check the status, and return the corresponding 433 | # function if necessary 434 | s = self.memory.read("status") 435 | #if s == "unknown": return self.unknown(mess) 436 | if s == "learn": return self._learn() 437 | if s: 438 | if s.startswith("pos"): 439 | return self._part_of_speech(mess, s.split("_")[1]) 440 | 441 | d = self.memory.read("data") 442 | k = self.memory.read("topic") 443 | # if there is no current topic, then decipher one 444 | # from the most recent message. 445 | if k == None: 446 | self._AI(mess) 447 | if self.memory.read("topic"): 448 | return None 449 | else: 450 | return "reset" 451 | 452 | # if there is a current topic, search for a subtopic 453 | else: 454 | self._AI(mess, d, k) 455 | if self.memory.read("status") == "pos_first": 456 | return None 457 | else: 458 | self.memory.pop("topic") 459 | self.memory.pop("data") 460 | return "reset" 461 | 462 | # -*- indent-tabs-mode: nil; tab-width: 4; -*- 463 | # vi: set ts=4 sw=4 et: 464 | -------------------------------------------------------------------------------- /vocabulary.gr: -------------------------------------------------------------------------------- 1 | #################### Nouns ###################### 2 | 3 | # Names 4 | 1 Noun Dodona 5 | 1 Noun jhamrick 6 | 1 Noun Jessica 7 | 1 Noun Socrates 8 | 1 Noun geofft 9 | 1 Noun God 10 | 11 | # Places (do not require "the") 12 | 1 Noun Cambridge 13 | 1 Noun Somerville 14 | 1 Place MIT 15 | 16 | # Events 17 | 1 Noun DEFCON 18 | 19 | # Programs 20 | 1 Noun scheme 21 | 1 Noun emacs 22 | 1 Noun BarnOwl 23 | 1 Noun Google 24 | 1 Noun Linux 25 | 1 Noun git 26 | 1 Noun Ubuntu 27 | 1 Noun Athena 28 | 1 Noun Zephyr 29 | 1 Noun SkyNet 30 | 1 Noun UNIX 31 | 1 Noun Intrepid 32 | 33 | 1 Noun \def 34 | 1 Noun \newcommand 35 | 1 Noun ^M 36 | 37 | # Organizations 38 | 1 Noun SIPB 39 | 40 | # Field of study 41 | 1 Noun NLP 42 | 1 Noun CS 43 | 1 Noun EE 44 | 45 | # Singular nouns 46 | 1 Noun green 47 | 1 Noun line 48 | 1 Noun office 49 | 1 Noun student 50 | 1 Noun center 51 | 1 Noun command 52 | 1 Noun line 53 | 1 Noun thing 54 | 1 Noun person 55 | 1 Noun text 56 | 1 Noun editor 57 | 1 Noun dinosaur 58 | 1 Noun color 59 | 1 Noun question 60 | 1 Noun room 61 | 1 Noun man 62 | 1 Noun sentence 63 | 1 Noun wood 64 | 1 Noun woodchuck 65 | 1 Noun revision 66 | 1 Noun result 67 | 1 Noun website 68 | 1 Noun sun 69 | 1 Noun earth 70 | 1 Noun phase 71 | 1 Noun moon 72 | 1 Noun name 73 | 1 Noun quest 74 | 1 Noun velocity 75 | 1 Noun swallow 76 | 1 Noun tree 77 | 1 Noun day 78 | 1 Noun registration 79 | 1 Noun state 80 | 1 Noun art 81 | 1 Noun mortal 82 | 1 Noun sandwich 83 | 1 Noun status 84 | 1 Noun extension 85 | 1 Noun page 86 | 1 Noun airspeed 87 | 1 Noun advantage 88 | 1 Noun language 89 | 1 Noun PEG 90 | 1 Noun CFG 91 | 1 Noun directory 92 | 1 Noun inode 93 | 1 Noun reference 94 | 1 Noun size 95 | 1 Noun router 96 | 1 Noun housing 97 | 1 Noun lottery 98 | 1 Noun difference 99 | 1 Noun hair 100 | 1 Noun LiveCD 101 | 1 Noun laptop 102 | 1 Noun harddrive 103 | 1 Noun drive 104 | 1 Noun path 105 | 1 Noun communication 106 | 1 Noun road 107 | 1 Noun car 108 | 1 Noun suggestion 109 | 1 Noun snark 110 | 1 Noun file 111 | 1 Noun Itanium 112 | 1 Noun program 113 | 1 Noun bot 114 | 1 Noun robot 115 | 1 Noun prevention 116 | 1 Noun removal 117 | 1 Noun autofill 118 | 1 Noun autosave 119 | 1 Noun recovery 120 | 1 Noun spellcheck 121 | 1 Noun copy 122 | 1 Noun key 123 | 1 Noun mouse 124 | 1 Noun customization 125 | 1 Noun function 126 | 1 Noun file 127 | 1 Noun menu 128 | 1 Noun help 129 | 1 Noun browser 130 | 1 Noun language 131 | 1 Noun line 132 | 1 Noun number 133 | 1 Noun button 134 | 1 Noun cursor 135 | 1 Noun mail 136 | 1 Noun query 137 | 1 Noun replacement 138 | 1 Noun source 139 | 1 Noun tag 140 | 1 Noun version 141 | 1 Noun window 142 | 1 Noun size 143 | 1 Noun backspace 144 | 1 Noun fill 145 | 1 Noun auto-fill 146 | 1 Noun auto-save 147 | 1 Noun rebound 148 | 1 Noun service 149 | 150 | # Plural nouns 151 | 152 | 1 Noun_Pl rebounds 153 | 1 Noun_Pl auto-saves 154 | 1 Noun_Pl auto-fills 155 | 1 Noun_Pl tags 156 | 1 Noun_Pl autofills 157 | 1 Noun_Pl backspaces 158 | 1 Noun_Pl versions 159 | 1 Noun_Pl windows 160 | 1 Noun_Pl sizes 161 | 1 Noun_Pl sources 162 | 1 Noun_Pl queries 163 | 1 Noun_Pl replacements 164 | 1 Noun_Pl cursors 165 | 1 Noun_Pl mail 166 | 1 Noun_Pl lines 167 | 1 Noun_Pl numbers 168 | 1 Noun_Pl buttons 169 | 1 Noun_Pl browsers 170 | 1 Noun_Pl languages 171 | 1 Noun_Pl functions 172 | 1 Noun_Pl menus 173 | 1 Noun_Pl files 174 | 1 Noun_Pl customizations 175 | 1 Noun_Pl keys 176 | 1 Noun_Pl mice 177 | 1 Noun_Pl copies 178 | 1 Noun_Pl spellchecks 179 | 1 Noun_Pl removals 180 | 1 Noun_Pl autosaves 181 | 1 Noun_Pl recoveries 182 | 1 Noun_Pl preventions 183 | 1 Noun_Pl commands 184 | 1 Noun_Pl lines 185 | 1 Noun_Pl things 186 | 1 Noun_Pl people 187 | 1 Noun_Pl editors 188 | 1 Noun_Pl dinosaurs 189 | 1 Noun_Pl colors 190 | 1 Noun_Pl questions 191 | 1 Noun_Pl rooms 192 | 1 Noun_Pl men 193 | 1 Noun_Pl sentences 194 | 1 Noun_Pl woods 195 | 1 Noun_Pl wood 196 | 1 Noun_Pl woodchucks 197 | 1 Noun_Pl revisions 198 | 1 Noun_Pl results 199 | 1 Noun_Pl websites 200 | 1 Noun_Pl suns 201 | 1 Noun_Pl earths 202 | 1 Noun_Pl phases 203 | 1 Noun_Pl moons 204 | 1 Noun_Pl names 205 | 1 Noun_Pl quests 206 | 1 Noun_Pl velocities 207 | 1 Noun_Pl swallows 208 | 1 Noun_Pl states 209 | 1 Noun_Pl art 210 | 1 Noun_Pl mortals 211 | 1 Noun_Pl sandwiches 212 | 1 Noun_Pl statuses 213 | 1 Noun_Pl extensions 214 | 1 Noun_Pl pages 215 | 1 Noun_Pl airspeeds 216 | 1 Noun_Pl advantages 217 | 1 Noun_Pl languages 218 | 1 Noun_Pl PEGs 219 | 1 Noun_Pl CFGs 220 | 1 Noun_Pl directories 221 | 1 Noun_Pl inodes 222 | 1 Noun_Pl references 223 | 1 Noun_Pl sizes 224 | 1 Noun_Pl routers 225 | 1 Noun_Pl housing 226 | 1 Noun_Pl lotteries 227 | 1 Noun_Pl differences 228 | 1 Noun_Pl hair 229 | 1 Noun_Pl hairs 230 | 1 Noun_Pl LiveCDs 231 | 1 Noun_Pl laptops 232 | 1 Noun_Pl harddrives 233 | 1 Noun_Pl drives 234 | 1 Noun_Pl paths 235 | 1 Noun_Pl communications 236 | 1 Noun_Pl roads 237 | 1 Noun_Pl cars 238 | 1 Noun_Pl suggestions 239 | 1 Noun_Pl snark 240 | 1 Noun_Pl files 241 | 1 Noun_Pl Itaniums 242 | 1 Noun_Pl programs 243 | 1 Noun_Pl robots 244 | 1 Noun_Pl bots 245 | 1 Noun_Pl fills 246 | 1 Noun_Pl services 247 | 248 | #################### Pronouns #################### 249 | 250 | # Personal pronouns 251 | 1 Pers_Pro_1st I 252 | 1 Pers_Pro_1st one 253 | 1 Pers_Pro_2nd you 254 | 1 Pers_Pro_3rd she 255 | 1 Pers_Pro_3rd he 256 | 1 Pers_Pro_3rd it 257 | 1 Pers_Pro_1st_Pl we 258 | 1 Pers_Pro_3rd_Pl they 259 | 260 | # Possessive personal pronouns (object) 261 | 1 Poss_Pers_Pro_Obj mine 262 | 1 Poss_Pers_Pro_Obj yours 263 | 1 Poss_Pers_Pro_Obj his 264 | 1 Poss_Pers_Pro_Obj hers 265 | 1 Poss_Pers_Pro_Obj its 266 | 1 Poss_Pers_Pro_Obj ours 267 | 1 Poss_Pers_Pro_Obj theirs 268 | 269 | # Possessive personal pronouns (subject) 270 | 1 Poss_Pers_Pro_Subj my 271 | 1 Poss_Pers_Pro_Subj your 272 | 1 Poss_Pers_Pro_Subj his 273 | 1 Poss_Pers_Pro_Subj her 274 | 1 Poss_Pers_Pro_Subj its 275 | 1 Poss_Pers_Pro_Subj our 276 | 1 Poss_Pers_Pro_Subj their 277 | 278 | # Objective personal pronouns 279 | 1 Obj_Pers_Pro me 280 | 1 Obj_Pers_Pro you 281 | 1 Obj_Pers_Pro him 282 | 1 Obj_Pers_Pro her 283 | 1 Obj_Pers_Pro it 284 | 1 Obj_Pers_Pro us 285 | 1 Obj_Pers_Pro them 286 | 287 | # Reflexive personal pronouns 288 | 1 Reflex_Pers_Pro myself 289 | 1 Reflex_Pers_Pro yourself 290 | 1 Reflex_Pers_Pro himself 291 | 1 Reflex_Pers_Pro herself 292 | 1 Reflex_Pers_Pro itself 293 | 1 Reflex_Pers_Pro ourselves 294 | 1 Reflex_Pers_Pro yourselves 295 | 1 Reflex_Pers_Pro themselves 296 | 297 | 1 's 's 298 | 299 | 1 Pronoun many 300 | 301 | #################### Adjectives #################### 302 | 303 | # Colors 304 | 1 Color red 305 | 1 Color orange 306 | 1 Color yellow 307 | 1 Color green 308 | 1 Color blue 309 | 1 Color purple 310 | 1 Color white 311 | 1 Color black 312 | 1 Color grey 313 | 314 | # Numbers (spelled out) 315 | 1 Num zero 316 | 1 Num_Sing one 317 | 1 Num two 318 | 1 Num three 319 | 1 Num four 320 | 1 Num five 321 | 1 Num six 322 | 1 Num seven 323 | 1 Num eight 324 | 1 Num nine 325 | 1 Num ten 326 | 1 Num eleven 327 | 1 Num twelve 328 | 1 Num thirteen 329 | 1 Num fourteen 330 | 1 Num fifteen 331 | 1 Num sixteen 332 | 1 Num seventeen 333 | 1 Num eighteen 334 | 1 Num nineteen 335 | 1 Num twenty 336 | 1 Num thirty 337 | 1 Num fourty 338 | 1 Num fifty 339 | 1 Num sixty 340 | 1 Num seventy 341 | 1 Num eighty 342 | 1 Num ninety 343 | 1 Num hundred 344 | 1 Num thousand 345 | 1 Num million 346 | 1 Num billion 347 | 348 | # Numbers (numbers) 349 | 1 Num_Sing 1 350 | 1 Num 2 351 | 1 Num 3 352 | 1 Num 4 353 | 1 Num 5 354 | 1 Num 6 355 | 1 Num 7 356 | 1 Num 8 357 | 1 Num 9 358 | 1 Num 0 359 | 360 | # Position 361 | 1 Adj_Pos past 362 | 1 Adj_Pos current 363 | 1 Adj_Pos future 364 | 1 Adj_Pos last 365 | 1 Adj_Pos distant 366 | 1 Adj_Pos first 367 | 1 Adj_Pos near 368 | 1 Adj_Pos far 369 | 1 Adj_Pos here 370 | 1 Adj_Pos there 371 | 372 | # State 373 | 1 Adj_State bad 374 | 1 Adj_State good 375 | 1 Adj_State mortal 376 | 1 Adj_State true 377 | 1 Adj_State unladen 378 | 1 Adj_State trapped 379 | 1 Adj_State only 380 | 1 Adj_State hard 381 | 1 Adj_State secure 382 | 1 Adj_State helpful 383 | 1 Adj_State open 384 | 1 Adj_State other 385 | 1 Adj_State sad 386 | 1 Adj_State auto 387 | 388 | # Directions 389 | 1 Adj_Dir up 390 | 1 Adj_Dir down 391 | 1 Adj_Dir left 392 | 1 Adj_Dir right 393 | 394 | # Superlatives 395 | 1 Super greater 396 | 1 Super best 397 | 398 | # Possesion 399 | 1 Poss_Adj own 400 | 401 | #################### Adverbs #################### 402 | 403 | 1 Adv instead 404 | 1 Adv ever 405 | 1 Adv back 406 | 1 Adv just 407 | 1 Adv best 408 | 1 Adv very 409 | 410 | #################### Conjunctions #################### 411 | 412 | # Coordinating conjunctions 413 | 1 Coord_Conj and 414 | 1 Coord_Conj for 415 | 1 Coord_Conj nor 416 | 1 Coord_Conj but 417 | 1 Coord_Conj or 418 | 1 Coord_Conj yet 419 | 1 Coord_Conj so 420 | 421 | # Subordinating conjunctions 422 | 1 Subord_Conj after 423 | 1 Subord_Conj although 424 | 1 Subord_Conj if 425 | 1 Subord_Conj unless 426 | 1 Subord_Conj therefore 427 | 1 Subord_Conj because 428 | 429 | # Correlative conjunctions 430 | 1 Corr_Conj_First both 431 | 1 Corr_Conj_First neither 432 | 1 Corr_Conj_First either 433 | 1 Corr_Conj_First not 434 | 1 Corr_Conj_First not only 435 | 1 Corr_Conj_Last and 436 | 1 Corr_Conj_Last nor 437 | 1 Corr_Conj_Last or 438 | 1 Corr_Conj_Last but 439 | 1 Corr_Conj_Last but also 440 | 1 Corr_Conj_First if 441 | 1 Corr_Conj_Last then 442 | 443 | 1 Noun_Conj and 444 | 1 Noun_Conj or 445 | 446 | #################### Determiners #################### 447 | 448 | # Quantifiers 449 | 1 Quant_Plur all 450 | 1 Quant_Part all 451 | 1 Quant_Plur some 452 | 1 Quant_Part some 453 | 1 Quant_Sing every 454 | 1 Quant_Plur most 455 | 1 Quant_Part most 456 | 1 Quant_Plur much 457 | 1 Quant_Part much 458 | 1 Quant_Plur more 459 | 1 Quant_Part more 460 | 1 Quant_Part no 461 | 1 Quant_Plur no 462 | 1 Quant_Sing no 463 | 464 | # Definite articles 465 | 1 Def_Article the 466 | 1 Def_Article that 467 | 1 Def_Article this 468 | 1 Def_Article_Pl these 469 | 1 Def_Article_Pl those 470 | 1 Def_Article_Pl the 471 | 472 | # Indefinite articles 473 | 1 Indef_Article a 474 | 1 Indef_Article an 475 | 476 | #################### Interrogatives #################### 477 | 478 | # Determiners which can work as an object 479 | 1 Interrog_Obj which 480 | 1 Interrog_Obj whose 481 | 1 Interrog_Obj what 482 | 483 | # Determiners 484 | 1 Interrog_Det which 485 | 1 Interrog_Det_Poss whose 486 | 1 Interrog_Det who 487 | 1 Interrog_Det when 488 | 1 Interrog_Det what 489 | 1 Interrog_Det where 490 | 491 | # Pronouns 492 | 1 Interrog_Pronoun who 493 | 1 Interrog_Pronoun whom 494 | 1 Interrog_Pronoun what 495 | 1 Interrog_Pronoun which 496 | 497 | # Pro-adverbs 498 | 1 Interrog_Proadverb where 499 | 1 Interrog_Proadverb when 500 | 1 Interrog_Proadverb how 501 | 1 Interrog_Proadverb why 502 | 503 | # Inflections 504 | 1 Infl that 505 | 1 Adj_Infl that 506 | 1 Adj_Infl which 507 | 1 Adj_Infl who 508 | 509 | #################### Verbs #################### 510 | 511 | 1 V_Inf_Tr use 512 | 1 V_Pres_Part_Tr using 513 | 1 V_Past_Part_Tr used 514 | 1 V_Base_Pres_Tr use 515 | 1 V_Base_Past_Tr used 516 | 1 V_3rdSing_Pres_Tr uses 517 | 518 | 1 V_Inf_Tr print 519 | 1 V_Pres_Part_Tr printing 520 | 1 V_Past_Part_Tr printed 521 | 1 V_Base_Pres_Tr print 522 | 1 V_Base_Past_Tr printed 523 | 1 V_3rdSing_Pres_Tr prints 524 | 525 | 1 V_Inf_Tr select 526 | 1 V_Pres_Part_Tr selecting 527 | 1 V_Past_Part_Tr selected 528 | 1 V_Base_Pres_Tr select 529 | 1 V_Base_Past_Tr selected 530 | 1 V_3rdSing_Pres_Tr selects 531 | 532 | 1 V_Inf_Tr kill 533 | 1 V_Pres_Part_Tr killing 534 | 1 V_Past_Part_Tr killed 535 | 1 V_Base_Pres_Tr kill 536 | 1 V_Base_Past_Tr killed 537 | 1 V_3rdSing_Pres_Tr kills 538 | 539 | 1 V_Inf_Tr set 540 | 1 V_Pres_Part_Tr setting 541 | 1 V_Past_Part_Tr set 542 | 1 V_Base_Pres_Tr set 543 | 1 V_Base_Past_Tr set 544 | 1 V_3rdSing_Pres_Tr sets 545 | 546 | 1 V_Inf_Tr answer 547 | 1 V_Pres_Part_Tr answering 548 | 1 V_Past_Part_Tr answered 549 | 1 V_Base_Pres_Tr answer 550 | 1 V_Base_Past_Tr answered 551 | 1 V_3rdSing_Pres_Tr answers 552 | 553 | 1 V_Inf_Tr reserve 554 | 1 V_Pres_Part_Tr reserving 555 | 1 V_Past_Part_Tr reserved 556 | 1 V_Base_Pres_Tr reserve 557 | 1 V_Base_Past_Tr reserved 558 | 1 V_3rdSing_Pres_Tr reserves 559 | 560 | 1 V_Inf_Tr revise 561 | 1 V_Pres_Part_Tr revising 562 | 1 V_Past_Part_Tr revised 563 | 1 V_Base_Pres_Tr revise 564 | 1 V_Base_Past_Tr revised 565 | 1 V_3rdSing_Pres_Tr revises 566 | 567 | 1 V_Inf_Tr change 568 | 1 V_Pres_Part_Tr changing 569 | 1 V_Past_Part_Tr changed 570 | 1 V_Base_Pres_Tr change 571 | 1 V_Base_Past_Tr changed 572 | 1 V_3rdSing_Pres_Tr changes 573 | 574 | 1 V_Inf_Tr make 575 | 1 V_Pres_Part_Tr making 576 | 1 V_Past_Part_Tr made 577 | 1 V_Base_Pres_Tr make 578 | 1 V_Base_Past_Tr made 579 | 1 V_3rdSing_Pres_Tr makes 580 | 581 | 1 V_Inf_Tr open 582 | 1 V_Pres_Part_Tr opening 583 | 1 V_Past_Part_Tr opened 584 | 1 V_Base_Pres_Tr open 585 | 1 V_Base_Past_Tr opened 586 | 1 V_3rdSing_Pres_Tr opens 587 | 588 | 1 V_Inf_Tr remove 589 | 1 V_Pres_Part_Tr removing 590 | 1 V_Past_Part_Tr removed 591 | 1 V_Base_Pres_Tr remove 592 | 1 V_Base_Part_Tr removed 593 | 1 V_3rdSing_Pres_Tr removes 594 | 595 | 1 V_Inf_Tr woo 596 | 1 V_Pres_Part_Tr wooing 597 | 1 V_Past_Part_Tr wooed 598 | 1 V_Base_Pres_Tr woo 599 | 1 V_Base_Past_Tr wooed 600 | 1 V_3rdSing_Pres_Tr woos 601 | 602 | 1 V_Inf_Tr chuck 603 | 1 V_Pres_Part_Tr chucking 604 | 1 V_Past_Part_Tr chucked 605 | 1 V_Base_Pres_Tr chuck 606 | 1 V_Base_Past_Tr chucked 607 | 1 V_3rdSing_Pres_Tr chucks 608 | 609 | 1 V_Inf_In happen 610 | 1 V_Pres_Part_In happening 611 | 1 V_Past_Part_In happened 612 | 1 V_Base_Pres_In happen 613 | 1 V_Base_Past_In happened 614 | 1 V_3rdSing_Pres_In happens 615 | 616 | 1 V_Inf_In set 617 | 1 V_Pres_Part_In setting 618 | 1 V_Past_Part_In set 619 | 1 V_Base_Pres_In set 620 | 1 V_Base_Past_In set 621 | 1 V_3rdSing_Pres_In sets 622 | 623 | 1 V_Inf_In answer 624 | 1 V_Pres_Part_In answering 625 | 1 V_Past_Part_In answered 626 | 1 V_Base_Pres_In answer 627 | 1 V_Base_Past_In answered 628 | 1 V_3rdSing_Pres_In answers 629 | 630 | 1 V_Inf_In change 631 | 1 V_Pres_Part_In changing 632 | 1 V_Past_Part_In changed 633 | 1 V_Base_Pres_In change 634 | 1 V_Base_Past_In changed 635 | 1 V_3rdSing_Pres_In changes 636 | 637 | 1 V_Inf_In make 638 | 1 V_Pres_Part_In making 639 | 1 V_Past_Part_In made 640 | 1 V_Base_Pres_In make 641 | 1 V_Base_Past_In made 642 | 1 V_3rdSing_Pres_In makes 643 | 644 | 1 V_Inf_In open 645 | 1 V_Pres_Part_In opening 646 | 1 V_Past_Part_In opened 647 | 1 V_Base_Pres_In open 648 | 1 V_Base_Past_In opened 649 | 1 V_3rdSing_Pres_In opens 650 | 651 | 1 V_Inf_In go 652 | 1 V_Pres_Part_In going 653 | 1 V_Past_Part_In gone 654 | 1 V_Base_Pres_In go 655 | 1 V_Base_Past_In went 656 | 1 V_3rdSing_Pres_In goes 657 | 658 | 1 V_Inf_Tr get 659 | 1 V_Pres_Part_Tr getting 660 | 1 V_Past_Part_Tr gotten 661 | 1 V_Base_Pres_Tr get 662 | 1 V_Base_Past_Tr got 663 | 1 V_3rdSing_Pres_In gets 664 | 665 | 1 V_Inf_In speak 666 | 1 V_Pres_Part_In speaking 667 | 1 V_Past_Part_In spoken 668 | 1 V_Base_Pres_In speak 669 | 1 V_Base_Past_In spoke 670 | 1 V_3rdSing_Pres_In speaks 671 | 672 | 1 V_Inf_Tr know 673 | 1 V_Pres_Part_Tr knowing 674 | 1 V_Past_Part_Tr known 675 | 1 V_Base_Pres_Tr know 676 | 1 V_Base_Past_Tr knew 677 | 1 V_3rdSing_Pres_Tr knows 678 | 679 | 1 V_Inf_In know 680 | 1 V_Pres_Part_In knowing 681 | 1 V_Past_Part_In known 682 | 1 V_Base_Pres_In know 683 | 1 V_Base_Past_In knew 684 | 1 V_3rdSing_Pres_In knows 685 | 686 | 1 V_Inf_Tr feel 687 | 1 V_Pres_Part_Tr feeling 688 | 1 V_Past_Part_Tr felt 689 | 1 V_Base_Pres_Tr feel 690 | 1 V_Base_Past_Tr felt 691 | 1 V_3rdSing_Pres_Tr feels 692 | 693 | 1 V_Inf_Tr take 694 | 1 V_Pres_Part_Tr taking 695 | 1 V_Past_Part_Tr taken 696 | 1 V_Base_Pres_Tr take 697 | 1 V_Base_Past_Tr took 698 | 1 V_3rdSing_Pres_Tr takes 699 | 700 | 1 V_Inf_Tr specify 701 | 1 V_Pres_Part_Tr specifying 702 | 1 V_Past_Part_Tr specified 703 | 1 V_Base_Pres_Tr specify 704 | 1 V_Base_Past_Tr specified 705 | 1 V_3rdSing_Pres_Tr specifies 706 | 707 | 1 V_Inf_In count 708 | 1 V_Pres_Part_In counting 709 | 1 V_Past_Part_In counted 710 | 1 V_Base_Pres_In count 711 | 1 V_Base_Past_In counted 712 | 1 V_3rdSing_Pres_In counts 713 | 714 | 1 V_Inf_Tr count 715 | 1 V_Pres_Part_Tr counting 716 | 1 V_Past_Part_Tr counted 717 | 1 V_Base_Pres_Tr count 718 | 1 V_Base_Past_Tr counted 719 | 1 V_3rdSing_Pres_Tr counts 720 | 721 | 1 V_Inf_Tr bring 722 | 1 V_Pres_Part_Tr bringing 723 | 1 V_Past_Part_Tr brought 724 | 1 V_Base_Pres_Tr bring 725 | 1 V_Base_Past_Tr brought 726 | 1 V_3rdSing_Pres_Tr brings 727 | 728 | 1 V_Inf_Tr dye 729 | 1 V_Pres_Part_Tr dying 730 | 1 V_Past_Part_Tr dyed 731 | 1 V_Base_Pres_Tr dye 732 | 1 V_Base_Past_Tr dyed 733 | 1 V_3rdSing_Pres_Tr dyes 734 | 735 | 1 V_Inf_Tr trap 736 | 1 V_Pres_Part_Tr trapping 737 | 1 V_Past_Part_Tr trapped 738 | 1 V_Base_Pres_Tr trap 739 | 1 V_Base_Past_Tr trapped 740 | 1 V_3rdSing_Pres_Tr traps 741 | 742 | 1 V_Inf_In miss 743 | 1 V_Pres_Part_In missing 744 | 1 V_Past_Part_In missed 745 | 1 V_Base_Pres_In miss 746 | 1 V_Base_Past_In missed 747 | 1 V_3rdSing_Pres_In misses 748 | 749 | 1 V_Inf_Tr bootstrap 750 | 1 V_Pres_Part_Tr bootstrapping 751 | 1 V_Past_Part_Tr bootstrapped 752 | 1 V_Base_Pres_Tr bootstrap 753 | 1 V_Base_Past_Tr bootstrapped 754 | 1 V_3rdSing_Pres_Tr bootstraps 755 | 756 | 1 V_Inf_In walk 757 | 1 V_Pres_Part_In walking 758 | 1 V_Past_Part_In walked 759 | 1 V_Base_Pres_In walk 760 | 1 V_Base_Past_In walked 761 | 1 V_3rdSing_Pres_In walks 762 | 763 | 1 V_Inf_Tr walk 764 | 1 V_Pres_Part_Tr walking 765 | 1 V_Past_Part_Tr walked 766 | 1 V_Base_Pres_Tr walk 767 | 1 V_Base_Past_Tr walked 768 | 1 V_3rdSing_Pres_Tr walks 769 | 770 | 1 V_Inf_In try 771 | 1 V_Pres_Part_In trying 772 | 1 V_Past_Part_In tried 773 | 1 V_Base_Pres_In try 774 | 1 V_Base_Past_In tried 775 | 1 V_3rdSing_Pres_In tries 776 | 777 | 1 V_Inf_Tr try 778 | 1 V_Pres_Part_Tr trying 779 | 1 V_Past_Part_Tr tried 780 | 1 V_Base_Pres_Tr try 781 | 1 V_Base_Past_Tr tried 782 | 1 V_3rdSing_Pres_Tr tries 783 | 784 | 1 V_Inf_Tr do 785 | 1 V_Pres_Part_Tr doing 786 | 1 V_Past_Part_Tr done 787 | 1 V_Base_Pres_Tr do 788 | 1 V_Base_Past_Tr did 789 | 1 V_3rdSing_Pres_Tr does 790 | 791 | 1 V_Inf_Tr call 792 | 1 V_Pres_Part_Tr calling 793 | 1 V_Past_Part_Tr called 794 | 1 V_Base_Pres_Tr call 795 | 1 V_Base_Past_Tr called 796 | 1 V_3rdSing_Pres_Tr calls 797 | 798 | 1 V_Inf_In call 799 | 1 V_Pres_Part_In calling 800 | 1 V_Past_Part_In called 801 | 1 V_Base_Pres_In call 802 | 1 V_Base_Past_In called 803 | 1 V_3rdSing_Pres_In calls 804 | 805 | 1 V_Inf_In think 806 | 1 V_Pres_Part_In thinking 807 | 1 V_Past_Part_In thought 808 | 1 V_Base_Pres_In think 809 | 1 V_Base_Past_In thought 810 | 1 V_3rdSing_Pres_In thinks 811 | 812 | 1 V_Inf_In tell 813 | 1 V_Pres_Part_In telling 814 | 1 V_Past_Part_In told 815 | 1 V_Base_Pres_In tell 816 | 1 V_Base_Past_In told 817 | 1 V_3rdSing_Pres_In tells 818 | 819 | 1 V_Inf_Tr tell 820 | 1 V_Pres_Part_Tr telling 821 | 1 V_Past_Part_Tr told 822 | 1 V_Base_Pres_Tr tell 823 | 1 V_Base_Past_Tr told 824 | 1 V_3rdSing_Pres_Tr tells 825 | 826 | 1 V_Inf_Tr want 827 | 1 V_Pres_Part_Tr wanting 828 | 1 V_Past_Part_Tr wanted 829 | 1 V_Base_Pres_Tr want 830 | 1 V_Base_Past_Tr wanted 831 | 1 V_3rdSing_Pres_Tr wants 832 | 833 | 1 V_Inf_Tr mean 834 | 1 V_Pres_Part_Tr meaning 835 | 1 V_Past_Part_Tr meant 836 | 1 V_Base_Pres_Tr mean 837 | 1 V_Base_Past_Tr meant 838 | 1 V_3rdSing_Pres_Tr means 839 | 840 | 1 V_Inf_Tr prevent 841 | 1 V_Pres_Part_Tr preventing 842 | 1 V_Past_Part_Tr prevented 843 | 1 V_Base_Pres_Tr prevent 844 | 1 V_Base_Past_Tr prevented 845 | 1 V_3rdSing_Pres_Tr prevents 846 | 847 | 1 V_Inf_Tr fill 848 | 1 V_Pres_Part_Tr filling 849 | 1 V_Past_Part_Tr filled 850 | 1 V_Base_Pres_Tr fill 851 | 1 V_Base_Past_Tr filled 852 | 1 V_3rdSing_Pres_Tr fills 853 | 854 | 1 V_Inf_Tr remove 855 | 1 V_Pres_Part_Tr removing 856 | 1 V_Past_Part_Tr removed 857 | 1 V_Base_Pres_Tr remove 858 | 1 V_Base_Past_Tr removed 859 | 1 V_3rdSing_Pres_Tr removes 860 | 861 | 1 V_Inf_Tr check 862 | 1 V_Pres_Part_Tr checking 863 | 1 V_Past_Part_Tr checked 864 | 1 V_Base_Pres_Tr check 865 | 1 V_Base_Past_Tr checked 866 | 1 V_3rdSing_Pres_Tr checks 867 | 868 | 1 V_Inf_Tr copy 869 | 1 V_Pres_Part_Tr copying 870 | 1 V_Past_Part_Tr copied 871 | 1 V_Base_Pres_Tr copy 872 | 1 V_Base_Past_Tr copied 873 | 1 V_3rdSing_Pres_Tr copies 874 | 875 | 1 V_Inf_Tr paste 876 | 1 V_Pres_Part_Tr pasting 877 | 1 V_Past_Part_Tr pasted 878 | 1 V_Base_Pres_Tr paste 879 | 1 V_Base_Past_Tr pasted 880 | 1 V_3rdSing_Pres_Tr pastes 881 | 882 | 1 V_Inf_Tr customize 883 | 1 V_Pres_Part_Tr customizing 884 | 1 V_Past_Part_Tr customized 885 | 1 V_Base_Pres_Tr customize 886 | 1 V_Base_Past_Tr customized 887 | 1 V_3rdSing_Pres_Tr customizes 888 | 889 | 1 V_Inf_Tr disable 890 | 1 V_Pres_Part_Tr disabling 891 | 1 V_Past_Part_Tr disabled 892 | 1 V_Base_Pres_Tr disable 893 | 1 V_Base_Past_Tr disabled 894 | 1 V_3rdSing_Pres_Tr disables 895 | 896 | 1 V_Inf_Tr help 897 | 1 V_Pres_Part_Tr helping 898 | 1 V_Past_Part_Tr helped 899 | 1 V_Base_Pres_Tr help 900 | 1 V_Base_Past_Tr helped 901 | 1 V_3rdSing_Pres_Tr helps 902 | 903 | 1 V_Inf_Tr move 904 | 1 V_Pres_Part_Tr moving 905 | 1 V_Past_Part_Tr moved 906 | 1 V_Base_Pres_Tr move 907 | 1 V_Base_Past_Tr moved 908 | 1 V_3rdSing_Pres_Tr moves 909 | 910 | 1 V_Inf_Tr ask 911 | 1 V_Pres_Part_Tr asking 912 | 1 V_Past_Part_Tr asked 913 | 1 V_Base_Pres_Tr ask 914 | 1 V_Base_Past_Tr asked 915 | 1 V_3rdSing_Pres_Tr asks 916 | 917 | #################### Modals #################### 918 | 919 | # present form 920 | 1 Modal_Pres shall 921 | 1 Modal_Pres should 922 | 1 Modal_Pres will 923 | 1 Modal_Pres_Neg won't 924 | 1 Modal_Pres may 925 | 1 Modal_Pres can 926 | 1 Modal_Pres_Neg cannot 927 | 1 Modal_Pres_Neg can't 928 | 1 Modal_Pres must 929 | 930 | 1 Not not 931 | 1 Have have 932 | 1 Not n't 933 | 934 | # preterite form 935 | 1 Modal_Past should 936 | 1 Modal_Past_Neg shouldn't 937 | 1 Modal_Past would 938 | 1 Modal_Past_Neg wouldn't 939 | 1 Modal_Past might 940 | 1 Modal_Past could 941 | 1 Modal_Past_Neg couldn't 942 | 1 Modal_Past must 943 | 944 | #################### Auxiliaries #################### 945 | 946 | 1 Aux_3rd does 947 | 1 Aux_3rd will 948 | 1 Aux do 949 | 1 Aux will 950 | 951 | #################### Verb Exceptions #################### 952 | 953 | # Verb exceptions - being verbs 954 | 1 Be_Inf be 955 | 1 Be_Pres_Part being 956 | 1 Be_Past_Part been 957 | 1 Be_1stSing_Pres am 958 | 1 Be_2ndSing_Pres are 959 | 1 Be_3rdSing_Pres is 960 | 1 Be_3rdSing_Pres 's 961 | 1 Be_1stPlur_Pres are 962 | 1 Be_2ndPlur_Pres are 963 | 1 Be_3rdPlur_Pres are 964 | 1 Be_1stSing_Past was 965 | 1 Be_2ndSing_Past were 966 | 1 Be_3rdSing_Past was 967 | 1 Be_1stPlur_Past were 968 | 1 Be_2ndPlur_Past were 969 | 1 Be_3rdPlur_Past were 970 | 971 | 1 Being_Inf be 972 | 1 Being_Pres_Part being 973 | 1 Being_Past_Part been 974 | 1 Being_1stSing_Pres am 975 | 1 Being_2ndSing_Pres are 976 | 1 Being_3rdSing_Pres is 977 | 1 Being_1stPlur_Pres are 978 | 1 Being_2ndPlur_Pres are 979 | 1 Being_3rdPlur_Pres are 980 | 1 Being_1stSing_Past was 981 | 1 Being_2ndSing_Past were 982 | 1 Being_3rdSing_Past was 983 | 1 Being_1stPlur_Past were 984 | 1 Being_2ndPlur_Past were 985 | 1 Being_3rdPlur_Past were 986 | 987 | 1 Being_Inf feel 988 | 1 Being_Pres_Part feeling 989 | 1 Being_Past_Part felt 990 | 1 Being_Base_Pres feel 991 | 1 Being_Base_Past felt 992 | 1 Being_3rdSing_Pres feels 993 | 994 | 1 Causal_Inf get 995 | 1 Causal_Pres_Part getting 996 | 1 Causal_Past_Part gotten 997 | 1 Causal_Base_Pres get 998 | 1 Causal_Base_Past got 999 | 1 Causal_3rdSing_Pres gets 1000 | 1001 | # Verb exceptions - expressive verbs 1002 | 1003 | 1 Exp_Inf know 1004 | 1 Exp_Pres_Part knowing 1005 | 1 Exp_Past_Part known 1006 | 1 Exp_Base_Pres know 1007 | 1 Exp_Base_Past knew 1008 | 1 Exp_3rdSing_Pres knows 1009 | 1010 | 1 Exp_Inf think 1011 | 1 Exp_Pres_Part thinking 1012 | 1 Exp_Past_Part thought 1013 | 1 Exp_Base_Pres think 1014 | 1 Exp_Base_Past thought 1015 | 1 Exp_3rdSing_Pres thinks 1016 | 1017 | 1 Do_Inf do 1018 | 1 Do_Pres_Part doing 1019 | 1 Do_Past_Part done 1020 | 1 Do_Base_Pres do 1021 | 1 Do_Base_Past did 1022 | 1 Do_3rdSing_Pres does 1023 | 1024 | 1 Go_Inf go 1025 | 1 Go_Pres_Part going 1026 | 1 Go_Past_Part gone 1027 | 1 Go_Base_Pres go 1028 | 1 Go_Base_Past went 1029 | 1 Go_3rdSing_Pres goes 1030 | 1031 | #################### Punctuation #################### 1032 | 1033 | 1 Comma , 1034 | 1 Punc . 1035 | 1 PuncQ ? 1036 | 1 Punc ! 1037 | 1038 | #################### Prepositions #################### 1039 | 1040 | 1 Prep aboard 1041 | 1 Prep about 1042 | 1 Prep above 1043 | 1 Prep across 1044 | 1 Prep after 1045 | 1 Prep against 1046 | 1 Prep along 1047 | 1 Prep alongside 1048 | 1 Prep amid 1049 | 1 Prep amidst 1050 | 1 Prep among 1051 | 1 Prep amongst 1052 | 1 Prep around 1053 | 1 Prep as 1054 | 1 Prep aside 1055 | 1 Prep at 1056 | 1 Prep atop 1057 | 1 Prep before 1058 | 1 Prep behind 1059 | 1 Prep below 1060 | 1 Prep beneath 1061 | 1 Prep beside 1062 | 1 Prep between 1063 | 1 Prep beyond 1064 | 1 Prep by 1065 | 1 Prep for 1066 | 1 Prep from 1067 | 1 Prep in 1068 | 1 Prep inside 1069 | 1 Prep into 1070 | 1 Prep near 1071 | 1 Prep of 1072 | 1 Prep off 1073 | 1 Prep on 1074 | 1 Prep onto 1075 | 1 Prep opposite 1076 | 1 Prep outside 1077 | 1 Prep over 1078 | 1 Prep past 1079 | 1 Prep round 1080 | 1 Prep than 1081 | 1 Prep through 1082 | 1 Prep throughout 1083 | 1 Prep to 1084 | 1 Prep toward 1085 | 1 Prep towards 1086 | 1 Prep under 1087 | 1 Prep underneath 1088 | 1 Prep upon 1089 | 1 Prep via 1090 | 1 Prep with 1091 | 1 Prep within 1092 | 1 Prep without 1093 | 1 Prep like 1094 | 1095 | #################### Misc #################### 1096 | 1097 | 1 File_Addr fs/binfmt_efl.c 1098 | 1 Web_Addr web.mit.edu/geofft/www 1099 | 1 Quote_Single ' 1100 | 1 Quote_Double " 1101 | 1102 | 1 Of of 1103 | 1 To to 1104 | 1105 | 1 Adj_State awesome 1106 | 1 Adv really 1107 | 1 Adj_State cool 1108 | 1 Noun_Pl ponies 1109 | 1 Adj_State better 1110 | 1 Noun_Pl unicorns 1111 | 1 Noun_Pl dragons 1112 | 1 V_Inf_Tr hear 1113 | 1 V_Pres_Part_Tr hearing 1114 | 1 V_Past_Part_Tr heard 1115 | 1 V_Base_Pres_Tr hear 1116 | 1 V_3rdSing_Pres_Tr hears 1117 | 1 V_Base_Past_Tr heard 1118 | 1 Noun_Pl doggies 1119 | 1 Noun_Pl cats 1120 | 1 Noun_Pl birds 1121 | 1 V_Inf_In dance 1122 | 1 V_Pres_Part_In dancing 1123 | 1 V_Past_Part_In danced 1124 | 1 V_Base_Pres_In dance 1125 | 1 V_3rdSing_Pres_In dances 1126 | 1 V_Base_Past_In danced 1127 | 1 V_Inf_In sing 1128 | 1 V_Pres_Part_In singing 1129 | 1 V_Past_Part_In sung 1130 | 1 V_Base_Pres_In sing 1131 | 1 V_3rdSing_Pres_In sings 1132 | 1 V_Base_Past_In sang 1133 | 1 Noun pony 1134 | 1 Noun unicorn 1135 | 1 Adj_State smart 1136 | 1 Adj_State favorite 1137 | 1 Noun life 1138 | 1 Noun meaning 1139 | 1 Noun_Pl meanings 1140 | 1 Noun test 1141 | 1 Noun noun 1142 | 1 Noun_Pl words 1143 | 1 Noun part 1144 | 1 Noun speech 1145 | 1 Noun morning 1146 | 1 Noun_Pl hamsters 1147 | 1 Noun_Pl macs 1148 | 1 Noun acronym 1149 | 1 Noun_Pl dogs 1150 | 1 Noun_Pl kitties 1151 | 1 Noun_Pl fishies 1152 | 1 Noun default 1153 | 1 V_Inf_Tr read 1154 | 1 V_Pres_Part_Tr reading 1155 | 1 V_Past_Part_Tr read 1156 | 1 V_Base_Pres_Tr read 1157 | 1 V_3rdSing_Pres_Tr reads 1158 | 1 V_Base_Past_Tr read 1159 | 1 V_Inf_In swim 1160 | 1 V_Pres_Part_In swimming 1161 | 1 V_Past_Part_In swum 1162 | 1 V_Base_Pres_In swim 1163 | 1 V_3rdSing_Pres_In swims 1164 | 1 V_Base_Past_In swam 1165 | 1 V_Inf_In run 1166 | 1 V_Pres_Part_In running 1167 | 1 V_Past_Part_In run 1168 | 1 V_Base_Pres_In run 1169 | 1 V_3rdSing_Pres_In runs 1170 | 1 V_Base_Past_In ran 1171 | 1 Noun paste 1172 | 1 Noun_Pl pastes 1173 | 1174 | 1 Noun job 1175 | 1 Noun queue 1176 | 1 Noun document 1177 | 1178 | 1 Noun document 1179 | 1 Noun print 1180 | 1 Noun_Pl daleks 1181 | 1 Noun karl 1182 | 1 Noun knowledge 1183 | 1 Noun extermination 1184 | 1 Noun entertainment 1185 | 1 Noun value 1186 | 1 Noun hatred 1187 | 1 Noun username 1188 | 1 Noun mitsfs 1189 | 1 Noun perl 1190 | 1 Noun eliza 1191 | 1 Noun php 1192 | 1 Adj_State evil 1193 | 1 Noun_Pl yaks 1194 | 1 V_Inf_In shave 1195 | 1 V_Pres_Part_In shaving 1196 | 1 V_Past_Part_In shaved 1197 | 1 V_Base_Pres_In shave 1198 | 1 V_3rdSing_Pres_In shaves 1199 | 1 V_Base_Past_In shaved 1200 | 1 Noun yak 1201 | 1 Noun foo 1202 | 1 Noun word 1203 | 1 Noun intro 1204 | 1 Noun printer 1205 | 1 Noun double-sided 1206 | 1 Noun print 1207 | 1 Noun purpose 1208 | 1 Noun vim 1209 | 1 Noun c-x 1210 | 1 Noun universe 1211 | 1 Noun everything 1212 | 1 Noun sfs 1213 | 1 V_Inf_In stand 1214 | 1 V_Pres_Part_In standing 1215 | 1 V_Past_Part_In stood 1216 | 1 V_Base_Pres_In stand 1217 | 1 V_3rdSing_Pres_In stands 1218 | 1 V_Base_Past_In stood 1219 | 1 V_Inf_Tr quit 1220 | 1 V_Pres_Part_Tr quitting 1221 | 1 V_Past_Part_Tr quit 1222 | 1 V_Base_Pres_Tr quit 1223 | 1 V_3rdSing_Pres_Tr quits 1224 | 1 V_Base_Past_Tr quit 1225 | 1 V_Inf_Tr hate 1226 | 1 V_Pres_Part_Tr hating 1227 | 1 V_Past_Part_Tr hated 1228 | 1 V_Base_Pres_Tr hate 1229 | 1 V_3rdSing_Pres_Tr hates 1230 | 1 V_Base_Past_Tr hated 1231 | 1 V_Inf_Tr stab 1232 | 1 V_Pres_Part_Tr stabbing 1233 | 1 V_Past_Part_Tr stabbed 1234 | 1 V_Base_Pres_Tr stab 1235 | 1 V_3rdSing_Pres_Tr stabs 1236 | 1 V_Base_Past_Tr stabbed 1237 | 1 Noun csail -------------------------------------------------------------------------------- /webUI.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import threading 3 | import SocketServer 4 | 5 | socket.setdefaulttimeout(10) 6 | 7 | hostServerIP="18.111.23.79" 8 | 9 | class MyTCPHandler(SocketServer.BaseRequestHandler): 10 | """ 11 | The RequestHandler class for our server. 12 | 13 | It is instantiated once per connection to the server, and must 14 | override the handle() method to implement communication to the 15 | client. 16 | """ 17 | 18 | def __init__(self): 19 | topics = load_topics("doctopics/topics.xml") 20 | sessions['webDodona']=Session('webDododna',topics) 21 | 22 | def handle(self): 23 | """recieves statement from the user """ 24 | print "handling request..." 25 | # self.request is the TCP socket connected to the client 26 | try: 27 | self.userspeak = self.request.recv(1024).strip() 28 | except socket.timeout: 29 | print 'socket timed out' 30 | return 31 | print "%s wrote:" % self.client_address[0] 32 | print self.userspeak 33 | dodonaspeak=self.respond(self.userspeak) 34 | # just send back the same data, but upper-cased 35 | self.request.send(dodonaspeak) 36 | 37 | def wordwrap(self,statement,numchars=70): 38 | if len(statement)>numchars: 39 | return statement[0:79]+'\n'+self.wordwrap(statement[79:]) 40 | else: 41 | return statement 42 | 43 | def respond(self,statement): 44 | return self.wordwrap("I don't know anything about "+str(statement)+" please ask again.") 45 | 46 | class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 47 | pass 48 | 49 | def startdaemon(): 50 | HOST, PORT = hostServerIP, 9999 51 | 52 | # Create the server, binding to localhost on port 9999 53 | server = ThreadedTCPServer((HOST, PORT), MyTCPHandler) 54 | 55 | # Start a thread with the server -- that thread will then start one 56 | # more thread for each request 57 | #server_thread = threading.Thread(target=server.serve_forever) 58 | # Exit the server thread when the main thread terminates 59 | #server_thread.setDaemon(True) 60 | #server_thread.start() 61 | print "Server daemon started..." 62 | server.serve_forever() 63 | 64 | if __name__ == "__main__": 65 | startdaemon() 66 | 67 | 68 | -------------------------------------------------------------------------------- /www/.README.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhamrick/dodona/2f11ee2b21cc7de523b3222fbf7a24579262bc3e/www/.README.swp -------------------------------------------------------------------------------- /www/.dodona.css.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhamrick/dodona/2f11ee2b21cc7de523b3222fbf7a24579262bc3e/www/.dodona.css.swp -------------------------------------------------------------------------------- /www/.handler.php.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jhamrick/dodona/2f11ee2b21cc7de523b3222fbf7a24579262bc3e/www/.handler.php.swp -------------------------------------------------------------------------------- /www/README: -------------------------------------------------------------------------------- 1 | = Web Interface for Dodona= 2 | 3 | == Project subdirectories == 4 | *console - an AJAX-enabled console application 5 | *gateway - a portal to the bot 6 | 7 | == Overview == 8 | (not completely accurate, but close enough) 9 | 10 | client________ __server__________________ 11 | | | | | 12 | | <---[HTTP]---> console.html | 13 | | browser | | | 14 | | <---[AJAX]---> gateway.php <----| | 15 | |______________| | [socket] | 16 | | daemon.py <----| | 17 | |__________________________| 18 | 19 | Here's how it works: 20 | 21 | 1) client open consle web page 22 | 2) client enters query and presses 'send' 23 | 3) console app sends query gateway.php via AJAX 24 | 4) gateway.php passes the query to the bot, which is 25 | running on the server inside a daemon thread and 26 | listening on (localhost,9999) 27 | 5) bot returns response via socket 28 | 6) gateway.php sends response to client 29 | 7) console app display result 30 | 31 | == Design Decisions == 32 | *Why a PHP gateway?* 33 | Python as a CGI script sucks. You have to write 34 | the headers yourself. (I may be doing this wrong, 35 | so please correct me if you know an easy way to 36 | use python to serve a page.) 37 | 38 | PHP is quick and it works. gateway.php is not a 39 | huge app. It's just a proxy for the bot that does 40 | some basic gatekeeping (rejecting invalid requests, 41 | etc...), so it doesn't need anything fancy. 42 | 43 | 44 | *Why have a gateway at all?* 45 | Dodona needs to sit inside a daemon thread so she 46 | doesn't have to reinitialize for each request. This 47 | is accomplished easily enough in python, but how 48 | she communicate with the outside world? 49 | 50 | Unfortunately, Python's socket handling sucks. You 51 | have to patch the libraries to get support for basic 52 | functionality like timeouts. This is fixed in 2.6 and 53 | 3000, but we probably won't have the luxury of using 54 | these. 55 | 56 | Also, I'm pretty sure Apache is just Better than a 57 | Python server at handling the AJAX web requests. We'd 58 | have to set up mod_python or twisted or some other 59 | Python server in order to have the client app interface 60 | directly with Dodona over HTTP. 61 | (corrections to this are welcome...) 62 | 63 | This means we need a simple gateway that can communicate 64 | over HTTP with the client, and via a socket with Dodona. 65 | This also grants us the ability to validate input before 66 | passing it to Dodona, so we can reduce the load on the 67 | bot herself. 68 | 69 | == TODO == 70 | - configuration 71 | -- daemon startup options (HOSTNAME,PORT) 72 | -- gateway config file (HOSTNAME,PORT) 73 | - stop server by pressing 74 | - more features in for the console 75 | -- history? 76 | -- submit on '.' 77 | -- proper overflow handling (inner div with fixed width) 78 | - web docs / about page 79 | -------------------------------------------------------------------------------- /www/dodona.css: -------------------------------------------------------------------------------- 1 | #content { 2 | width: 550px; 3 | margin: 10px; 4 | text-align: right; 5 | } 6 | 7 | #chatbox { 8 | white-space: pre; 9 | padding: 10px; 10 | border: 1px solid #666; 11 | background: #000; 12 | color: #fff; 13 | font-family: monospace; 14 | height: 300px; 15 | margin-bottom: 10px; 16 | text-align: left; 17 | overflow: auto; 18 | } 19 | 20 | #chatinput { 21 | width: 100%; 22 | height: 140px; 23 | } 24 | -------------------------------------------------------------------------------- /www/dodona.js: -------------------------------------------------------------------------------- 1 | $(function onready(){ 2 | $('#sendbutton').click(function(){ 3 | var input = $('#chatinput').val(); 4 | $.get('handler.php?msg='+input, 5 | function(data){ 6 | $('#chatbox').text($('#chatbox').text()+'> '+input+'\n'+data+'\n'); 7 | },'text'); 8 | }); 9 | }); 10 | /* this needs to be able to word-wrap to 70 chars.*/ 11 | -------------------------------------------------------------------------------- /www/handler.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 |
10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /www/jquery-1.2.6.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery 1.2.6 - New Wave Javascript 3 | * 4 | * Copyright (c) 2008 John Resig (jquery.com) 5 | * Dual licensed under the MIT (MIT-LICENSE.txt) 6 | * and GPL (GPL-LICENSE.txt) licenses. 7 | * 8 | * $Date: 2008-05-24 14:22:17 -0400 (Sat, 24 May 2008) $ 9 | * $Rev: 5685 $ 10 | */ 11 | (function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else 12 | return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else 13 | return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else 14 | selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else 16 | this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else 17 | return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else 18 | jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else 22 | jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("",""]||!tags.indexOf("",""]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
"]||!tags.indexOf("",""]||(!tags.indexOf("",""]||!tags.indexOf("",""]||jQuery.browser.msie&&[1,"div
","
"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf(""&&tags.indexOf("=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else 23 | ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&¬xml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else 24 | while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return im[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else 26 | for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("
").append(res.responseText.replace(//g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else 28 | xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else 29 | jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else 30 | for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else 31 | s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else 32 | e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;ithis.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); -------------------------------------------------------------------------------- /xml_parser.py: -------------------------------------------------------------------------------- 1 | import site 2 | site.addsitedir('/afs/athena.mit.edu/user/b/r/broder/lib/python2.5/site-packages') 3 | from xml.dom import minidom 4 | 5 | def load_topics(file): 6 | """ 7 | Loads the topics from the specified file, 8 | and parse the XML to find the file which 9 | each topic is associated with. Returns a 10 | dictionary of the topics and their associated 11 | infomation. 12 | """ 13 | topics = {} 14 | xmldoc = minidom.parse(file) 15 | topicsNode = xmldoc.firstChild 16 | for topic in topicsNode.childNodes: 17 | if topic.nodeType == topic.ELEMENT_NODE and topic.localName == "topic": 18 | topic_name = topic.attributes["name"].value.lower() 19 | topic_file = topic.attributes["file"].value 20 | topics[topic_name.encode('ascii')] = load_topic(topic_file) 21 | for topic in topicsNode.childNodes: 22 | if topic.nodeType == topic.ELEMENT_NODE and topic.localName == "alias": 23 | topic_name = topic.attributes["name"].value.lower() 24 | topic_file = topic.attributes["to"].value 25 | topics[topic_name.encode('ascii')] = topics[(topic_file)] 26 | 27 | print topics.keys() 28 | return topics 29 | 30 | def load_topic(file): 31 | """ 32 | Load the information about a topic from 33 | the specified file, and return a dictionary 34 | with said information. 35 | """ 36 | answers = {} 37 | print "Loading " + file + "..." 38 | xmldoc = minidom.parse(file) 39 | topicNode = xmldoc.firstChild 40 | for answer in topicNode.childNodes: 41 | if answer.nodeType == answer.ELEMENT_NODE: 42 | if answer.localName == "answer": 43 | answer_question = answer.attributes["question"].value.lower() 44 | answers[answer_question.encode('ascii')] = answer.firstChild.data 45 | elif answer.localName == "default": 46 | default_answer = answer.firstChild.data 47 | answers["default"] = default_answer 48 | return answers 49 | 50 | def update_files(topic, topics, newtopic=True): 51 | """ 52 | Updates the XML files with new information, which 53 | is added by users. 54 | """ 55 | file = open("./doctopics/" + topic + ".xml", "w") 56 | file.write("\n") 57 | file.write("\n") 58 | file.write("Overview of " + topic + "\n") 59 | 60 | for subtopic in topics[topic]: 61 | file.write("\n") 62 | file.write(topics[topic][subtopic] + "\n") 63 | file.write("\n") 64 | 65 | file.write("") 66 | file.close() 67 | 68 | if newtopic: 69 | file = open("./doctopics/topics.xml", "r") 70 | f = [] 71 | line = None 72 | while line != "": 73 | line = file.readline() 74 | if line.find("") == -1: 75 | f.append(line) 76 | else: 77 | f.append("\n") 78 | f.append(line) 79 | 80 | file.close() 81 | file = open("./doctopics/topics.xml", "w") 82 | for line in f: 83 | file.write(line) 84 | 85 | file.close() 86 | -------------------------------------------------------------------------------- /zephyrUI.py: -------------------------------------------------------------------------------- 1 | import site 2 | site.addsitedir('/afs/athena.mit.edu/user/b/r/broder/lib/python2.5/site-packages') 3 | import zephyr 4 | from helper import custom_fill, tokenize 5 | import traceback 6 | 7 | class IO: 8 | def __init__(self, c = "dodona-test"): 9 | """ 10 | Initializes the python-zephyr utilities. 11 | """ 12 | self.cls = c 13 | # initialize zephyr 14 | zephyr.init() 15 | # subscribe to the specified cls 16 | zephyr.Subscriptions().add((self.cls, '*', '*')) 17 | # send an initialization message 18 | self.send(custom_fill('Dodona is now running. If you find that a topic you wish answered is not accounted for, please send mail to dodona AT mit DOT edu')) 19 | 20 | def send(self, mess, name = None): 21 | """ 22 | Sends a zephyr to the specified cls, addressing 23 | a specific person if specified. 24 | """ 25 | if name != None: 26 | mess = name + ": " + mess 27 | 28 | mess = mess.decode("utf-8") # decode the message 29 | mess = custom_fill(mess) 30 | # try to send the message 31 | try: 32 | z = zephyr.ZNotice(cls=self.cls, fields=["", mess], sender='dodona@ATHENA.MIT.EDU') 33 | foo = str(z.__dict__) 34 | z.send() 35 | except KeyboardInterrupt: 36 | "Dodona is no longer running." 37 | raise 38 | except: 39 | print traceback.format_exc() 40 | 41 | def receive_from_subs(self, return_sender=False): 42 | """ 43 | Receive a message from the cls specified in the 44 | init method, and returns the message and the sender of the 45 | message if return_sender is True. 46 | """ 47 | received = False 48 | while not received: # loop until you recieve a message 49 | try: 50 | m = zephyr.receive(True) 51 | received = True 52 | except KeyboardInterrupt: 53 | self.send("Dodona is no longer running.") 54 | raise 55 | except: 56 | continue 57 | 58 | # ignore messages from yourself 59 | while m.sender == 'dodona@ATHENA.MIT.EDU': 60 | try: 61 | m = zephyr.receive(True) 62 | except KeyboardInterrupt: 63 | self.send("Dodona is no longer running.") 64 | raise 65 | except: 66 | continue 67 | 68 | # ignore empty messages 69 | while m.__dict__['fields'][1].lower().strip() == "": 70 | try: 71 | m = zephyr.receive(True) 72 | except KeyboardInterrupt: 73 | self.send("Dodona is no longer running.") 74 | raise 75 | except: 76 | continue 77 | 78 | # ignore messages from anywhere except the specified 79 | # class 80 | while m.cls != self.cls: 81 | try: 82 | m = zephyr.receive(True) 83 | except KeyboardInterrupt: 84 | self.send("Dodona is no longer running.") 85 | raise 86 | except: 87 | continue 88 | 89 | print "From: ", m.sender 90 | print "Instance: ", m.instance 91 | print "Message: ", m.__dict__['fields'][1] 92 | 93 | sender = m.sender 94 | m = m.__dict__['fields'][1] 95 | # clean the message of trailing whitespce 96 | # and convert it to lowercase 97 | try: 98 | m = str(m.strip().lower()) 99 | except KeyboardInterrupt: 100 | self.send("Dodona is no longer running.") 101 | raise 102 | except: 103 | print traceback.format_exc() 104 | 105 | if return_sender: return [m, sender] 106 | else: return m 107 | --------------------------------------------------------------------------------