1 /* ------------------------------------------------------------------------- */
2 /* "verbs" : Manages actions and grammar tables; parses the directives */
5 /* Part of Inform 6.41 */
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).
313 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 = 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];
417 for (i=0; i<no_actions; i++)
418 { strcpy(action_name, symbols[actions[i].symbol].name);
419 action_name[strlen(action_name) - 3] = '\0'; /* remove "__A" */
420 strcpy(action_sub, action_name);
421 strcat(action_sub, "Sub");
422 j = symbol_index(action_sub, -1);
423 if (symbols[j].flags & UNKNOWN_SFLAG)
425 error_named_at("No ...Sub action routine found for action:", action_name, symbols[actions[i].symbol].line);
428 if (symbols[j].type != ROUTINE_T)
430 error_named_at("No ...Sub action routine found for action:", action_name, symbols[actions[i].symbol].line);
431 error_named_at("-- ...Sub symbol found, but not a routine:", action_sub, symbols[j].line);
434 { actions[i].byte_offset = symbols[j].value;
435 symbols[j].flags |= USED_SFLAG;
440 /* ------------------------------------------------------------------------- */
442 /* ------------------------------------------------------------------------- */
444 static int make_adjective(char *English_word)
446 /* Returns adjective number of the English word supplied, creating
447 a new adjective number if need be.
449 Note that (partly for historical reasons) adjectives are numbered
450 from 0xff downwards. (And partly to make them stand out as tokens.)
452 This routine is used only in grammar version 1: the corresponding
453 table is left empty in GV2. */
456 uchar new_sort_code[MAX_DICT_WORD_BYTES];
458 if (no_adjectives >= 255) {
459 error("Grammar version 1 cannot support more than 255 prepositions");
462 if (ZCODE_LESS_DICT_DATA && !glulx_mode) {
463 /* We need to use #dict_par3 for the preposition number. */
464 error("Grammar version 1 cannot be used with ZCODE_LESS_DICT_DATA");
467 ensure_memory_list_available(&adjectives_memlist, no_adjectives+1);
468 ensure_memory_list_available(&adjective_sort_code_memlist, (no_adjectives+1) * DICT_WORD_BYTES);
470 dictionary_prepare(English_word, new_sort_code);
471 for (i=0; i<no_adjectives; i++)
472 if (compare_sorts(new_sort_code,
473 adjective_sort_code+i*DICT_WORD_BYTES) == 0)
475 adjectives[no_adjectives]
476 = dictionary_add(English_word,8,0,0xff-no_adjectives);
477 copy_sorts(adjective_sort_code+no_adjectives*DICT_WORD_BYTES,
479 return(0xff-no_adjectives++);
482 /* ------------------------------------------------------------------------- */
483 /* Parsing routines. */
484 /* ------------------------------------------------------------------------- */
486 static int make_parsing_routine(int32 routine_address)
488 /* This routine is used only in grammar version 1: the corresponding
489 table is left empty in GV2. */
492 for (l=0; l<no_grammar_token_routines; l++)
493 if (grammar_token_routine[l] == routine_address)
496 ensure_memory_list_available(&grammar_token_routine_memlist, no_grammar_token_routines+1);
498 grammar_token_routine[no_grammar_token_routines] = routine_address;
499 return(no_grammar_token_routines++);
502 /* ------------------------------------------------------------------------- */
503 /* The English-verb list. */
504 /* ------------------------------------------------------------------------- */
506 static int find_or_renumber_verb(char *English_verb, int *new_number)
508 /* If new_number is null, returns the Inform-verb number which the
509 * given English verb causes, or -1 if the given verb is not in the
512 /* If new_number is non-null, renumbers the Inform-verb number which
513 * English_verb matches in English_verb_list to account for the case
514 * when we are extending a verb. Returns 0 if successful, or -1 if
515 * the given verb is not in the dictionary (which shouldn't happen as
516 * get_verb has already run) */
520 while (p < English_verb_list+English_verb_list_size)
521 { if (strcmp(English_verb, p+3) == 0)
523 { p[1] = (*new_number)/256;
524 p[2] = (*new_number)%256;
527 return(256*((uchar)p[1]))+((uchar)p[2]);
534 static char *find_verb_by_number(int num)
536 /* Find the English verb string with the given verb number. */
539 while (p < English_verb_list+English_verb_list_size)
541 int val = (p[1] << 8) | p[2];
550 static void register_verb(char *English_verb, int number)
552 /* Registers a new English verb as referring to the given Inform-verb
553 number. (See comments above for format of the list.) */
557 if (find_or_renumber_verb(English_verb, NULL) != -1)
558 { error_named("Two different verb definitions refer to", English_verb);
562 /* We set a hard limit of MAX_VERB_WORD_SIZE=120 because the
563 English_verb_list table stores length in a leading byte. (We could
564 raise that to 250, really, but there's little point when
565 MAX_DICT_WORD_SIZE is 40.) */
566 entrysize = strlen(English_verb)+4;
567 if (entrysize > MAX_VERB_WORD_SIZE+4)
568 error_numbered("Verb word is too long -- max length is", MAX_VERB_WORD_SIZE);
569 ensure_memory_list_available(&English_verb_list_memlist, English_verb_list_size + entrysize);
570 top = English_verb_list + English_verb_list_size;
571 English_verb_list_size += entrysize;
576 strcpy(top+3, English_verb);
579 static int get_verb(void)
581 /* Look at the last-read token: if it's the name of an English verb
582 understood by Inform, in double-quotes, then return the Inform-verb
583 that word refers to: otherwise give an error and return -1. */
587 if ((token_type == DQ_TT) || (token_type == SQ_TT))
588 { j = find_or_renumber_verb(token_text, NULL);
590 error_named("There is no previous grammar for the verb",
595 ebf_error("an English verb in quotes", token_text);
600 /* ------------------------------------------------------------------------- */
601 /* Grammar lines for Verb/Extend directives. */
602 /* ------------------------------------------------------------------------- */
604 static void ensure_grammar_lines_available(int verbnum, int num)
606 /* Note that the size field always starts positive. */
607 if (num > Inform_verbs[verbnum].size) {
608 int newsize = 2*num+4;
609 my_realloc(&Inform_verbs[verbnum].l, sizeof(int) * Inform_verbs[verbnum].size, sizeof(int) * newsize, "grammar lines for one verb");
610 Inform_verbs[verbnum].size = newsize;
614 static int grammar_line(int verbnum, int line)
616 /* Parse a grammar line, to be written into grammar_lines[] starting
617 at grammar_lines_top. grammar_lines_top is left at the end
620 This stores the line position in Inform_verbs[verbnum].l[line].
621 (It does not increment Inform_verbs[verbnum].lines; the caller
624 Syntax: * <token1> ... <token-n> -> <action>
626 is compiled to a table in the form:
628 <action number : word>
629 <token 1> ... <token n> <ENDIT>
631 where <ENDIT> is the byte 15, and each <token> is 3 bytes long.
633 If grammar_version_number is 1, the token holds
637 and otherwise a GV2 token.
639 Return TRUE if grammar continues after the line, FALSE if the
640 directive comes to an end. */
642 int j, bytecode, mark; int32 wordcode;
643 int grammar_token, slash_mode, last_was_slash;
644 int reverse_action, TOKEN_SIZE;
645 debug_location_beginning beginning_debug_location =
646 get_token_location_beginning();
649 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
650 { discard_token_location(beginning_debug_location);
653 if (!((token_type == SEP_TT) && (token_value == TIMES_SEP)))
654 { discard_token_location(beginning_debug_location);
655 ebf_error("'*' divider", token_text);
656 panic_mode_error_recovery();
660 mark = grammar_lines_top;
662 ensure_grammar_lines_available(verbnum, line+1);
663 Inform_verbs[verbnum].l[line] = mark;
673 ensure_memory_list_available(&grammar_lines_memlist, mark);
675 grammar_token = 0; last_was_slash = TRUE; slash_mode = FALSE;
680 bytecode = 0; wordcode = 0;
681 if ((token_type == SEP_TT) && (token_value == SEMICOLON_SEP))
682 { discard_token_location(beginning_debug_location);
683 ebf_error("'->' clause", token_text);
686 if ((token_type == SEP_TT) && (token_value == ARROW_SEP))
687 { if (last_was_slash && (grammar_token>0))
688 ebf_error("grammar token", token_text);
692 if (!last_was_slash) slash_mode = FALSE;
693 if ((token_type == SEP_TT) && (token_value == DIVIDE_SEP))
694 { if (grammar_version_number == 1)
695 error("'/' can only be used with Library 6/3 or later");
697 ebf_error("grammar token or '->'", token_text);
699 { last_was_slash = TRUE;
701 if (((grammar_lines[mark-TOKEN_SIZE]) & 0x0f) != 2)
702 error("'/' can only be applied to prepositions");
703 grammar_lines[mark-TOKEN_SIZE] |= 0x20;
707 else last_was_slash = FALSE;
709 if ((token_type == DQ_TT) || (token_type == SQ_TT))
710 { if (grammar_version_number == 1)
711 bytecode = make_adjective(token_text);
714 wordcode = dictionary_add(token_text, 8, 0, 0);
717 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==NOUN_DK))
719 if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
721 /* noun = <routine> */
724 if ((token_type != SYMBOL_TT)
725 || (symbols[token_value].type != ROUTINE_T))
726 { discard_token_location(beginning_debug_location);
727 ebf_error("routine name after 'noun='", token_text);
728 panic_mode_error_recovery();
731 if (grammar_version_number == 1)
733 = 16 + make_parsing_routine(symbols[token_value].value);
736 wordcode = symbols[token_value].value;
738 symbols[token_value].flags |= USED_SFLAG;
742 if (grammar_version_number == 1) bytecode=0;
743 else { bytecode = 1; wordcode = 0; }
746 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==HELD_DK))
747 { if (grammar_version_number==1) bytecode=1;
748 else { bytecode=1; wordcode=1; } }
749 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTI_DK))
750 { if (grammar_version_number==1) bytecode=2;
751 else { bytecode=1; wordcode=2; } }
752 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIHELD_DK))
753 { if (grammar_version_number==1) bytecode=3;
754 else { bytecode=1; wordcode=3; } }
755 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIEXCEPT_DK))
756 { if (grammar_version_number==1) bytecode=4;
757 else { bytecode=1; wordcode=4; } }
758 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==MULTIINSIDE_DK))
759 { if (grammar_version_number==1) bytecode=5;
760 else { bytecode=1; wordcode=5; } }
761 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==CREATURE_DK))
762 { if (grammar_version_number==1) bytecode=6;
763 else { bytecode=1; wordcode=6; } }
764 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==SPECIAL_DK))
765 { if (grammar_version_number==1) bytecode=7;
766 else { bytecode=1; wordcode=7; } }
767 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==NUMBER_DK))
768 { if (grammar_version_number==1) bytecode=8;
769 else { bytecode=1; wordcode=8; } }
770 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==TOPIC_DK))
771 { if (grammar_version_number==1)
772 error("The 'topic' token is only available if you \
773 are using Library 6/3 or later");
774 else { bytecode=1; wordcode=9; } }
775 else if ((token_type==DIR_KEYWORD_TT)&&(token_value==SCOPE_DK))
777 /* scope = <routine> */
780 if (!((token_type==SEP_TT)&&(token_value==SETEQUALS_SEP)))
781 { discard_token_location(beginning_debug_location);
782 ebf_error("'=' after 'scope'", token_text);
783 panic_mode_error_recovery();
788 if ((token_type != SYMBOL_TT)
789 || (symbols[token_value].type != ROUTINE_T))
790 { discard_token_location(beginning_debug_location);
791 ebf_error("routine name after 'scope='", token_text);
792 panic_mode_error_recovery();
796 if (grammar_version_number == 1)
798 make_parsing_routine(symbols[token_value].value);
799 else { bytecode = 0x85; wordcode = symbols[token_value].value; }
800 symbols[token_value].flags |= USED_SFLAG;
802 else if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
803 { discard_token_location(beginning_debug_location);
804 error("'=' is only legal here as 'noun=Routine'");
805 panic_mode_error_recovery();
808 else { /* <attribute> or <general-parsing-routine> tokens */
810 if ((token_type != SYMBOL_TT)
811 || ((symbols[token_value].type != ATTRIBUTE_T)
812 && (symbols[token_value].type != ROUTINE_T)))
813 { discard_token_location(beginning_debug_location);
814 error_named("No such grammar token as", token_text);
815 panic_mode_error_recovery();
818 if (symbols[token_value].type==ATTRIBUTE_T)
819 { if (grammar_version_number == 1)
820 bytecode = 128 + symbols[token_value].value;
821 else { bytecode = 4; wordcode = symbols[token_value].value; }
824 { if (grammar_version_number == 1)
826 make_parsing_routine(symbols[token_value].value);
827 else { bytecode = 0x86; wordcode = symbols[token_value].value; }
829 symbols[token_value].flags |= USED_SFLAG;
832 grammar_token++; no_grammar_tokens++;
833 if ((grammar_version_number == 1) && (grammar_token > 6))
834 { if (grammar_token == 7)
835 warning("Grammar line cut short: you can only have up to 6 \
836 tokens in any line (unless you're compiling with library 6/3 or later)");
840 { if (bytecode != 0x42)
841 error("'/' can only be applied to prepositions");
844 ensure_memory_list_available(&grammar_lines_memlist, mark+5);
845 grammar_lines[mark++] = bytecode;
847 grammar_lines[mark++] = wordcode/256;
848 grammar_lines[mark++] = wordcode%256;
851 grammar_lines[mark++] = ((wordcode >> 24) & 0xFF);
852 grammar_lines[mark++] = ((wordcode >> 16) & 0xFF);
853 grammar_lines[mark++] = ((wordcode >> 8) & 0xFF);
854 grammar_lines[mark++] = ((wordcode) & 0xFF);
860 ensure_memory_list_available(&grammar_lines_memlist, mark+1);
861 grammar_lines[mark++] = 15;
862 grammar_lines_top = mark;
864 dont_enter_into_symbol_table = TRUE;
866 dont_enter_into_symbol_table = FALSE;
868 if (token_type != DQ_TT)
869 { discard_token_location(beginning_debug_location);
870 ebf_error("name of new or existing action", token_text);
871 panic_mode_error_recovery();
875 { assembly_operand AO = action_of_name(token_text);
877 if (j >= ((grammar_version_number==1)?256:4096))
878 error_named("This is a fake action, not a real one:", token_text);
881 reverse_action = FALSE;
883 if ((token_type == DIR_KEYWORD_TT) && (token_value == REVERSE_DK))
884 { if (grammar_version_number == 1)
885 error("'reverse' actions can only be used with \
886 Library 6/3 or later");
887 reverse_action = TRUE;
889 else put_token_back();
891 mark = Inform_verbs[verbnum].l[line];
893 if (debugfile_switch)
894 { debug_file_printf("<table-entry>");
895 debug_file_printf("<type>grammar line</type>");
896 debug_file_printf("<address>");
897 write_debug_grammar_backpatch(mark);
898 debug_file_printf("</address>");
899 debug_file_printf("<end-address>");
900 write_debug_grammar_backpatch(grammar_lines_top);
901 debug_file_printf("</end-address>");
902 write_debug_locations
903 (get_token_location_end(beginning_debug_location));
904 debug_file_printf("</table-entry>");
907 ensure_memory_list_available(&grammar_lines_memlist, mark+3);
911 grammar_lines[mark++] = j/256;
912 grammar_lines[mark++] = j%256;
915 grammar_lines[mark++] = ((j >> 8) & 0xFF);
916 grammar_lines[mark++] = ((j) & 0xFF);
917 grammar_lines[mark++] = (reverse_action ? 1 : 0);
923 /* ------------------------------------------------------------------------- */
924 /* The Verb directive: */
926 /* Verb [meta] "word-1" ... "word-n" | = "existing-English-verb" */
927 /* | <grammar-line-1> ... <g-line-n> */
929 /* ------------------------------------------------------------------------- */
931 extern void make_verb(void)
933 /* Parse an entire Verb ... directive. */
935 int Inform_verb, meta_verb_flag=FALSE, verb_equals_form=FALSE;
937 int no_given = 0, verbs_given_pos = 0;
940 directive_keywords.enabled = TRUE;
944 if ((token_type == DIR_KEYWORD_TT) && (token_value == META_DK))
945 { meta_verb_flag = TRUE;
949 while ((token_type == DQ_TT) || (token_type == SQ_TT))
951 int len = strlen(token_text) + 1;
952 ensure_memory_list_available(&English_verbs_given_memlist, verbs_given_pos + len);
953 strcpy(English_verbs_given+verbs_given_pos, token_text);
954 verbs_given_pos += len;
960 { ebf_error("English verb in quotes", token_text);
961 panic_mode_error_recovery(); return;
964 if ((token_type == SEP_TT) && (token_value == SETEQUALS_SEP))
965 { verb_equals_form = TRUE;
967 Inform_verb = get_verb();
968 if (Inform_verb == -1) return;
970 if (!((token_type == SEP_TT) && (token_value == SEMICOLON_SEP)))
971 ebf_error("';' after English verb", token_text);
974 { verb_equals_form = FALSE;
975 if (!glulx_mode && no_Inform_verbs >= 255) {
976 error("Z-code is limited to 255 verbs.");
977 panic_mode_error_recovery(); return;
979 ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1);
980 Inform_verb = no_Inform_verbs;
981 Inform_verbs[no_Inform_verbs].lines = 0;
982 Inform_verbs[no_Inform_verbs].size = 4;
983 Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb");
986 for (i=0, pos=0; i<no_given; i++) {
987 char *wd = English_verbs_given+pos;
989 0x41 + ((meta_verb_flag)?0x02:0x00),
990 (glulx_mode)?(0xffff-Inform_verb):(0xff-Inform_verb), 0);
991 register_verb(wd, Inform_verb);
992 pos += (strlen(wd) + 1);
995 if (!verb_equals_form)
998 while (grammar_line(no_Inform_verbs, lines++)) ;
999 Inform_verbs[no_Inform_verbs++].lines = --lines;
1002 directive_keywords.enabled = FALSE;
1005 /* ------------------------------------------------------------------------- */
1006 /* The Extend directive: */
1008 /* Extend | only "verb-1" ... "verb-n" | <grammar-lines> */
1009 /* | "verb" | "replace" */
1013 /* ------------------------------------------------------------------------- */
1015 #define EXTEND_REPLACE 1
1016 #define EXTEND_FIRST 2
1017 #define EXTEND_LAST 3
1019 extern void extend_verb(void)
1021 /* Parse an entire Extend ... directive. */
1023 int Inform_verb = -1, k, l, lines, extend_mode;
1025 directive_keywords.enabled = TRUE;
1026 directives.enabled = FALSE;
1029 if ((token_type == DIR_KEYWORD_TT) && (token_value == ONLY_DK))
1031 if (!glulx_mode && no_Inform_verbs >= 255) {
1032 error("Z-code is limited to 255 verbs.");
1033 panic_mode_error_recovery(); return;
1035 ensure_memory_list_available(&Inform_verbs_memlist, no_Inform_verbs+1);
1037 while (get_next_token(),
1038 ((token_type == DQ_TT) || (token_type == SQ_TT)))
1039 { Inform_verb = get_verb();
1040 if (Inform_verb == -1) return;
1041 if ((l!=-1) && (Inform_verb!=l))
1042 warning_named("Verb disagrees with previous verbs:", token_text);
1044 dictionary_set_verb_number(token_text,
1045 (glulx_mode)?(0xffff-no_Inform_verbs):(0xff-no_Inform_verbs));
1046 /* make call to renumber verb in English_verb_list too */
1047 if (find_or_renumber_verb(token_text, &no_Inform_verbs) == -1)
1048 warning_named("Verb to extend not found in English_verb_list:",
1052 /* Copy the old Inform-verb into a new one which the list of
1053 English-verbs given have had their dictionary entries modified
1055 /* (We are copying entry Inform_verb to no_Inform_verbs here.) */
1057 l = Inform_verbs[Inform_verb].lines; /* number of lines to copy */
1059 Inform_verbs[no_Inform_verbs].lines = l;
1060 Inform_verbs[no_Inform_verbs].size = l+4;
1061 Inform_verbs[no_Inform_verbs].l = my_malloc(sizeof(int) * Inform_verbs[no_Inform_verbs].size, "grammar lines for one verb");
1063 Inform_verbs[no_Inform_verbs].l[k] = Inform_verbs[Inform_verb].l[k];
1064 Inform_verb = no_Inform_verbs++;
1067 { Inform_verb = get_verb();
1068 if (Inform_verb == -1) return;
1072 /* Inform_verb now contains the number of the Inform-verb to extend... */
1074 extend_mode = EXTEND_LAST;
1075 if ((token_type == SEP_TT) && (token_value == TIMES_SEP))
1079 if ((token_type == DIR_KEYWORD_TT) && (token_value == REPLACE_DK))
1080 extend_mode = EXTEND_REPLACE;
1081 if ((token_type == DIR_KEYWORD_TT) && (token_value == FIRST_DK))
1082 extend_mode = EXTEND_FIRST;
1083 if ((token_type == DIR_KEYWORD_TT) && (token_value == LAST_DK))
1084 extend_mode = EXTEND_LAST;
1087 { ebf_error("'replace', 'last', 'first' or '*'", token_text);
1088 extend_mode = EXTEND_LAST;
1092 l = Inform_verbs[Inform_verb].lines;
1094 if (extend_mode == EXTEND_LAST) lines=l;
1097 if (extend_mode == EXTEND_FIRST) {
1098 ensure_grammar_lines_available(Inform_verb, l+lines+1);
1100 Inform_verbs[Inform_verb].l[k+lines]
1101 = Inform_verbs[Inform_verb].l[k-1+lines];
1103 } while (grammar_line(Inform_verb, lines++));
1105 if (extend_mode == EXTEND_FIRST)
1107 ensure_grammar_lines_available(Inform_verb, l+lines+1);
1108 Inform_verbs[Inform_verb].lines = l+lines-1;
1109 for (k=0; k<l; k++) {
1110 Inform_verbs[Inform_verb].l[k+lines-1]
1111 = Inform_verbs[Inform_verb].l[k+lines];
1114 else Inform_verbs[Inform_verb].lines = --lines;
1116 directive_keywords.enabled = FALSE;
1117 directives.enabled = TRUE;
1120 /* ========================================================================= */
1121 /* Data structure management routines */
1122 /* ------------------------------------------------------------------------- */
1124 extern void init_verbs_vars(void)
1126 no_fake_actions = 0;
1128 no_grammar_lines = 0;
1129 no_grammar_tokens = 0;
1130 English_verb_list_size = 0;
1132 Inform_verbs = NULL;
1134 grammar_lines = NULL;
1135 grammar_token_routine = NULL;
1137 adjective_sort_code = NULL;
1138 English_verb_list = NULL;
1139 English_verbs_given = NULL;
1142 grammar_version_number = 1;
1144 grammar_version_number = 2;
1147 extern void verbs_begin_pass(void)
1149 no_Inform_verbs=0; no_adjectives=0;
1150 no_grammar_token_routines=0;
1154 grammar_lines_top = 0;
1157 extern void verbs_allocate_arrays(void)
1159 initialise_memory_list(&Inform_verbs_memlist,
1160 sizeof(verbt), 128, (void**)&Inform_verbs,
1163 initialise_memory_list(&grammar_lines_memlist,
1164 sizeof(uchar), 4000, (void**)&grammar_lines,
1167 initialise_memory_list(&actions_memlist,
1168 sizeof(actioninfo), 128, (void**)&actions,
1171 initialise_memory_list(&grammar_token_routine_memlist,
1172 sizeof(int32), 50, (void**)&grammar_token_routine,
1173 "grammar token routines");
1175 initialise_memory_list(&adjectives_memlist,
1176 sizeof(int32), 50, (void**)&adjectives,
1178 initialise_memory_list(&adjective_sort_code_memlist,
1179 sizeof(uchar), 50*DICT_WORD_BYTES, (void**)&adjective_sort_code,
1180 "adjective sort codes");
1182 initialise_memory_list(&English_verb_list_memlist,
1183 sizeof(char), 2048, (void**)&English_verb_list,
1184 "register of verbs");
1186 initialise_memory_list(&English_verbs_given_memlist,
1187 sizeof(char), 80, (void**)&English_verbs_given,
1188 "verb words within a single definition");
1191 extern void verbs_free_arrays(void)
1194 for (ix=0; ix<no_Inform_verbs; ix++)
1196 my_free(&Inform_verbs[ix].l, "grammar lines for one verb");
1198 deallocate_memory_list(&Inform_verbs_memlist);
1199 deallocate_memory_list(&grammar_lines_memlist);
1200 deallocate_memory_list(&actions_memlist);
1201 deallocate_memory_list(&grammar_token_routine_memlist);
1202 deallocate_memory_list(&adjectives_memlist);
1203 deallocate_memory_list(&adjective_sort_code_memlist);
1204 deallocate_memory_list(&English_verb_list_memlist);
1205 deallocate_memory_list(&English_verbs_given_memlist);
1208 /* ========================================================================= */