1 /* ------------------------------------------------------------------------- */
2 /* "verbs" : Manages actions and grammar tables; parses the directives */
5 /* Part of Inform 6.40 */
6 /* copyright (c) Graham Nelson 1993 - 2022 */
8 /* Inform is free software: you can redistribute it and/or modify */
9 /* it under the terms of the GNU General Public License as published by */
10 /* the Free Software Foundation, either version 3 of the License, or */
11 /* (at your option) any later version. */
13 /* Inform is distributed in the hope that it will be useful, */
14 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
15 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
16 /* GNU General Public License for more details. */
18 /* You should have received a copy of the GNU General Public License */
19 /* along with Inform. If not, see https://gnu.org/licenses/ */
21 /* ------------------------------------------------------------------------- */
25 int grammar_version_number; /* 1 for pre-Inform 6.06 table format */
26 int32 grammar_version_symbol; /* Index of "Grammar__Version"
27 within symbols table */
29 /* ------------------------------------------------------------------------- */
31 /* ------------------------------------------------------------------------- */
32 /* Array defined below: */
34 /* actioninfo actions[n] Symbol table index and byte offset */
35 /* of the ...Sub routine */
36 /* ------------------------------------------------------------------------- */
38 int no_actions, /* Number of actions made so far */
39 no_fake_actions; /* Number of fake actions made so far */
41 /* ------------------------------------------------------------------------- */
42 /* Adjectives. (The term "adjective" is traditional; they are mainly */
43 /* prepositions, such as "onto".) */
44 /* ------------------------------------------------------------------------- */
45 /* Arrays defined below: */
47 /* int32 adjectives[n] Byte address of dictionary entry */
48 /* for the nth adjective */
49 /* dict_word adjective_sort_code[n] Dictionary sort code of nth adj */
50 /* ------------------------------------------------------------------------- */
52 int no_adjectives; /* Number of adjectives made so far */
54 /* ------------------------------------------------------------------------- */
55 /* Verbs. Note that Inform-verbs are not quite the same as English verbs: */
56 /* for example the English verbs "take" and "drop" both normally */
57 /* correspond in a game's dictionary to the same Inform verb. An */
58 /* Inform verb is essentially a list of grammar lines. */
59 /* (Calling them "English verbs" is of course out of date. Read */
60 /* this as jargon for "dict words which are verbs". */
61 /* ------------------------------------------------------------------------- */
62 /* Arrays defined below: */
64 /* verbt Inform_verbs[n] The n-th grammar line sequence: */
65 /* see "header.h" for the definition */
66 /* of the typedef struct verbt */
67 /* int32 grammar_token_routine[n] The byte offset from start of code */
68 /* area of the n-th one */
69 /* ------------------------------------------------------------------------- */
71 int no_Inform_verbs, /* Number of Inform-verbs made so far */
72 no_grammar_token_routines; /* Number of routines given in tokens */
74 /* ------------------------------------------------------------------------- */
75 /* We keep a list of English verb-words known (e.g. "take" or "eat") and */
76 /* which Inform-verbs they correspond to. (This list is needed for some */
77 /* of the grammar extension operations.) */
78 /* The format of this list is a sequence of variable-length records: */
80 /* Byte offset to start of next record (1 byte) */
81 /* Inform verb number this word corresponds to (2 bytes) */
82 /* The English verb-word (reduced to lower case), null-terminated */
83 /* ------------------------------------------------------------------------- */
85 static char *English_verb_list; /* Allocated to English_verb_list_size */
86 static memory_list English_verb_list_memlist;
88 static int English_verb_list_size; /* Size of the list in bytes */
90 static char *English_verbs_given; /* Allocated to verbs_given_pos
91 (Used only within make_verb()) */
92 static memory_list English_verbs_given_memlist;
94 /* ------------------------------------------------------------------------- */
95 /* Arrays used by this file */
96 /* ------------------------------------------------------------------------- */
98 verbt *Inform_verbs; /* Allocated up to no_Inform_verbs */
99 static memory_list Inform_verbs_memlist;
100 uchar *grammar_lines; /* Allocated to grammar_lines_top */
101 static memory_list grammar_lines_memlist;
102 int32 grammar_lines_top;
103 int no_grammar_lines, no_grammar_tokens;
105 actioninfo *actions; /* Allocated to no_actions */
106 memory_list actions_memlist;
107 int32 *grammar_token_routine; /* Allocated to no_grammar_token_routines */
108 static memory_list grammar_token_routine_memlist;
110 int32 *adjectives; /* Allocated to no_adjectives */
111 static memory_list adjectives_memlist;
113 static uchar *adjective_sort_code; /* Allocated to no_adjectives*DICT_WORD_BYTES */
114 static memory_list adjective_sort_code_memlist;
116 /* ------------------------------------------------------------------------- */
117 /* Tracing for compiler maintenance */
118 /* ------------------------------------------------------------------------- */
120 static char *find_verb_by_number(int num);
122 static void list_grammar_line_v1(int mark)
128 /* There is no GV1 for Glulx. */
132 action = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]);
136 while (grammar_lines[mark] != 15) {
137 uchar tok = grammar_lines[mark];
151 printf(" multiheld");
154 printf(" multiexcept");
157 printf(" multiinside");
169 if (tok >= 16 && tok < 48) {
170 printf(" noun=%d", tok-16);
172 else if (tok >= 48 && tok < 80) {
173 printf(" routine=%d", tok-48);
175 else if (tok >= 80 && tok < 128) {
176 printf(" scope=%d", tok-80);
178 else if (tok >= 128 && tok < 160) {
179 printf(" attr=%d", tok-128);
181 else if (tok >= 160) {
182 printf(" prep=%d", tok);
191 actsym = actions[action].symbol;
192 str = (symbols[actsym].name);
193 len = strlen(str) - 3; /* remove "__A" */
194 for (ix=0; ix<len; ix++) putchar(str[ix]);
198 static void list_grammar_line_v2(int mark)
200 int action, flags, actsym;
205 action = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]);
206 flags = (action & 0x400);
211 action = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]);
213 flags = grammar_lines[mark++];
217 while (grammar_lines[mark] != 15) {
218 int toktype, tokdat, tokalt;
220 toktype = grammar_lines[mark] & 0x0F;
221 tokalt = (grammar_lines[mark] >> 4) & 0x03;
223 tokdat = (grammar_lines[mark] << 8) | (grammar_lines[mark+1]);
227 toktype = grammar_lines[mark] & 0x0F;
228 tokalt = (grammar_lines[mark] >> 4) & 0x03;
230 tokdat = (grammar_lines[mark] << 24) | (grammar_lines[mark+1] << 16) | (grammar_lines[mark+2] << 8) | (grammar_lines[mark+3]);
234 if (tokalt == 3 || tokalt == 1)
240 case 0: printf(" noun"); break;
241 case 1: printf(" held"); break;
242 case 2: printf(" multi"); break;
243 case 3: printf(" multiheld"); break;
244 case 4: printf(" multiexcept"); break;
245 case 5: printf(" multiinside"); break;
246 case 6: printf(" creature"); break;
247 case 7: printf(" special"); break;
248 case 8: printf(" number"); break;
249 case 9: printf(" topic"); break;
250 default: printf(" ???"); break;
255 print_dict_word(tokdat);
259 printf(" noun=%d", tokdat);
262 printf(" attr=%d", tokdat);
265 printf(" scope=%d", tokdat);
268 printf(" routine=%d", tokdat);
271 printf(" ???%d:%d", toktype, tokdat);
276 actsym = actions[action].symbol;
277 str = (symbols[actsym].name);
278 len = strlen(str) - 3; /* remove "__A" */
279 for (ix=0; ix<len; ix++) putchar(str[ix]);
280 if (flags) printf(" (reversed)");
284 extern void list_verb_table(void)
287 printf("Grammar table: %d verbs\n", no_Inform_verbs);
288 for (verb=0; verb<no_Inform_verbs; verb++) {
289 char *verbword = find_verb_by_number(verb);
290 printf("Verb '%s'\n", verbword);
291 for (lx=0; lx<Inform_verbs[verb].lines; lx++) {
292 int mark = Inform_verbs[verb].l[lx];
293 switch (grammar_version_number) {
295 list_grammar_line_v1(mark);
298 list_grammar_line_v2(mark);
305 /* ------------------------------------------------------------------------- */
307 /* ------------------------------------------------------------------------- */
309 static void new_action(char *b, int c)
311 /* Called whenever a new action (or fake action) is created (either
312 by using make_action above, or the Fake_Action directive, or by
313 the linker). At present just a hook for some tracing code. */
315 if (printactions_switch)
316 printf("Action '%s' is numbered %d\n",b,c);
319 /* Note that fake actions are numbered from a high base point upwards;
320 real actions are numbered from 0 upward in GV2. */
322 extern void make_fake_action(void)
324 char action_sub[MAX_IDENTIFIER_LENGTH+4];
325 debug_location_beginning beginning_debug_location =
326 get_token_location_beginning();
329 if (token_type != SYMBOL_TT)
330 { discard_token_location(beginning_debug_location);
331 ebf_error("new fake action name", token_text);
332 panic_mode_error_recovery(); return;
334 /* Action symbols (including fake_actions) may collide with other kinds of symbols. So we don't check that. */
336 snprintf(action_sub, MAX_IDENTIFIER_LENGTH+4, "%s__A", token_text);
337 i = symbol_index(action_sub, -1);
339 if (!(symbols[i].flags & UNKNOWN_SFLAG))
340 { discard_token_location(beginning_debug_location);
341 /* The user didn't know they were defining FOO__A, but they were and it's a problem. */
342 ebf_symbol_error("new fake action name", action_sub, typename(symbols[i].type), symbols[i].line);
343 panic_mode_error_recovery(); return;
346 assign_symbol(i, ((grammar_version_number==1)?256:4096)+no_fake_actions++,
349 new_action(token_text, i);
351 if (debugfile_switch)
352 { debug_file_printf("<fake-action>");
353 debug_file_printf("<identifier>##%s</identifier>", token_text);
354 debug_file_printf("<value>%d</value>", symbols[i].value);
356 write_debug_locations
357 (get_token_location_end(beginning_debug_location));
359 debug_file_printf("</fake-action>");
365 extern assembly_operand action_of_name(char *name)
367 /* Returns the action number of the given name, creating it as a new
368 action name if it isn't already known as such. */
370 char action_sub[MAX_IDENTIFIER_LENGTH+4];
374 snprintf(action_sub, MAX_IDENTIFIER_LENGTH+4, "%s__A", name);
375 j = symbol_index(action_sub, -1);
377 if (symbols[j].type == FAKE_ACTION_T)
379 AO.value = symbols[j].value;
381 AO.type = LONG_CONSTANT_OT;
383 set_constant_ot(&AO);
384 symbols[j].flags |= USED_SFLAG;
388 if (symbols[j].flags & UNKNOWN_SFLAG)
390 ensure_memory_list_available(&actions_memlist, no_actions+1);
391 new_action(name, no_actions);
392 actions[no_actions].symbol = j;
393 actions[no_actions].byte_offset = 0; /* fill in later */
394 assign_symbol(j, no_actions++, CONSTANT_T);
395 symbols[j].flags |= ACTION_SFLAG;
397 symbols[j].flags |= USED_SFLAG;
400 AO.value = symbols[j].value;
401 AO.marker = ACTION_MV;
403 AO.type = (module_switch)?LONG_CONSTANT_OT:SHORT_CONSTANT_OT;
404 if (symbols[j].value >= 256) AO.type = LONG_CONSTANT_OT;
407 AO.type = CONSTANT_OT;
412 extern void find_the_actions(void)
414 char action_name[MAX_IDENTIFIER_LENGTH+4];
415 char action_sub[MAX_IDENTIFIER_LENGTH+4];
418 for (i=0; i<no_actions; i++) actions[i].byte_offset = 0;
420 for (i=0; i<no_actions; i++)
421 { strcpy(action_name, symbols[actions[i].symbol].name);
422 action_name[strlen(action_name) - 3] = '\0'; /* remove "__A" */
423 strcpy(action_sub, action_name);
424 strcat(action_sub, "Sub");
425 j = symbol_index(action_sub, -1);
426 if (symbols[j].flags & UNKNOWN_SFLAG)
428 error_named_at("No ...Sub action routine found for action:", action_name, symbols[actions[i].symbol].line);
431 if (symbols[j].type != ROUTINE_T)
433 error_named_at("No ...Sub action routine found for action:", action_name, symbols[actions[i].symbol].line);
434 error_named_at("-- ...Sub symbol found, but not a routine:", action_sub, symbols[j].line);
437 { actions[i].byte_offset = symbols[j].value;
438 symbols[j].flags |= USED_SFLAG;
443 /* ------------------------------------------------------------------------- */
445 /* ------------------------------------------------------------------------- */
447 static int make_adjective(char *English_word)
449 /* Returns adjective number of the English word supplied, creating
450 a new adjective number if need be.
452 Note that (partly for historical reasons) adjectives are numbered
453 from 0xff downwards. (And partly to make them stand out as tokens.)
455 This routine is used only in grammar version 1: the corresponding
456 table is left empty in GV2. */
459 uchar new_sort_code[MAX_DICT_WORD_BYTES];
461 if (no_adjectives >= 255) {
462 error("Grammar version 1 cannot support more than 255 prepositions");
465 if (ZCODE_LESS_DICT_DATA && !glulx_mode) {
466 /* We need to use #dict_par3 for the preposition number. */
467 error("Grammar version 1 cannot be used with ZCODE_LESS_DICT_DATA");
470 ensure_memory_list_available(&adjectives_memlist, no_adjectives+1);
471 ensure_memory_list_available(&adjective_sort_code_memlist, (no_adjectives+1) * DICT_WORD_BYTES);
473 dictionary_prepare(English_word, new_sort_code);
474 for (i=0; i<no_adjectives; i++)
475 if (compare_sorts(new_sort_code,
476 adjective_sort_code+i*DICT_WORD_BYTES) == 0)
478 adjectives[no_adjectives]
479 = dictionary_add(English_word,8,0,0xff-no_adjectives);
480 copy_sorts(adjective_sort_code+no_adjectives*DICT_WORD_BYTES,
482 return(0xff-no_adjectives++);
485 /* ------------------------------------------------------------------------- */
486 /* Parsing routines. */
487 /* ------------------------------------------------------------------------- */
489 static int make_parsing_routine(int32 routine_address)
491 /* This routine is used only in grammar version 1: the corresponding
492 table is left empty in GV2. */
495 for (l=0; l<no_grammar_token_routines; l++)
496 if (grammar_token_routine[l] == routine_address)
499 ensure_memory_list_available(&grammar_token_routine_memlist, no_grammar_token_routines+1);
501 grammar_token_routine[no_grammar_token_routines] = routine_address;
502 return(no_grammar_token_routines++);
505 /* ------------------------------------------------------------------------- */
506 /* The English-verb list. */
507 /* ------------------------------------------------------------------------- */
509 static int find_or_renumber_verb(char *English_verb, int *new_number)
511 /* If new_number is null, returns the Inform-verb number which the
512 * given English verb causes, or -1 if the given verb is not in the
515 /* If new_number is non-null, renumbers the Inform-verb number which
516 * English_verb matches in English_verb_list to account for the case
517 * when we are extending a verb. Returns 0 if successful, or -1 if
518 * the given verb is not in the dictionary (which shouldn't happen as
519 * get_verb has already run) */
523 while (p < English_verb_list+English_verb_list_size)
524 { if (strcmp(English_verb, p+3) == 0)
526 { p[1] = (*new_number)/256;
527 p[2] = (*new_number)%256;
530 return(256*((uchar)p[1]))+((uchar)p[2]);
537 static char *find_verb_by_number(int num)
539 /* Find the English verb string with the given verb number. */
542 while (p < English_verb_list+English_verb_list_size)
544 int val = (p[1] << 8) | p[2];
553 static void register_verb(char *English_verb, int number)
555 /* Registers a new English verb as referring to the given Inform-verb
556 number. (See comments above for format of the list.) */
560 if (find_or_renumber_verb(English_verb, NULL) != -1)
561 { error_named("Two different verb definitions refer to", English_verb);
565 /* We set a hard limit of MAX_VERB_WORD_SIZE=120 because the
566 English_verb_list table stores length in a leading byte. (We could
567 raise that to 250, really, but there's little point when
568 MAX_DICT_WORD_SIZE is 40.) */
569 entrysize = strlen(English_verb)+4;
570 if (entrysize > MAX_VERB_WORD_SIZE+4)
571 error_numbered("Verb word is too long -- max length is", MAX_VERB_WORD_SIZE);
572 ensure_memory_list_available(&English_verb_list_memlist, English_verb_list_size + entrysize);
573 top = English_verb_list + English_verb_list_size;
574 English_verb_list_size += entrysize;
579 strcpy(top+3, English_verb);
582 static int get_verb(void)
584 /* Look at the last-read token: if it's the name of an English verb
585 understood by Inform, in double-quotes, then return the Inform-verb
586 that word refers to: otherwise give an error and return -1. */
590 if ((token_type == DQ_TT) || (token_type == SQ_TT))
591 { j = find_or_renumber_verb(token_text, NULL);
593 error_named("There is no previous grammar for the verb",
598 ebf_error("an English verb in quotes", token_text);
603 /* ------------------------------------------------------------------------- */
604 /* Grammar lines for Verb/Extend directives. */
605 /* ------------------------------------------------------------------------- */
607 static void ensure_grammar_lines_available(int verbnum, int num)
609 /* Note that the size field always starts positive. */
610 if (num > Inform_verbs[verbnum].size) {
611 int newsize = 2*num+4;
612 my_realloc(&Inform_verbs[verbnum].l, sizeof(int) * Inform_verbs[verbnum].size, sizeof(int) * newsize, "grammar lines for one verb");
613 Inform_verbs[verbnum].size = newsize;
617 static int grammar_line(int verbnum, int line)
619 /* Parse a grammar line, to be written into grammar_lines[] starting
620 at grammar_lines_top. grammar_lines_top is left at the end
623 This stores the line position in Inform_verbs[verbnum].l[line].
624 (It does not increment Inform_verbs[verbnum].lines; the caller
627 Syntax: * <token1> ... <token-n> -> <action>
629 is compiled to a table in the form:
631 <action number : word>
632 <token 1> ... <token n> <ENDIT>
634 where <ENDIT> is the byte 15, and each <token> is 3 bytes long.
636 If grammar_version_number is 1, the token holds
640 and otherwise a GV2 token.
642 Return TRUE if grammar continues after the line, FALSE if the
643 directive comes to an end. */
645 int j, bytecode, mark; int32 wordcode;
646 int grammar_token, slash_mode, last_was_slash;
647 int reverse_action, TOKEN_SIZE;
648 debug_location_beginning beginning_debug_location =
649 get_token_location_beginning();
652 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
653 { discard_token_location(beginning_debug_location);
656 if (!((token_type == SEP_TT) && (token_value == TIMES_SEP)))
657 { discard_token_location(beginning_debug_location);
658 ebf_error("'*' divider", token_text);
659 panic_mode_error_recovery();
663 mark = grammar_lines_top;
665 ensure_grammar_lines_available(verbnum, line+1);
666 Inform_verbs[verbnum].l[line] = mark;
676 ensure_memory_list_available(&grammar_lines_memlist, mark);
678 grammar_token = 0; last_was_slash = TRUE; slash_mode = FALSE;
683 bytecode = 0; wordcode = 0;
684 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
685 { discard_token_location(beginning_debug_location);
686 ebf_error("'->' clause", token_text);
689 if ((token_type == SEP_TT) && (token_value == ARROW_SEP))
690 { if (last_was_slash && (grammar_token>0))
691 ebf_error("grammar token", token_text);
695 if (!last_was_slash) slash_mode = FALSE;
696 if ((token_type == SEP_TT) && (token_value == DIVIDE_SEP))
697 { if (grammar_version_number == 1)
698 error("'/' can only be used with Library 6/3 or later");
700 ebf_error("grammar token or '->'", token_text);
702 { last_was_slash = TRUE;
704 if (((grammar_lines[mark-TOKEN_SIZE]) & 0x0f) != 2)
705 error("'/' can only be applied to prepositions");
706 grammar_lines[mark-TOKEN_SIZE] |= 0x20;
710 else last_was_slash = FALSE;
712 if ((token_type == DQ_TT) || (token_type == SQ_TT))
713 { if (grammar_version_number == 1)
714 bytecode = make_adjective(token_text);
717 wordcode = dictionary_add(token_text, 8, 0, 0);
720 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==NOUN_DK))
722 if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
724 /* noun = <routine> */
727 if ((token_type != SYMBOL_TT)
728 || (symbols[token_value].type != ROUTINE_T))
729 { discard_token_location(beginning_debug_location);
730 ebf_error("routine name after 'noun='", token_text);
731 panic_mode_error_recovery();
734 if (grammar_version_number == 1)
736 = 16 + make_parsing_routine(symbols[token_value].value);
739 wordcode = symbols[token_value].value;
741 symbols[token_value].flags |= USED_SFLAG;
745 if (grammar_version_number == 1) bytecode=0;
746 else { bytecode = 1; wordcode = 0; }
749 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==HELD_DK))
750 { if (grammar_version_number==1) bytecode=1;
751 else { bytecode=1; wordcode=1; } }
752 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTI_DK))
753 { if (grammar_version_number==1) bytecode=2;
754 else { bytecode=1; wordcode=2; } }
755 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIHELD_DK))
756 { if (grammar_version_number==1) bytecode=3;
757 else { bytecode=1; wordcode=3; } }
758 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIEXCEPT_DK))
759 { if (grammar_version_number==1) bytecode=4;
760 else { bytecode=1; wordcode=4; } }
761 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIINSIDE_DK))
762 { if (grammar_version_number==1) bytecode=5;
763 else { bytecode=1; wordcode=5; } }
764 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==CREATURE_DK))
765 { if (grammar_version_number==1) bytecode=6;
766 else { bytecode=1; wordcode=6; } }
767 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==SPECIAL_DK))
768 { if (grammar_version_number==1) bytecode=7;
769 else { bytecode=1; wordcode=7; } }
770 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==NUMBER_DK))
771 { if (grammar_version_number==1) bytecode=8;
772 else { bytecode=1; wordcode=8; } }
773 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TOPIC_DK))
774 { if (grammar_version_number==1)
775 error("The 'topic' token is only available if you \
776 are using Library 6/3 or later");
777 else { bytecode=1; wordcode=9; } }
778 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==SCOPE_DK))
780 /* scope = <routine> */
783 if (!((token_type==SEP_TT)&&(token_value==SETEQUALS_SEP)))
784 { discard_token_location(beginning_debug_location);
785 ebf_error("'=' after 'scope'", token_text);
786 panic_mode_error_recovery();
791 if ((token_type != SYMBOL_TT)
792 || (symbols[token_value].type != ROUTINE_T))
793 { discard_token_location(beginning_debug_location);
794 ebf_error("routine name after 'scope='", token_text);
795 panic_mode_error_recovery();
799 if (grammar_version_number == 1)
801 make_parsing_routine(symbols[token_value].value);
802 else { bytecode = 0x85; wordcode = symbols[token_value].value; }
803 symbols[token_value].flags |= USED_SFLAG;
805 else if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
806 { discard_token_location(beginning_debug_location);
807 error("'=' is only legal here as 'noun=Routine'");
808 panic_mode_error_recovery();
811 else { /* <attribute> or <general-parsing-routine> tokens */
813 if ((token_type != SYMBOL_TT)
814 || ((symbols[token_value].type != ATTRIBUTE_T)
815 && (symbols[token_value].type != ROUTINE_T)))
816 { discard_token_location(beginning_debug_location);
817 error_named("No such grammar token as", token_text);
818 panic_mode_error_recovery();
821 if (symbols[token_value].type==ATTRIBUTE_T)
822 { if (grammar_version_number == 1)
823 bytecode = 128 + symbols[token_value].value;
824 else { bytecode = 4; wordcode = symbols[token_value].value; }
827 { if (grammar_version_number == 1)
829 make_parsing_routine(symbols[token_value].value);
830 else { bytecode = 0x86; wordcode = symbols[token_value].value; }
832 symbols[token_value].flags |= USED_SFLAG;
835 grammar_token++; no_grammar_tokens++;
836 if ((grammar_version_number == 1) && (grammar_token > 6))
837 { if (grammar_token == 7)
838 warning("Grammar line cut short: you can only have up to 6 \
839 tokens in any line (unless you're compiling with library 6/3 or later)");
843 { if (bytecode != 0x42)
844 error("'/' can only be applied to prepositions");
847 ensure_memory_list_available(&grammar_lines_memlist, mark+5);
848 grammar_lines[mark++] = bytecode;
850 grammar_lines[mark++] = wordcode/256;
851 grammar_lines[mark++] = wordcode%256;
854 grammar_lines[mark++] = ((wordcode >> 24) & 0xFF);
855 grammar_lines[mark++] = ((wordcode >> 16) & 0xFF);
856 grammar_lines[mark++] = ((wordcode >> 8) & 0xFF);
857 grammar_lines[mark++] = ((wordcode) & 0xFF);
863 ensure_memory_list_available(&grammar_lines_memlist, mark+1);
864 grammar_lines[mark++] = 15;
865 grammar_lines_top = mark;
867 dont_enter_into_symbol_table = TRUE;
869 dont_enter_into_symbol_table = FALSE;
871 if (token_type != DQ_TT)
872 { discard_token_location(beginning_debug_location);
873 ebf_error("name of new or existing action", token_text);
874 panic_mode_error_recovery();
878 { assembly_operand AO = action_of_name(token_text);
880 if (j >= ((grammar_version_number==1)?256:4096))
881 error_named("This is a fake action, not a real one:", token_text);
884 reverse_action = FALSE;
886 if ((token_type == DIR_KEYWORD_TT) && (token_value == REVERSE_DK))
887 { if (grammar_version_number == 1)
888 error("'reverse' actions can only be used with \
889 Library 6/3 or later");
890 reverse_action = TRUE;
892 else put_token_back();
894 mark = Inform_verbs[verbnum].l[line];
896 if (debugfile_switch)
897 { debug_file_printf("<table-entry>");
898 debug_file_printf("<type>grammar line</type>");
899 debug_file_printf("<address>");
900 write_debug_grammar_backpatch(mark);
901 debug_file_printf("</address>");
902 debug_file_printf("<end-address>");
903 write_debug_grammar_backpatch(grammar_lines_top);
904 debug_file_printf("</end-address>");
905 write_debug_locations
906 (get_token_location_end(beginning_debug_location));
907 debug_file_printf("</table-entry>");
910 ensure_memory_list_available(&grammar_lines_memlist, mark+3);
914 grammar_lines[mark++] = j/256;
915 grammar_lines[mark++] = j%256;
918 grammar_lines[mark++] = ((j >> 8) & 0xFF);
919 grammar_lines[mark++] = ((j) & 0xFF);
920 grammar_lines[mark++] = (reverse_action ? 1 : 0);
926 /* ------------------------------------------------------------------------- */
927 /* The Verb directive: */
929 /* Verb [meta] "word-1" ... "word-n" | = "existing-English-verb" */
930 /* | <grammar-line-1> ... <g-line-n> */
932 /* ------------------------------------------------------------------------- */
934 extern void make_verb(void)
936 /* Parse an entire Verb ... directive. */
938 int Inform_verb, meta_verb_flag=FALSE, verb_equals_form=FALSE;
940 int no_given = 0, verbs_given_pos = 0;
943 directive_keywords.enabled = TRUE;
947 if ((token_type == DIR_KEYWORD_TT) && (token_value == META_DK))
948 { meta_verb_flag = TRUE;
952 while ((token_type == DQ_TT) || (token_type == SQ_TT))
954 int len = strlen(token_text) + 1;
955 ensure_memory_list_available(&English_verbs_given_memlist, verbs_given_pos + len);
956 strcpy(English_verbs_given+verbs_given_pos, token_text);
957 verbs_given_pos += len;
963 { ebf_error("English verb in quotes", token_text);
964 panic_mode_error_recovery(); return;
967 if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
968 { verb_equals_form = TRUE;
970 Inform_verb = get_verb();
971 if (Inform_verb == -1) return;
973 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
974 ebf_error("';' after English verb", token_text);
977 { verb_equals_form = FALSE;
978 if (!glulx_mode && no_Inform_verbs >= 255) {
979 error("Z-code is limited to 255 verbs.");
980 panic_mode_error_recovery(); return;
982 ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1);
983 Inform_verb = no_Inform_verbs;
984 Inform_verbs[no_Inform_verbs].lines = 0;
985 Inform_verbs[no_Inform_verbs].size = 4;
986 Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb");
989 for (i=0, pos=0; i<no_given; i++) {
990 char *wd = English_verbs_given+pos;
992 0x41 + ((meta_verb_flag)?0x02:0x00),
993 (glulx_mode)?(0xffff-Inform_verb):(0xff-Inform_verb), 0);
994 register_verb(wd, Inform_verb);
995 pos += (strlen(wd) + 1);
998 if (!verb_equals_form)
1001 while (grammar_line(no_Inform_verbs, lines++)) ;
1002 Inform_verbs[no_Inform_verbs++].lines = --lines;
1005 directive_keywords.enabled = FALSE;
1008 /* ------------------------------------------------------------------------- */
1009 /* The Extend directive: */
1011 /* Extend | only "verb-1" ... "verb-n" | <grammar-lines> */
1012 /* | "verb" | "replace" */
1016 /* ------------------------------------------------------------------------- */
1018 #define EXTEND_REPLACE 1
1019 #define EXTEND_FIRST 2
1020 #define EXTEND_LAST 3
1022 extern void extend_verb(void)
1024 /* Parse an entire Extend ... directive. */
1026 int Inform_verb = -1, k, l, lines, extend_mode;
1028 directive_keywords.enabled = TRUE;
1029 directives.enabled = FALSE;
1032 if ((token_type == DIR_KEYWORD_TT) && (token_value == ONLY_DK))
1034 if (!glulx_mode && no_Inform_verbs >= 255) {
1035 error("Z-code is limited to 255 verbs.");
1036 panic_mode_error_recovery(); return;
1038 ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1);
1040 while (get_next_token(),
1041 ((token_type == DQ_TT) || (token_type == SQ_TT)))
1042 { Inform_verb = get_verb();
1043 if (Inform_verb == -1) return;
1044 if ((l!=-1) && (Inform_verb!=l))
1045 warning_named("Verb disagrees with previous verbs:", token_text);
1047 dictionary_set_verb_number(token_text,
1048 (glulx_mode)?(0xffff-no_Inform_verbs):(0xff-no_Inform_verbs));
1049 /* make call to renumber verb in English_verb_list too */
1050 if (find_or_renumber_verb(token_text, &no_Inform_verbs) == -1)
1051 warning_named("Verb to extend not found in English_verb_list:",
1055 /* Copy the old Inform-verb into a new one which the list of
1056 English-verbs given have had their dictionary entries modified
1058 /* (We are copying entry Inform_verb to no_Inform_verbs here.) */
1060 l = Inform_verbs[Inform_verb].lines; /* number of lines to copy */
1062 Inform_verbs[no_Inform_verbs].lines = l;
1063 Inform_verbs[no_Inform_verbs].size = l+4;
1064 Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb");
1066 Inform_verbs[no_Inform_verbs].l[k] = Inform_verbs[Inform_verb].l[k];
1067 Inform_verb = no_Inform_verbs++;
1070 { Inform_verb = get_verb();
1071 if (Inform_verb == -1) return;
1075 /* Inform_verb now contains the number of the Inform-verb to extend... */
1077 extend_mode = EXTEND_LAST;
1078 if ((token_type == SEP_TT) && (token_value == TIMES_SEP))
1082 if ((token_type == DIR_KEYWORD_TT) && (token_value == REPLACE_DK))
1083 extend_mode = EXTEND_REPLACE;
1084 if ((token_type == DIR_KEYWORD_TT) && (token_value == FIRST_DK))
1085 extend_mode = EXTEND_FIRST;
1086 if ((token_type == DIR_KEYWORD_TT) && (token_value == LAST_DK))
1087 extend_mode = EXTEND_LAST;
1090 { ebf_error("'replace', 'last', 'first' or '*'", token_text);
1091 extend_mode = EXTEND_LAST;
1095 l = Inform_verbs[Inform_verb].lines;
1097 if (extend_mode == EXTEND_LAST) lines=l;
1100 if (extend_mode == EXTEND_FIRST) {
1101 ensure_grammar_lines_available(Inform_verb, l+lines+1);
1103 Inform_verbs[Inform_verb].l[k+lines]
1104 = Inform_verbs[Inform_verb].l[k-1+lines];
1106 } while (grammar_line(Inform_verb, lines++));
1108 if (extend_mode == EXTEND_FIRST)
1110 ensure_grammar_lines_available(Inform_verb, l+lines+1);
1111 Inform_verbs[Inform_verb].lines = l+lines-1;
1112 for (k=0; k<l; k++) {
1113 Inform_verbs[Inform_verb].l[k+lines-1]
1114 = Inform_verbs[Inform_verb].l[k+lines];
1117 else Inform_verbs[Inform_verb].lines = --lines;
1119 directive_keywords.enabled = FALSE;
1120 directives.enabled = TRUE;
1123 /* ========================================================================= */
1124 /* Data structure management routines */
1125 /* ------------------------------------------------------------------------- */
1127 extern void init_verbs_vars(void)
1129 no_fake_actions = 0;
1131 no_grammar_lines = 0;
1132 no_grammar_tokens = 0;
1133 English_verb_list_size = 0;
1135 Inform_verbs = NULL;
1137 grammar_lines = NULL;
1138 grammar_token_routine = NULL;
1140 adjective_sort_code = NULL;
1141 English_verb_list = NULL;
1142 English_verbs_given = NULL;
1145 grammar_version_number = 1;
1147 grammar_version_number = 2;
1150 extern void verbs_begin_pass(void)
1152 no_Inform_verbs=0; no_adjectives=0;
1153 no_grammar_token_routines=0;
1157 grammar_lines_top = 0;
1160 extern void verbs_allocate_arrays(void)
1162 initialise_memory_list(&Inform_verbs_memlist,
1163 sizeof(verbt), 128, (void**)&Inform_verbs,
1166 initialise_memory_list(&grammar_lines_memlist,
1167 sizeof(uchar), 4000, (void**)&grammar_lines,
1170 initialise_memory_list(&actions_memlist,
1171 sizeof(actioninfo), 128, (void**)&actions,
1174 initialise_memory_list(&grammar_token_routine_memlist,
1175 sizeof(int32), 50, (void**)&grammar_token_routine,
1176 "grammar token routines");
1178 initialise_memory_list(&adjectives_memlist,
1179 sizeof(int32), 50, (void**)&adjectives,
1181 initialise_memory_list(&adjective_sort_code_memlist,
1182 sizeof(uchar), 50*DICT_WORD_BYTES, (void**)&adjective_sort_code,
1183 "adjective sort codes");
1185 initialise_memory_list(&English_verb_list_memlist,
1186 sizeof(char), 2048, (void**)&English_verb_list,
1187 "register of verbs");
1189 initialise_memory_list(&English_verbs_given_memlist,
1190 sizeof(char), 80, (void**)&English_verbs_given,
1191 "verb words within a single definition");
1194 extern void verbs_free_arrays(void)
1197 for (ix=0; ix<no_Inform_verbs; ix++)
1199 my_free(&Inform_verbs[ix].l, "grammar lines for one verb");
1201 deallocate_memory_list(&Inform_verbs_memlist);
1202 deallocate_memory_list(&grammar_lines_memlist);
1203 deallocate_memory_list(&actions_memlist);
1204 deallocate_memory_list(&grammar_token_routine_memlist);
1205 deallocate_memory_list(&adjectives_memlist);
1206 deallocate_memory_list(&adjective_sort_code_memlist);
1207 deallocate_memory_list(&English_verb_list_memlist);
1208 deallocate_memory_list(&English_verbs_given_memlist);
1211 /* ========================================================================= */