diff --git a/README.md b/README.md index c4e5b75be..37a641af2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Inform 7 -v10.1.0-alpha.1+6R57 'Krypton' (21 March 2021) +v10.1.0-alpha.1+6R58 'Krypton' (22 March 2021) ## About Inform 7 diff --git a/build.txt b/build.txt index a81a9d393..ec65494c3 100644 --- a/build.txt +++ b/build.txt @@ -1,3 +1,3 @@ Prerelease: alpha.1 -Build Date: 21 March 2021 -Build Number: 6R57 +Build Date: 22 March 2021 +Build Number: 6R58 diff --git a/docs/imperative-module/1-im.html b/docs/imperative-module/1-im.html index 4f87e6fed..d13d98926 100644 --- a/docs/imperative-module/1-im.html +++ b/docs/imperative-module/1-im.html @@ -89,7 +89,7 @@ which use this module: COMPILE_WRITER(ph_type_data *, Phrases::TypeData::Textual::log) COMPILE_WRITER(local_variable *, LocalVariables::log) COMPILE_WRITER(phrase *, Phrases::log) -COMPILE_WRITER(ph_usage_data *, Phrases::Usage::log) +COMPILE_WRITER(ph_usage_data *, Phrases::Usage::log) void ImperativeModule::start(void) { Writers::register_writer('L', &LocalVariables::writer); @@ -98,7 +98,7 @@ which use this module: REGISTER_WRITER('h', Phrases::TypeData::Textual::log); REGISTER_WRITER('k', LocalVariables::log); REGISTER_WRITER('R', Phrases::log); - REGISTER_WRITER('U', Phrases::Usage::log); + REGISTER_WRITER('U', Phrases::Usage::log); Memory::reason_name(INV_LIST_MREASON, "lists for type-checking invocations"); Log::declare_aspect(DESCRIPTION_COMPILATION_DA, L"description compilation", FALSE, FALSE); Log::declare_aspect(EXPRESSIONS_DA, L"expressions", FALSE, FALSE); diff --git a/docs/imperative-module/2-rb.html b/docs/imperative-module/2-rb.html index 9b1326d91..25fe935c6 100644 --- a/docs/imperative-module/2-rb.html +++ b/docs/imperative-module/2-rb.html @@ -174,12 +174,12 @@ the rulebook; instead, the booking is marked for automatic placement later on. phrase *ph = Rules::get_defn_as_phrase(br->rule_being_booked); if (ph) { current_sentence = ph->declaration_node; - rulebook *original_owner = Phrases::Usage::get_rulebook(&(ph->usage_data)); - int placement = Phrases::Usage::get_rulebook_placement(&(ph->usage_data)); + rulebook *original_owner = Phrases::Usage::get_rulebook(&(ph->usage_data)); + int placement = Phrases::Usage::get_rulebook_placement(&(ph->usage_data)); rulebook *owner = original_owner; PluginCalls::place_rule(br->rule_being_booked, original_owner, &owner); if (owner != original_owner) { - Phrases::Usage::set_rulebook(&(ph->usage_data), owner); + Phrases::Usage::set_rulebook(&(ph->usage_data), owner); LOGIF(RULE_ATTACHMENTS, "Rerouting $b: $K --> $K\n", br, original_owner, owner); } diff --git a/docs/imperative-module/2-rlb.html b/docs/imperative-module/2-rlb.html index d2c7190f1..fe7c962cb 100644 --- a/docs/imperative-module/2-rlb.html +++ b/docs/imperative-module/2-rlb.html @@ -87,7 +87,7 @@ MathJax = {

Rulebooks collate rules and provide an organised way for them to collaborate on a larger task.

-
+

§1. Introduction. We think of a rulebook as being a list of rules, for which see the code in Booking Lists, but it also has a good deal of metadata. Handling that @@ -230,11 +230,11 @@ being analogous to a function \(X\to Y\).

-int Rulebooks::focus(rulebook *B) {
+int Rulebooks::focus(rulebook *B) {
     return Rulebooks::Outcomes::get_focus(&(B->my_focus));
 }
 
-kind *Rulebooks::get_focus_kind(rulebook *B) {
+kind *Rulebooks::get_focus_kind(rulebook *B) {
     return Rulebooks::Outcomes::get_focus_parameter_kind(&(B->my_focus));
 }
 
@@ -396,7 +396,7 @@ that action are automatically created, and similarly for activities and scenes.
     return BookingLists::first(B->contents);
 }
 
-int Rulebooks::runs_during_activities(rulebook *B) {
+int Rulebooks::runs_during_activities(rulebook *B) {
     return B->runs_during_activities;
 }
 
@@ -404,7 +404,7 @@ that action are automatically created, and similarly for activities and scenes.

-void Rulebooks::log_name_only(rulebook *B) {
+void Rulebooks::log_name_only(rulebook *B) {
     LOG("Rulebook %d (%W)", B->allocation_id, B->primary_name);
 }
 
@@ -616,8 +616,8 @@ user in beta-testing.)
     BookingLists::remove(B->contents, R);
 }
 
-

§13. Name parsing of rulebooks. The following internal finds the "stem" of a rule, that is, the part -which identifies which rulebook it will go into. For example, in +

§13. Rule stems. The voracious nonterminal <rulebook-stem> finds the "stem" of a rule, that is, +the part which identifies which rulebook it will go into. For example, in;

@@ -628,30 +628,58 @@ which identifies which rulebook it will go into. For example, in

Instead of eating: ...

-

the stems are "before printing the name" and "instead". It makes use -of <rulebook-stem-inner> below, and then does some direct parsing. +

the stems are "before printing the name" and "instead". +

+ +

The results are, however, too complicated to return from <rulebook-stem>; since +it is not used recursively, we store the results in parsed_rm on success.

 typedef struct rulebook_match {
     struct rulebook *matched_rulebook;
-    int match_from;
-    int match_length;
-    int advance_words;
-    int tail_words;
-    struct article *article_used;
-    int placement_requested;
+    int match_from;  first word of matched text
+    int match_length;  number of words in matched text
+    int advance_words;  how far the nonterminal should advance
+    int tail_words;  for rulebook names split by scene start or end
+    struct article *article_used;  or NULL if none was
+    int placement_requested;  one of the *_PLACEMENT values
 } rulebook_match;
+
+rulebook_match parsed_rm;
+int parsed_scene_stem_len = 0;
+rulebook *parsed_scene_stem_B = NULL;
 

§14.

 <rulebook-stem> internal ? {
-    rulebook_match rm = Rulebooks::rb_match_from_description(W);
-    if (rm.matched_rulebook == NULL) { ==> { fail nonterminal }; }
-    parsed_rm = rm;
-    return Wordings::first_wn(W) + rm.advance_words - 1;
+    int initial_w1 = Wordings::first_wn(W);
+    parsed_scene_stem_len = 0;
+    parsed_scene_stem_B = NULL;
+    if (<rulebook-stem-inner>(W)) {
+        W = GET_RW(<rulebook-stem-name>, 1);
+        int modifier_words = Wordings::first_wn(W) - initial_w1;
+        article_usage *au = (article_usage *) <<rp>>;
+        int pl = <<r>>;
+        rulebook_match rm;
+        rm.match_length = 0;
+        rm.advance_words = 0;
+        rm.tail_words = 0;
+        rm.matched_rulebook = NULL;
+        if (Rulebooks::rb_match_from_description(W, parsed_scene_stem_B,
+            parsed_scene_stem_len, &rm)) {
+            parsed_rm = rm;
+            parsed_rm.match_length += modifier_words;
+            parsed_rm.advance_words += modifier_words;
+            parsed_rm.match_from = initial_w1;
+            parsed_rm.article_used = (au)?(au->article_used):NULL;
+            parsed_rm.placement_requested = pl;
+            return initial_w1 + parsed_rm.advance_words - 1;
+        }
+    }
+    ==> { fail nonterminal };
 }
 
@@ -662,114 +690,121 @@ of <rulebook-stem-inner> below, and then does some direct parsing.

The first rule for printing the name of something: ...

-

the following grammar peels away the easier-to-read indications at the -front. It notes the use of "The", and the placement "first"; it throws -away other verbiage so that <rulebook-stem-name> matches -

- -
-

printing the name of something

-
- -

<rulebook-stem> then takes over again and searches for the longest possible -rulebook name at the start of the stem. So if there were a rulebook called -"printing", it wouldn't match here, because "printing the name" is longer. -(<rulebook-stem> doesn't match the "of".) -

- -

Productions (a) and (b) of <rulebook-stem-name> are slightly hacky exceptions -to allow for the "when S begins" rulebooks, where S can be any description -of a scene rather than just a scene's name. In effect, the stem here consists -of the two outer words and is discontiguous. +

the following grammar peels away the easier-to-read indications at the front. It +notes the use of "The", and the placement "first"; it throws away other verbiage so +that <rulebook-stem-name> matches "printing the name of something".

 <rulebook-stem-inner> ::=
-    <indefinite-article> <rulebook-stem-inner-unarticled> |  ==> { R[2], RP[1] }
-    <definite-article> <rulebook-stem-inner-unarticled> |    ==> { R[2], RP[1] }
-    <rulebook-stem-inner-unarticled>                         ==> { R[1], NULL }
+    <indefinite-article> <rulebook-stem-inner-unarticled> | ==> { R[2], RP[1] }
+    <definite-article> <rulebook-stem-inner-unarticled> |   ==> { R[2], RP[1] }
+    <rulebook-stem-inner-unarticled>                        ==> { R[1], NULL }
 
 <rulebook-stem-inner-unarticled> ::=
-    rule for/about/on <rulebook-stem-name> |  ==> { MIDDLE_PLACEMENT, -, <<len>> = R[1] }
-    rule <rulebook-stem-name> |               ==> { MIDDLE_PLACEMENT, -, <<len>> = R[1] }
-    first rule <rulebook-stem-name> |         ==> { FIRST_PLACEMENT, -, <<len>> = R[1] }
-    first <rulebook-stem-name> |              ==> { FIRST_PLACEMENT, -, <<len>> = R[1] }
-    last rule <rulebook-stem-name> |          ==> { LAST_PLACEMENT, -, <<len>> = R[1] }
-    last <rulebook-stem-name> |               ==> { LAST_PLACEMENT, -, <<len>> = R[1] }
-    <rulebook-stem-name>                      ==> { MIDDLE_PLACEMENT, -, <<len>> = R[1] }
+    rule for/about/on <rulebook-stem-name> | ==> { MIDDLE_PLACEMENT, - }
+    rule <rulebook-stem-name> |              ==> { MIDDLE_PLACEMENT, - }
+    first rule <rulebook-stem-name> |        ==> { FIRST_PLACEMENT, - }
+    first <rulebook-stem-name> |             ==> { FIRST_PLACEMENT, - }
+    last rule <rulebook-stem-name> |         ==> { LAST_PLACEMENT, - }
+    last <rulebook-stem-name> |              ==> { LAST_PLACEMENT, - }
+    <rulebook-stem-name>                     ==> { MIDDLE_PLACEMENT, - }
 
 <rulebook-stem-name> ::=
-    {when ... begins} |  ==> { 2, -, <<rulebook:m>> = Rulebooks::std(WHEN_SCENE_BEGINS_RB) }
-    {when ... ends} |    ==> { 2, -, <<rulebook:m>> = Rulebooks::std(WHEN_SCENE_ENDS_RB) }
-    ...                  ==> { 0, -, <<rulebook:m>> = NULL }
+    {when ... begins} |                      ==> Match the when scene begins exception15.1
+    {when ... ends} |                        ==> Match the when scene ends exception15.2
+    ...                                      ==> { -, - }
 
-

§16.

+

§15.1. Match the when scene begins exception15.1 = +

-rulebook_match Rulebooks::rb_match_from_description(wording W) {
-    int initial_w1 = Wordings::first_wn(W), modifier_words;
-    int pl = MIDDLE_PLACEMENT;
-    rulebook *rb;
-    rulebook_match rm;
+    parsed_scene_stem_B = Rulebooks::std(WHEN_SCENE_BEGINS_RB);
+    parsed_scene_stem_len = 2;
+    ==> { -, - };
+
+ +

§15.2. Match the when scene ends exception15.2 = +

- <rulebook-stem-inner>(W); - W = GET_RW(<rulebook-stem-name>, 1); - article_usage *au = (article_usage *) <<rp>>; pl = <<r>>; +
+    parsed_scene_stem_B = Rulebooks::std(WHEN_SCENE_ENDS_RB);
+    parsed_scene_stem_len = 2;
+    ==> { -, - };
+
+ +

§16. In this function, SB will be set for the hacky exceptional case where it's +known that the remaining text matches "when ... begins/ends", one of the scenes +rulebooks. This is all a bit inelegant, but we manage. +

- modifier_words = Wordings::first_wn(W) - initial_w1; +
+int Rulebooks::rb_match_from_description(wording W, rulebook *SB, int len, rulebook_match *rm) {
+    Find the longest-named rulebook whose name appears at the front of W16.1;
+    if (rm->matched_rulebook == NULL) return FALSE;
 
-    rm.match_length = 0;
-    rm.advance_words = 0;
-    rm.match_from = initial_w1;
-    rm.tail_words = 0;
-    rm.matched_rulebook = NULL;
-    rm.article_used = (au)?(au->article_used):NULL;
-    rm.placement_requested = pl;
+    rm->advance_words = rm->match_length;
+    if (rm->matched_rulebook == SB) {
+        rm->tail_words = 1;
+        rm->match_length = 1;
+    }
 
-    LOOP_OVER(rb, rulebook) {
+    If the matched rulebook was derived from an action, match less text16.2;
+    return TRUE;
+}
+
+

§16.1. Find the longest-named rulebook whose name appears at the front of W16.1 = +

- if (rb == <<rulebook:m>>) { - if (rm.match_length < <<len>>) { - rm.match_length = <<len>>; - rm.matched_rulebook = rb; +
+    rulebook *B;
+    LOOP_OVER(B, rulebook) {
+        if (B == SB) {  matches one of the scene begins/ends exceptions
+            if (rm->match_length < len) {
+                rm->match_length = len;
+                rm->matched_rulebook = B;
             }
-        } else {
-            if (Wordings::starts_with(W, rb->primary_name)) {
-                if (rm.match_length < Wordings::length(rb->primary_name)) {
-                    rm.match_length = Wordings::length(rb->primary_name);
-                    rm.matched_rulebook = rb;
+        } else {  any other rulebook
+            if (Wordings::starts_with(W, B->primary_name)) {
+                if (rm->match_length < Wordings::length(B->primary_name)) {
+                    rm->match_length = Wordings::length(B->primary_name);
+                    rm->matched_rulebook = B;
                 }
-            } else if (Wordings::starts_with(W, rb->alternative_name)) {
-                if (rm.match_length < Wordings::length(rb->alternative_name)) {
-                    rm.match_length = Wordings::length(rb->alternative_name);
-                    rm.matched_rulebook = rb;
+            } else if (Wordings::starts_with(W, B->alternative_name)) {
+                if (rm->match_length < Wordings::length(B->alternative_name)) {
+                    rm->match_length = Wordings::length(B->alternative_name);
+                    rm->matched_rulebook = B;
                 }
             }
         }
-
     }
-
-    if (rm.match_length == 0) return rm;
-
-    rm.advance_words = rm.match_length;
-
-    if (rm.matched_rulebook == <<rulebook:m>>) {
-        rm.tail_words = 1;
-        rm.match_length = 1;
-    }
-
-    if (rm.matched_rulebook->action_stem_length) {
-        int w1a = Wordings::first_wn(W) + rm.match_length - 1;
-        if (w1a != Wordings::last_wn(W))
-            rm.match_length = rm.matched_rulebook->action_stem_length;
-    }
-
-    rm.match_length += modifier_words;
-    rm.advance_words += modifier_words;
-    return rm;
-}
 
+ +

§16.2. action_stem_length is zero except for rulebooks derived from actions, such +as "check taking". It is by definition the difference in length between the +rulebook name and the action name — here, therefore, it's 2 - 1 = 1. +

+ +

If the entire text W is the rulebook name — in this case, "check taking" — +we match that as normal. But if there is more text — say, "check taking an +open container" — then we retreat slightly and match only the prefix "check". +This ensures that something like "check taking or dropping something" is +initially, at least, put into the general check rulebook and not the specific +one for taking, where the "or dropping" part would never have effect. +

+ +

If the matched rulebook was derived from an action, match less text16.2 = +

+ +
+    if (rm->matched_rulebook->action_stem_length > 0) {
+        int w1a = Wordings::first_wn(W) + rm->match_length - 1;
+        if (w1a != Wordings::last_wn(W))
+            rm->match_length = rm->matched_rulebook->action_stem_length;
+    }
+
+

§17. Standard rulebooks. A few rulebooks are special to Inform, in that they have built-in support either from the compiler, or from one of the kits, or both. The list below looks long, but actually most of these are special only in that they are shown in their @@ -825,7 +860,7 @@ for the first two. int built_in_rulebooks_initialised = FALSE; rulebook *built_in_rulebooks[MAX_BUILT_IN_RULEBOOKS]; -rulebook *Rulebooks::std(int rb) { +rulebook *Rulebooks::std(int rb) { if ((rb < 0) || (rb >= MAX_BUILT_IN_RULEBOOKS)) internal_error("rb out of range"); if (built_in_rulebooks_initialised == FALSE) { built_in_rulebooks_initialised = TRUE; diff --git a/docs/imperative-module/2-rls.html b/docs/imperative-module/2-rls.html index 09a59b545..e3e0a039e 100644 --- a/docs/imperative-module/2-rls.html +++ b/docs/imperative-module/2-rls.html @@ -145,7 +145,7 @@ rule called W,

-rule *Rules::obtain(wording W, int allow_responses) {
+rule *Rules::obtain(wording W, int allow_responses) {
     if (Wordings::nonempty(W)) {
         W = Articles::remove_the(W);
         rule *R = Rules::by_name(W);
@@ -182,7 +182,7 @@ rule called W,
 
 
 int PM_RuleWithComma_issued_at = -1;
-int Rules::vet_name(wording W) {
+int Rules::vet_name(wording W) {
     if (<unsuitable-name>(W)) {
         if (PM_RuleWithComma_issued_at != Wordings::first_wn(W)) {
             PM_RuleWithComma_issued_at = Wordings::first_wn(W);
@@ -217,7 +217,7 @@ end in "rule" slightly differently. (Not all rule names do: those for timed even
         mc, Rvalues::from_rule(R), Task::language_of_syntax());
 }
 
-rule *Rules::by_name(wording W) {
+rule *Rules::by_name(wording W) {
     if (Wordings::empty(W)) return NULL;
     W = Articles::remove_the(W);
     unsigned int mc = RULE_MC;
@@ -318,11 +318,11 @@ of a phrase as follows:
 

-void Rules::set_defn_as_phrase(rule *R, phrase *ph) {
+void Rules::set_defn_as_phrase(rule *R, phrase *ph) {
     R->defn_as_phrase = ph;
 }
 
-phrase *Rules::get_defn_as_phrase(rule *R) {
+phrase *Rules::get_defn_as_phrase(rule *R) {
     if (R == NULL) return NULL;
     return R->defn_as_phrase;
 }
@@ -348,7 +348,7 @@ the variables belonging to that activity.
 
 struct stacked_variable_owner_list *all_action_processing_vars = NULL;
 
-stacked_variable_owner_list *Rules::all_action_processing_variables(void) {
+stacked_variable_owner_list *Rules::all_action_processing_variables(void) {
     if (all_action_processing_vars == NULL) {
         rulebook *B = Rulebooks::std(ACTION_PROCESSING_RB);
         if (B) all_action_processing_vars =
diff --git a/docs/imperative-module/3-cs.html b/docs/imperative-module/3-cs.html
index 7272ae699..135c4038b 100644
--- a/docs/imperative-module/3-cs.html
+++ b/docs/imperative-module/3-cs.html
@@ -268,7 +268,7 @@ correctly refer to the most recently mentioned action.
         current_sentence = ph->declaration_node;
         Frames::make_current(&(ph->stack_frame));
         ph->runtime_context_data =
-            Phrases::Usage::to_runtime_context_data(&(ph->usage_data));
+            Phrases::Usage::to_runtime_context_data(&(ph->usage_data));
         Frames::remove_current();
     }
 }
@@ -385,7 +385,7 @@ of Inform.
 
     phrase *ph;
     LOOP_OVER(ph, phrase)
-        if (Phrases::Usage::get_effect(&(ph->usage_data)) ==
+        if (Phrases::Usage::get_effect(&(ph->usage_data)) ==
             DEFINITIONAL_PHRASE_EFF)
             Phrases::compile(ph, &total_phrases_compiled,
                 total_phrases_to_compile, NULL, NULL, NULL);
@@ -467,7 +467,7 @@ points", say). This is where we do it:
     phrase *ph;
     LOOP_OVER(ph, phrase)
         if ((Phrases::TypeData::invoked_inline(ph)) &&
-            (Phrases::Usage::has_name_as_constant(&(ph->usage_data)))) {
+            (Phrases::Usage::has_name_as_constant(&(ph->usage_data)))) {
             current_sentence = Phrases::declaration_node(ph);
             Problems::quote_source(1, current_sentence);
             StandardProblems::handmade_problem(Task::syntax_tree(), _p_(PM_NamedInline));
diff --git a/docs/imperative-module/3-dptd.html b/docs/imperative-module/3-dptd.html
index cc480a064..dfd911c46 100644
--- a/docs/imperative-module/3-dptd.html
+++ b/docs/imperative-module/3-dptd.html
@@ -337,7 +337,7 @@ match is shown.
         if (Kinds::Behaviour::definite(phtd->return_kind) == FALSE) WRITE("value");
         else Kinds::Textual::write(OUT, phtd->return_kind);
         WRITE("</i>");
-        wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
+        wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
         if (Wordings::nonempty(W)) {
             WRITE("&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<i>y</i>&nbsp;=&nbsp;<b>%+W</b>(<i>x</i>)", W);
         }
@@ -397,7 +397,7 @@ of course.
 

-    wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
+    wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
     if (Wordings::nonempty(W)) {
         HTML_CLOSE("p");
         HTML_OPEN("p");
diff --git a/docs/imperative-module/3-pav.html b/docs/imperative-module/3-pav.html
index 2bdc71a44..f55d22ca5 100644
--- a/docs/imperative-module/3-pav.html
+++ b/docs/imperative-module/3-pav.html
@@ -98,7 +98,7 @@ own right, a functional-programming sort of device. For example:
 

-constant_phrase *Phrases::Constants::create(wording NW, wording RW) {
+constant_phrase *Phrases::Constants::create(wording NW, wording RW) {
     constant_phrase *cphr = CREATE(constant_phrase);
     cphr->phrase_meant = NULL;  we won't know until later
     cphr->cphr_kind = NULL;  nor this
@@ -113,7 +113,7 @@ own right, a functional-programming sort of device. For example:
 

-constant_phrase *Phrases::Constants::parse(wording NW) {
+constant_phrase *Phrases::Constants::parse(wording NW) {
     if (<s-value>(NW)) {
         parse_node *spec = <<rp>>;
         if (Rvalues::is_CONSTANT_construction(spec, CON_phrase)) {
@@ -149,7 +149,7 @@ the following takes a patch-it-later approach.
 

-phrase *Phrases::Constants::as_phrase(constant_phrase *cphr) {
+phrase *Phrases::Constants::as_phrase(constant_phrase *cphr) {
     if (cphr == NULL) internal_error("null cphr");
     if (cphr->phrase_meant == NULL) {
         phrase *ph;
diff --git a/docs/imperative-module/3-phr.html b/docs/imperative-module/3-phr.html
index 462a27c70..2220bcb12 100644
--- a/docs/imperative-module/3-phr.html
+++ b/docs/imperative-module/3-phr.html
@@ -180,7 +180,7 @@ invocation which is given as verbatim I6.
 
     Parse for the PHUD in fine mode5.2;
 
-    int effect = Phrases::Usage::get_effect(&phud);
+    int effect = Phrases::Usage::get_effect(&phud);
     if ((inline_wn >= 0) && (effect != TO_PHRASE_EFF)) Inline is for To... phrases only5.10;
 
     if ((effect != DEFINITIONAL_PHRASE_EFF) && (p->down == NULL))
@@ -214,14 +214,14 @@ invocation which is given as verbatim I6.
 

-    phud = Phrases::Usage::new(Node::get_text(p), FALSE);
+    phud = Phrases::Usage::new(Node::get_text(p), FALSE);
 
  • This code is used in §5.

§5.3. Construct the PHTD, find the phrase options, find the documentation reference5.3 =

-    wording XW = Phrases::Usage::get_preamble_text(&phud);
+    wording XW = Phrases::Usage::get_preamble_text(&phud);
     phtd = Phrases::TypeData::new();
     if (inline_wn >= 0) Phrases::TypeData::make_inline(&phtd);
     switch (effect) {
@@ -289,11 +289,11 @@ inline definitions.
             break;
         case RULE_IN_RULEBOOK_EFF:
             Rules::request_automatic_placement(
-                Phrases::Usage::to_rule(&(new_ph->usage_data), new_ph));
+                Phrases::Usage::to_rule(&(new_ph->usage_data), new_ph));
             new_ph->compile_with_run_time_debugging = TRUE;
             break;
         case RULE_NOT_IN_RULEBOOK_EFF:
-            Phrases::Usage::to_rule(&(new_ph->usage_data), new_ph);
+            Phrases::Usage::to_rule(&(new_ph->usage_data), new_ph);
             new_ph->compile_with_run_time_debugging = TRUE;
             break;
     }
@@ -332,7 +332,7 @@ of it:
 

-    wording XW = Phrases::Usage::get_preamble_text(&phud);
+    wording XW = Phrases::Usage::get_preamble_text(&phud);
     LOGIF(PHRASE_CREATIONS, "Creating phrase: <%W>\n$U", XW, &phud);
 
     new_ph = CREATE(phrase);
@@ -448,7 +448,7 @@ what number is...", for instance.
 void Phrases::log(phrase *ph) {
     if (ph == NULL) { LOG("RULE:NULL"); return; }
     LOG("%n", Phrases::iname(ph));
-    Phrases::Usage::log_rule_name(&(ph->usage_data));
+    Phrases::Usage::log_rule_name(&(ph->usage_data));
 }
 
 void Phrases::log_briefly(phrase *ph) {
@@ -506,7 +506,7 @@ what number is...", for instance.
     return ph->ph_iname;
 }
 
-parse_node *Phrases::declaration_node(phrase *ph) {
+parse_node *Phrases::declaration_node(phrase *ph) {
     return ph->declaration_node;
 }
 
@@ -524,7 +524,7 @@ response to "requests". All other phrases are compiled just once. void Phrases::compile(phrase *ph, int *i, int max_i, stacked_variable_owner_list *legible, to_phrase_request *req, rule *R) { if (ph->imported) return; - int effect = Phrases::Usage::get_effect(&(ph->usage_data)); + int effect = Phrases::Usage::get_effect(&(ph->usage_data)); if (effect == RULE_NOT_IN_RULEBOOK_EFF) effect = RULE_IN_RULEBOOK_EFF; if (effect == TO_PHRASE_EFF) { Routines::Compile::routine(ph, legible, req, R); diff --git a/docs/imperative-module/3-pi.html b/docs/imperative-module/3-pi.html index 1205196ae..6e5263432 100644 --- a/docs/imperative-module/3-pi.html +++ b/docs/imperative-module/3-pi.html @@ -116,7 +116,7 @@ suppress indexing of their definitions. phrase *ph, *run_begin = NULL; LOOP_OVER(ph, phrase) { include only if this is a To... phrase - if (Phrases::Usage::get_effect(&(ph->usage_data)) != TO_PHRASE_EFF) + if (Phrases::Usage::get_effect(&(ph->usage_data)) != TO_PHRASE_EFF) continue; and only if it is under an indexed heading heading *this_heading = diff --git a/docs/imperative-module/3-prcd.html b/docs/imperative-module/3-prcd.html index 41765a6b3..952786dc0 100644 --- a/docs/imperative-module/3-prcd.html +++ b/docs/imperative-module/3-prcd.html @@ -181,7 +181,7 @@ the following only blanks out a PHRCD structure ready for that to happen.

-ph_runtime_context_data Phrases::Context::new(void) {
+ph_runtime_context_data Phrases::Context::new(void) {
     ph_runtime_context_data phrcd;
     phrcd.activity_context = EMPTY_WORDING;
     phrcd.activity_where = NULL;
diff --git a/docs/imperative-module/3-pu.html b/docs/imperative-module/3-pu.html
index 1f3615cd1..a7ffb315e 100644
--- a/docs/imperative-module/3-pu.html
+++ b/docs/imperative-module/3-pu.html
@@ -73,7 +73,7 @@ function togglePopup(material_id) {
     
 

To parse the preamble of a phrase declaration to a phrase usage (PHUD) structure containing a mostly textual representation of the conditions for its usage.

-
+

§1. As we've seen, phrases can be categorised according to their "effect". We need one more code: @@ -107,13 +107,7 @@ We need one more code: } ph_usage_data;

  • The structure ph_usage_data is accessed in 3/phr, 3/dptd, 3/pav, 3/tp and here.
-

§3. We will need to store values temporarily here while parsing: -

- -
-rulebook_match parsed_rm;
-
-

§4. The mid-morning predeclarations. Recall that early in Inform's run, we make a coarse parsing of the preamble +

§3. The mid-morning predeclarations. Recall that early in Inform's run, we make a coarse parsing of the preamble of each rule to look for a name: if we find it, we declare it as a rule; and in any event we throw away the PHUD produced. (We will make a better one just before noon.) @@ -121,12 +115,12 @@ just before noon.)

 void Phrases::Usage::predeclare_name_in(parse_node *p) {
-    ph_usage_data phud = Phrases::Usage::new(Node::get_text(p), TRUE);
+    ph_usage_data phud = Phrases::Usage::new(Node::get_text(p), TRUE);
     if (Wordings::nonempty(phud.explicit_name))
         Rules::obtain(phud.explicit_name, TRUE);
 }
 
-

§5. The late-morning creations. A little later on, we've made a rule phrase, and it now has a proper PHUD. +

§4. The late-morning creations. A little later on, we've made a rule phrase, and it now has a proper PHUD. If the rule is an anonymous one, such as:

@@ -150,11 +144,11 @@ connect this existing one to the phrase. rule *Phrases::Usage::to_rule(ph_usage_data *phud, phrase *ph) { wording W = EMPTY_WORDING; int explicitly = FALSE; - Find the name of the phrase, and whether or not it's explicitly given5.1; + Find the name of the phrase, and whether or not it's explicitly given4.1; rule *R = NULL; if (Wordings::nonempty(W)) R = Rules::by_name(W); - if (R) Check that this isn't duplicating the name of a rule already made5.2 + if (R) Check that this isn't duplicating the name of a rule already made4.2 else R = Rules::obtain(W, explicitly); if (Wordings::empty(W)) Hierarchy::markup_wording(R->compilation_data.rule_package, RULE_NAME_HMD, Node::get_text(ph->declaration_node)); @@ -162,12 +156,12 @@ connect this existing one to the phrase. package_request *P = RTRules::package(R); ph->ph_iname = Hierarchy::make_localised_iname_in(RULE_FN_HL, P, ph->owning_module); - Do some tedious business for indexing the rule later on5.3; + Do some tedious business for indexing the rule later on4.3; return R; }
-

§5.1. Find the name of the phrase, and whether or not it's explicitly given5.1 = +

§4.1. Find the name of the phrase, and whether or not it's explicitly given4.1 =

@@ -178,8 +172,8 @@ connect this existing one to the phrase.
         explicitly = TRUE;
     }
 
-
  • This code is used in §5.
-

§5.2. Check that this isn't duplicating the name of a rule already made5.2 = +

  • This code is used in §4.
+

§4.2. Check that this isn't duplicating the name of a rule already made4.2 =

@@ -194,11 +188,11 @@ connect this existing one to the phrase.
         Problems::issue_problem_end();
     }
 
-
  • This code is used in §5.
-

§5.3. This is simply to make the rule's entry in the Index more helpful. +

  • This code is used in §4.
+

§4.3. This is simply to make the rule's entry in the Index more helpful.

-

Do some tedious business for indexing the rule later on5.3 = +

Do some tedious business for indexing the rule later on4.3 =

@@ -212,8 +206,8 @@ connect this existing one to the phrase.
     }
     IXRules::set_italicised_index_text(R, IX);
 
-
  • This code is used in §5.
-

§6. Parsing. For our purposes here, phrase definitions and rules are the same thing. Inform +

  • This code is used in §4.
+

§5. Parsing. For our purposes here, phrase definitions and rules are the same thing. Inform detects these from the punctuation used, not from their wording, and divides them into a "preamble" (the part before the colon, or in limited cases a comma) and a "body". Early on in Inform's run, we parse the preamble in @@ -225,24 +219,24 @@ just enough from the wording to tell what sort of rule/phrase is to follow. <rule-preamble> ::= definition | ==> { DEFINITIONAL_PHRASE_EFF, - } this is the {... rule} | ==> { RULE_NOT_IN_RULEBOOK_EFF, -, <<event-time>> = NOT_AN_EVENT, <<written>> = FALSE } - this is the rule | ==> Issue PM_NamelessRule problem6.1 - this is ... rule | ==> Issue PM_UnarticledRule problem6.2 - this is ... rules | ==> Issue PM_PluralisedRule problem6.3 + this is the rule | ==> Issue PM_NamelessRule problem5.1 + this is ... rule | ==> Issue PM_UnarticledRule problem5.2 + this is ... rules | ==> Issue PM_PluralisedRule problem5.3 <event-rule-preamble> | ==> { RULE_NOT_IN_RULEBOOK_EFF, -, <<event-time>> = R[1] } - to | ==> Issue PM_BareTo problem6.4 - to ... ( called ... ) | ==> Issue PM_DontCallPhrasesWithCalled problem6.5 + to | ==> Issue PM_BareTo problem5.4 + to ... ( called ... ) | ==> Issue PM_DontCallPhrasesWithCalled problem5.5 {to ...} ( this is the {### function} inverse to ### ) | ==> { TO_PHRASE_EFF, -, <<named>> = TRUE, <<written>> = TRUE, <<inverted>> = TRUE } {to ...} ( this is the {### function} ) | ==> { TO_PHRASE_EFF, -, <<named>> = TRUE, <<written>> = TRUE, <<inverted>> = FALSE } {to ...} ( this is ... ) | ==> { TO_PHRASE_EFF, -, <<named>> = TRUE, <<written>> = FALSE } to ... | ==> { TO_PHRASE_EFF, -, <<named>> = FALSE } ... ( this is the {... rule} ) | ==> { RULE_IN_RULEBOOK_EFF, -, <<named>> = TRUE, <<written>> = FALSE } - ... ( this is the rule ) | ==> Issue PM_NamelessRule problem6.1 - ... ( this is ... rule ) | ==> Issue PM_UnarticledRule problem6.2 - ... ( this is ... rules ) | ==> Issue PM_PluralisedRule problem6.3 + ... ( this is the rule ) | ==> Issue PM_NamelessRule problem5.1 + ... ( this is ... rule ) | ==> Issue PM_UnarticledRule problem5.2 + ... ( this is ... rules ) | ==> Issue PM_PluralisedRule problem5.3 ... ==> { RULE_IN_RULEBOOK_EFF, -, <<named>> = FALSE }

-

§6.1. Issue PM_NamelessRule problem6.1 = +

§5.1. Issue PM_NamelessRule problem5.1 =

@@ -251,8 +245,8 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
         "so you need to give a name: 'this is the abolish dancing rule', say, "
         "not just 'this is the rule'.");
 
-
  • This code is used in §6 (twice).
-

§6.2. Issue PM_UnarticledRule problem6.2 = +

  • This code is used in §5 (twice).
+

§5.2. Issue PM_UnarticledRule problem5.2 =

@@ -262,8 +256,8 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
         "with this name: 'this is the promote dancing rule', say, not just "
         "'this is promote dancing rule'.");
 
-
  • This code is used in §6 (twice).
-

§6.3. Issue PM_PluralisedRule problem6.3 = +

  • This code is used in §5 (twice).
+

§5.3. Issue PM_PluralisedRule problem5.3 =

@@ -272,8 +266,8 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
         "since the plural is only used for rulebooks, which can of course "
         "contain many rules at once.");
 
-
  • This code is used in §6 (twice).
-

§6.4. Issue PM_BareTo problem6.4 = +

  • This code is used in §5 (twice).
+

§5.4. Issue PM_BareTo problem5.4 =

@@ -281,8 +275,8 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
         "'to' what? No name is given",
         "which means that this would not define a new phrase.");
 
-
  • This code is used in §6.
-

§6.5. Issue PM_DontCallPhrasesWithCalled problem6.5 = +

  • This code is used in §5.
+

§5.5. Issue PM_DontCallPhrasesWithCalled problem5.5 =

@@ -291,8 +285,8 @@ just enough from the wording to tell what sort of rule/phrase is to follow.
         "and instead use 'this is...'. For example, 'To salute (called saluting)' "
         "isn't allowed, but 'To salute (this is saluting)' is.");
 
-
  • This code is used in §6.
-

§7. As a safety measure, to avoid ambiguities, Inform only allows one phrase +

  • This code is used in §5.
+

§6. As a safety measure, to avoid ambiguities, Inform only allows one phrase definition to begin with "now". It recognises such phrases as those whose preambles match:

@@ -302,7 +296,7 @@ preambles match: to now ...
-

§8. In basic mode (only), the To phrase "to begin" acts as something like +

§7. In basic mode (only), the To phrase "to begin" acts as something like main in a C-like language, so we need to take note of where it's defined:

@@ -311,7 +305,7 @@ preambles match: to begin
-

§9. Much later on, Inform returns to the definition. If the preamble matches +

§8. Much later on, Inform returns to the definition. If the preamble matches either of the final two productions of <rule-preamble>, then we definitely have a rule rather than a phrase definition or a timed event; and in that case the rule's preamble (without its name, if given) has to match the @@ -341,7 +335,7 @@ following grammar. (Parsing this is "fine mode".) rule ==> { FALSE, - }

-

§10. The following turns the preamble text into a PHUD. It can be used as often +

§9. The following turns the preamble text into a PHUD. It can be used as often as necessary in "coarse mode", but should be run once and once only on any given phrase when in "fine mode".

@@ -358,23 +352,23 @@ effects — see below.)
 int no_now_phrases = 0;
 
-ph_usage_data Phrases::Usage::new(wording W, int coarse_mode) {
+ph_usage_data Phrases::Usage::new(wording W, int coarse_mode) {
     ph_usage_data phud;
-    Empty the PHUD10.1;
+    Empty the PHUD9.1;
 
     if (<rule-preamble>(W)) {
         phud.phrase_effect = <<r>>;
         switch (<<r>>) {
             case TO_PHRASE_EFF:
-                The preamble parses to a To phrase10.2;
+                The preamble parses to a To phrase9.2;
                 break;
             case DEFINITIONAL_PHRASE_EFF:
                 break;
             case RULE_IN_RULEBOOK_EFF:
-                The preamble parses to a rule with a specified rulebook10.3;
+                The preamble parses to a rule with a specified rulebook9.3;
                 break;
             case RULE_NOT_IN_RULEBOOK_EFF:
-                The preamble parses to a rule with no specified rulebook10.4;
+                The preamble parses to a rule with no specified rulebook9.4;
                 break;
         }
     }
@@ -382,7 +376,7 @@ effects — see below.)
     return phud;
 }
 
-

§10.1. Empty the PHUD10.1 = +

§9.1. Empty the PHUD9.1 =

@@ -405,14 +399,14 @@ effects — see below.)
     phud.owning_rulebook_placement = MIDDLE_PLACEMENT;
     phud.explicit_name_for_inverse = EMPTY_WORDING;
 
-
  • This code is used in §10.
-

§10.2. The preamble parses to a To phrase10.2 = +

  • This code is used in §9.
+

§9.2. The preamble parses to a To phrase9.2 =

     phud.rule_preamble = W;
 
-    if (<<named>>) The preamble parses to a named To phrase10.2.1;
+    if (<<named>>) The preamble parses to a named To phrase9.2.1;
     if (<now-phrase-preamble>(W)) {
         if ((coarse_mode) && (no_now_phrases++ == 1)) {
             StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_RedefinedNow),
@@ -427,13 +421,13 @@ effects — see below.)
         phud.to_begin = TRUE;
     }
 
-
  • This code is used in §10.
-

§10.2.1. When we parse a named phrase in coarse mode, we need to make sure that +

  • This code is used in §9.
+

§9.2.1. When we parse a named phrase in coarse mode, we need to make sure that name is registered as a constant value; when we parse it again in fine mode, we can get that value back again if we look it up by name.

-

The preamble parses to a named To phrase10.2.1 = +

The preamble parses to a named To phrase9.2.1 =

@@ -479,8 +473,8 @@ mode, we can get that value back again if we look it up by name.
     }
     phud.rule_preamble = RW;
 
- -

§10.3. The preamble parses to a rule with a specified rulebook10.3 = +

  • This code is used in §9.2.
+

§9.3. The preamble parses to a rule with a specified rulebook9.3 =

@@ -488,10 +482,10 @@ mode, we can get that value back again if we look it up by name.
         W = GET_RW(<rule-preamble>, 1);
         phud.explicit_name = GET_RW(<rule-preamble>, 2);
     }
-    if (coarse_mode == FALSE) Parse the rulebook stem in fine mode10.3.1;
+    if (coarse_mode == FALSE) Parse the rulebook stem in fine mode9.3.1;
 
-
  • This code is used in §10.
-

§10.4. The preamble parses to a rule with no specified rulebook10.4 = +

  • This code is used in §9.
+

§9.4. The preamble parses to a rule with no specified rulebook9.4 =

@@ -505,8 +499,8 @@ mode, we can get that value back again if we look it up by name.
             phud.event_name = GET_RW(<event-rule-preamble>, 1);
     }
 
-
  • This code is used in §10.
-

§10.3.1. That's it for coarse mode. The rest is what happens in fine mode, which +

  • This code is used in §9.
+

§9.3.1. That's it for coarse mode. The rest is what happens in fine mode, which affects rules giving a rulebook and some circumstances:

@@ -517,7 +511,7 @@ affects rules giving a rulebook and some circumstances:

Here "Instead of" is the stem and "taking a container" the bud.

-

Parse the rulebook stem in fine mode10.3.1 = +

Parse the rulebook stem in fine mode9.3.1 =

@@ -533,17 +527,17 @@ affects rules giving a rulebook and some circumstances:
         phud.owning_rulebook = parsed_rm.matched_rulebook;
         if (phud.owning_rulebook == NULL) internal_error("rulebook stem misparsed");
         phud.owning_rulebook_placement = parsed_rm.placement_requested;
-        Disallow the definite article for anonymous rules10.3.1.2;
-        Cut off the bud from the stem10.3.1.1;
+        Disallow the definite article for anonymous rules9.3.1.2;
+        Cut off the bud from the stem9.3.1.1;
     }
     phud.rule_preamble = W;
 
- -

§10.3.1.1. The bud is not always present at all, and need not always be at the end +

  • This code is used in §9.3.
+

§9.3.1.1. The bud is not always present at all, and need not always be at the end of the stem, so we have to be very careful:

-

Cut off the bud from the stem10.3.1.1 = +

Cut off the bud from the stem9.3.1.1 =

@@ -599,17 +593,17 @@ of the stem, so we have to be very careful:
         phud.whenwhile = EMPTY_WORDING;
     }
 
- -

§11. If we can't find a stem, the following chooses which problem to issue: +

+

§10. If we can't find a stem, the following chooses which problem to issue:

 <unrecognised-rule-stem-diagnosis> ::=
-    when *** |    ==> Issue PM_BadRulePreambleWhen problem11.1
-    ...                         ==> Issue PM_BadRulePreamble problem11.2
+    when *** |    ==> Issue PM_BadRulePreambleWhen problem10.1
+    ...                         ==> Issue PM_BadRulePreamble problem10.2
 
-

§11.1. Issue PM_BadRulePreambleWhen problem11.1 = +

§10.1. Issue PM_BadRulePreambleWhen problem10.1 =

@@ -635,8 +629,8 @@ of the stem, so we have to be very careful:
         "location is the South Pole.'");
     Problems::issue_problem_end();
 
-
  • This code is used in §11.
-

§11.2. Issue PM_BadRulePreamble problem11.2 = +

  • This code is used in §10.
+

§10.2. Issue PM_BadRulePreamble problem10.2 =

@@ -650,8 +644,8 @@ of the stem, so we have to be very careful:
         "by some description of the action or value to apply to (e.g. "
         "'Instead of taking something:' or 'Every turn:').");
 
-
  • This code is used in §11.
-

§10.3.1.2. Disallow the definite article for anonymous rules10.3.1.2 = +

  • This code is used in §10.
+

§9.3.1.2. Disallow the definite article for anonymous rules9.3.1.2 =

@@ -662,8 +656,8 @@ of the stem, so we have to be very careful:
             "so (e.g.) 'the before rule: ...' is disallowed; you should "
             "write 'a before rule: ...' instead.");
 
- -

§12. Extracting the stem. A couple of routines to read but not really parse the stem and the bud. +

+

§11. Extracting the stem. A couple of routines to read but not really parse the stem and the bud.

@@ -672,7 +666,7 @@ of the stem, so we have to be very careful:
     return phud->full_preamble;
 }
 
-

§13. For example, for the rule +

§12. For example, for the rule

@@ -692,14 +686,14 @@ of the stem, so we have to be very careful: return EMPTY_WORDING; }
-

§14.

+

§13.

 <when-while-clause> ::=
     ... when/while ...
 
-

§15. Miscellaneous. Some access routines. +

§14. Miscellaneous. Some access routines.

@@ -741,7 +735,7 @@ of the stem, so we have to be very careful:
     if (Wordings::nonempty(phud->explicit_name_for_inverse)) {
         phrase *ph;
         LOOP_OVER(ph, phrase) {
-            wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
+            wording W = Phrases::Usage::get_equation_form(&(ph->usage_data));
             if (Wordings::nonempty(W))
                 if (Wordings::match(W, phud->explicit_name_for_inverse))
                     return ph;
@@ -750,12 +744,12 @@ of the stem, so we have to be very careful:
     return NULL;
 }
 
-

§16. Logging and indexing. The length and thoroughness of this may give some hint of how troublesome +

§15. Logging and indexing. The length and thoroughness of this may give some hint of how troublesome it was to debug the preamble-parsing code:

-void Phrases::Usage::log(ph_usage_data *phud) {
+void Phrases::Usage::log(ph_usage_data *phud) {
     char *ram = "<UNKNOWN_NT>";
     switch(phud->phrase_effect) {
         case AS_YET_UNKNOWN_EFF:        ram = "AS_YET_UNKNOWN_EFF"; break;
@@ -806,7 +800,7 @@ it was to debug the preamble-parsing code:
     } else LOG("(%W)", phud->explicit_name);
 }
 
-

§17. In our compiled code, it's useful to label routines with I6 comments: +

§16. In our compiled code, it's useful to label routines with I6 comments:

@@ -817,7 +811,7 @@ it was to debug the preamble-parsing code:
     DISCARD_TEXT(C)
 }
 
-

§18. And similarly: +

§17. And similarly:

@@ -825,7 +819,7 @@ it was to debug the preamble-parsing code:
     WRITE("%+W", phud->full_preamble);
 }
 
-

§19. How the PHUD translates into a PHRCD. Recall that in the early afternoon, the PHUD for a rule phrase is translated +

§18. How the PHUD translates into a PHRCD. Recall that in the early afternoon, the PHUD for a rule phrase is translated into a PHRCD, that is, a set of instructions about the circumstances for the rule to fire.

@@ -839,7 +833,7 @@ seen problems in Inform. A couple of variables are needed just for that: int NAP_problem_explained = FALSE; pertains to Named Action Patterns int issuing_ANL_problem = FALSE; pertains to Action Name Lists
-

§20.

+

§19.

 ph_runtime_context_data Phrases::Usage::to_runtime_context_data(ph_usage_data *phud) {
@@ -849,21 +843,21 @@ seen problems in Inform. A couple of variables are needed just for that:
         phrcd.permit_all_outcomes = TRUE;
 
     if (phud->phrase_effect == RULE_IN_RULEBOOK_EFF)
-        Finish work parsing the conditions for the rule to fire20.1;
+        Finish work parsing the conditions for the rule to fire19.1;
 
     return phrcd;
 }
 
-

§20.1. All of this is just dumb copying... +

§19.1. All of this is just dumb copying...

-

Finish work parsing the conditions for the rule to fire20.1 = +

Finish work parsing the conditions for the rule to fire19.1 =

     phrcd.compile_for_rulebook = &(phud->owning_rulebook);
 
-    if (Wordings::nonempty(phud->rule_parameter)) Parse what used to be the bud into the PHRCD20.1.1;
+    if (Wordings::nonempty(phud->rule_parameter)) Parse what used to be the bud into the PHRCD19.1.1;
 
     if (Wordings::nonempty(phud->whenwhile)) {
         phrcd.activity_context =
@@ -877,11 +871,11 @@ seen problems in Inform. A couple of variables are needed just for that:
     if (phud->during_scene_spec) phrcd.during_scene = phud->during_scene_spec;
     #endif
 
- -

§20.1.1. ...except for this: +

+

§19.1.1. ...except for this:

-

Parse what used to be the bud into the PHRCD20.1.1 = +

Parse what used to be the bud into the PHRCD19.1.1 =

@@ -896,7 +890,7 @@ seen problems in Inform. A couple of variables are needed just for that:
         ParseActionPatterns::restore_mode(saved);
 
         if (phrcd.ap == NULL)
-            Issue a problem message for a bad action20.1.1.1;
+            Issue a problem message for a bad action19.1.1.1;
     } else {
         kind *pk = Rulebooks::get_focus_kind(phud->owning_rulebook);
         phrcd.ap = ActionPatterns::parse_parametric(phud->rule_parameter, pk);
@@ -910,16 +904,16 @@ seen problems in Inform. A couple of variables are needed just for that:
                 }
             }
         }
-        if (phrcd.ap == NULL) Issue a problem message for a bad parameter20.1.1.2;
+        if (phrcd.ap == NULL) Issue a problem message for a bad parameter19.1.1.2;
     }
     #endif
     #ifndef IF_MODULE
     kind *pk = Rulebooks::get_focus_kind(phud->owning_rulebook);
-    Issue a problem message for a bad parameter20.1.1.2;
+    Issue a problem message for a bad parameter19.1.1.2;
     #endif
 
- -

§20.1.1.1. All that's left is to issue a "good" problem message, but this is quite +

+

§19.1.1.1. All that's left is to issue a "good" problem message, but this is quite a large undertaking, because the situation as we currently know it is just that something's wrong with the rule preamble — which covers an enormous range of different faults. @@ -929,26 +923,26 @@ range of different faults. parser, recording how it most recently failed.

-

Issue a problem message for a bad action20.1.1.1 = +

Issue a problem message for a bad action19.1.1.1 =

-    Phrases::Usage::log(phud);
+    Phrases::Usage::log(phud);
     LOG("Bad action pattern: %W = $A\nPAP failure reason: %d\n",
         phud->rule_parameter, phrcd.ap, pap_failure_reason);
     Problems::quote_source(1, current_sentence);
     Problems::quote_wording(2, phud->rule_parameter);
     if (<action-problem-diagnosis>(phud->rule_parameter) == FALSE)
         switch(pap_failure_reason) {
-            case MIXEDNOUNS_PAPF: Issue PM_APWithDisjunction problem20.1.1.1.1; break;
-            case NOPARTICIPLE_PAPF: Issue PM_APWithNoParticiple problem20.1.1.1.2; break;
-            case IMMISCIBLE_PAPF: Issue PM_APWithImmiscible problem20.1.1.1.3; break;
-            case WHEN_PAPF: Issue PM_APWithBadWhen problem20.1.1.1.4; break;
-            default: Issue PM_APUnknown problem20.1.1.1.5; break;
+            case MIXEDNOUNS_PAPF: Issue PM_APWithDisjunction problem19.1.1.1.1; break;
+            case NOPARTICIPLE_PAPF: Issue PM_APWithNoParticiple problem19.1.1.1.2; break;
+            case IMMISCIBLE_PAPF: Issue PM_APWithImmiscible problem19.1.1.1.3; break;
+            case WHEN_PAPF: Issue PM_APWithBadWhen problem19.1.1.1.4; break;
+            default: Issue PM_APUnknown problem19.1.1.1.5; break;
         }
 
- -

§20.1.1.1.1. Issue PM_APWithDisjunction problem20.1.1.1.1 = +

+

§19.1.1.1.1. Issue PM_APWithDisjunction problem19.1.1.1.1 =

@@ -966,8 +960,8 @@ parser, recording how it most recently failed.
         "write more than one rule.");
     Problems::issue_problem_end();
 
- -

§20.1.1.1.2. Issue PM_APWithNoParticiple problem20.1.1.1.2 = +

+

§19.1.1.1.2. Issue PM_APWithNoParticiple problem19.1.1.1.2 =

@@ -980,8 +974,8 @@ parser, recording how it most recently failed.
         "badly misunderstood what you intended.");
     Problems::issue_problem_end();
 
- -

§20.1.1.1.3. Issue PM_APWithImmiscible problem20.1.1.1.3 = +

+

§19.1.1.1.3. Issue PM_APWithImmiscible problem19.1.1.1.3 =

@@ -997,8 +991,8 @@ parser, recording how it most recently failed.
         "would make different use of objects from each other.)");
     Problems::issue_problem_end();
 
- -

§20.1.1.1.4. Issue PM_APWithBadWhen problem20.1.1.1.4 = +

+

§19.1.1.1.4. Issue PM_APWithBadWhen problem19.1.1.1.4 =

@@ -1036,8 +1030,8 @@ parser, recording how it most recently failed.
             "location'; but the same thing with '...and when Peter is...' is not allowed.");
     Problems::issue_problem_end();
 
- -

§20.1.1.1.5. Issue PM_APUnknown problem20.1.1.1.5 = +

+

§19.1.1.1.5. Issue PM_APUnknown problem19.1.1.1.5 =

@@ -1050,15 +1044,15 @@ parser, recording how it most recently failed.
     Problems::issue_problem_segment(
         "You wrote %1, which seems to introduce a rule taking effect only if the "
         "action is '%2'. %3 did not make sense as a description of an action.");
-    See if it starts with a valid action name, at least20.1.1.1.5.1;
-    See if this might be a when-for confusion20.1.1.1.5.2;
-    Break down the action list and say which are okay20.1.1.1.5.3;
+    See if it starts with a valid action name, at least19.1.1.1.5.1;
+    See if this might be a when-for confusion19.1.1.1.5.2;
+    Break down the action list and say which are okay19.1.1.1.5.3;
     Problems::issue_problem_segment(
         " I am unable to place this rule into any rulebook.");
     Problems::issue_problem_end();
 
- -

§20.1.1.1.5.1. See if it starts with a valid action name, at least20.1.1.1.5.1 = +

+

§19.1.1.1.5.1. See if it starts with a valid action name, at least19.1.1.1.5.1 =

@@ -1074,8 +1068,8 @@ parser, recording how it most recently failed.
             break;
         }
 
- -

§20.1.1.1.5.2. See if this might be a when-for confusion20.1.1.1.5.2 = +

+

§19.1.1.1.5.2. See if this might be a when-for confusion19.1.1.1.5.2 =

@@ -1090,8 +1084,8 @@ parser, recording how it most recently failed.
         }
     }
 
- -

§20.1.1.1.5.3. If the action pattern contains what looks like a list of action names, as +

+

§19.1.1.1.5.3. If the action pattern contains what looks like a list of action names, as for example

@@ -1104,7 +1098,7 @@ apparent number of action names. We then run the grammar again, but this time allowing it to print comments on each apparent action name it sees.

-

Break down the action list and say which are okay20.1.1.1.5.3 = +

Break down the action list and say which are okay19.1.1.1.5.3 =

@@ -1125,37 +1119,37 @@ allowing it to print comments on each apparent action name it sees.
         Problems::issue_problem_segment(" so");
     }
 
- -

§20.1.1.2. We have a much easier time if the rulebook was value-focused, so that +

+

§19.1.1.2. We have a much easier time if the rulebook was value-focused, so that the only possible problem is that the value was wrong.

-

Issue a problem message for a bad parameter20.1.1.2 = +

Issue a problem message for a bad parameter19.1.1.2 =

-    Phrases::Usage::log(phud);
+    Phrases::Usage::log(phud);
     Problems::quote_source(1, current_sentence);
     Problems::quote_wording(2, phud->rule_parameter);
     Problems::quote_kind(3, pk);
     <parametric-problem-diagnosis>(phud->rule_preamble);
 
- -

§21. And that is the end of the code as such, but we still have to define the +

+

§20. And that is the end of the code as such, but we still have to define the three diagnosis grammars we needed.

-

§22. Parametric rules are those applying to values not actions, and the following +

§21. Parametric rules are those applying to values not actions, and the following is used to choose a problem message if the value makes no sense.

 <parametric-problem-diagnosis> ::=
-    when the play begins/ends |    ==> Issue PM_WhenThePlay problem22.1
-    ...                                 ==> Issue PM_BadParameter problem22.2
+    when the play begins/ends |    ==> Issue PM_WhenThePlay problem21.1
+    ...                                 ==> Issue PM_BadParameter problem21.2
 
-

§22.1. Issue PM_WhenThePlay problem22.1 = +

§21.1. Issue PM_WhenThePlay problem21.1 =

@@ -1165,8 +1159,8 @@ is used to choose a problem message if the value makes no sense.
         "special rulebooks, 'When play begins' and 'When play ends', "
         "and I think you probably mean to refer to one of those.");
 
- -

§22.2. Issue PM_BadParameter problem22.2 = +

+

§21.2. Issue PM_BadParameter problem21.2 =

@@ -1177,18 +1171,18 @@ is used to choose a problem message if the value makes no sense.
         "that should have described %3.");
     Problems::issue_problem_end();
 
- -

§23. And here we choose a problem message if a rule applying to an action is used, +

+

§22. And here we choose a problem message if a rule applying to an action is used, but the action isn't one we recognise.

 <action-problem-diagnosis> ::=
-    in the presence of ... |    ==> Issue PM_NonActionInPresenceOf problem23.1
-    in ...                          ==> Issue PM_NonActionIn problem23.2
+    in the presence of ... |    ==> Issue PM_NonActionInPresenceOf problem22.1
+    in ...                          ==> Issue PM_NonActionIn problem22.2
 
-

§23.1. Issue PM_NonActionInPresenceOf problem23.1 = +

§22.1. Issue PM_NonActionInPresenceOf problem22.1 =

@@ -1205,8 +1199,8 @@ but the action isn't one we recognise.
         "see...'.");
     Problems::issue_problem_end();
 
- -

§23.2. Issue PM_NonActionIn problem23.2 = +

+

§22.2. Issue PM_NonActionIn problem22.2 =

@@ -1219,8 +1213,8 @@ but the action isn't one we recognise.
         "when in the Library'.");
     Problems::issue_problem_end();
 
- -

§24. The following is used to choose a problem when the trouble with the rule +

+

§23. The following is used to choose a problem when the trouble with the rule occurred in a when/while condition at the end; while all five cases produce the PM_APWithBadWhen problem, they each provide different clues as to what might have gone wrong. @@ -1235,7 +1229,7 @@ might have gone wrong. ... {when/while ...} ==> { 5, -, <<cw1>> = Wordings::first_wn(WR[2]), <<cw2>> = Wordings::last_wn(WR[2]) }

-

§25.

+

§24.

 <anl-diagnosis> ::=
@@ -1251,10 +1245,10 @@ might have gone wrong.
     _,/or <anl-inner-diagnosis>                   ==> { pass 1 }
 
 <anl-entry-diagnosis> ::=
-    ......                                          ==> Diagnose problem with this ANL entry25.1
+    ......                                          ==> Diagnose problem with this ANL entry24.1
 
-

§25.1. Diagnose problem with this ANL entry25.1 = +

§24.1. Diagnose problem with this ANL entry24.1 =

@@ -1302,7 +1296,7 @@ might have gone wrong.
     }
     ==> { 1, - };
 
- + diff --git a/docs/imperative-module/3-tp.html b/docs/imperative-module/3-tp.html index 49fd73cc4..da5b73f3c 100644 --- a/docs/imperative-module/3-tp.html +++ b/docs/imperative-module/3-tp.html @@ -103,7 +103,7 @@ defined as "At 9:00 AM: ..." But two values are special: int when_count = 0; phrase *ph; LOOP_OVER(ph, phrase) { - int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); + int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NOT_A_TIMED_EVENT) continue; if (t == NO_FIXED_TIME) when_count++; else Emit::array_iname_entry(Phrases::iname(ph)); @@ -123,7 +123,7 @@ defined as "At 9:00 AM: ..." But two values are special: int when_count = 0; phrase *ph; LOOP_OVER(ph, phrase) { - int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); + int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data)); if (t == NOT_A_TIMED_EVENT) continue; if (t == NO_FIXED_TIME) when_count++; else Emit::array_numeric_entry((inter_ti) t); @@ -142,7 +142,7 @@ defined as "At 9:00 AM: ..." But two values are special:
 void Phrases::Timed::note_usage(phrase *ph, parse_node *at) {
-    int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+    int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
     if (t == NO_FIXED_TIME) {
         use_as_event *uae = CREATE(use_as_event);
         uae->where_triggered = at;
@@ -164,7 +164,7 @@ arguably shouldn't block compilation. Then again...
 void Phrases::Timed::check_for_unused(void) {
     phrase *ph;
     LOOP_OVER(ph, phrase)
-        if (Phrases::Usage::get_timing_of_event(&(ph->usage_data)) == NO_FIXED_TIME) {
+        if (Phrases::Usage::get_timing_of_event(&(ph->usage_data)) == NO_FIXED_TIME) {
             if (ph->usage_data.uses_as_event == NULL) {
                 current_sentence = ph->declaration_node;
                 StandardProblems::sentence_problem(Task::syntax_tree(), _p_(PM_UnusedTimedEvent),
@@ -195,7 +195,7 @@ arguably shouldn't block compilation. Then again...
 
     phrase *ph;
     LOOP_OVER(ph, phrase) {
-        int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+        int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
         if (t == NO_FIXED_TIME) {
             if (when_count == 0) {
                 HTML_OPEN("p");
@@ -204,7 +204,7 @@ arguably shouldn't block compilation. Then again...
             }
             when_count++;
             HTML_OPEN_WITH("p", "class=\"tightin2\"");
-            Phrases::Usage::index_preamble(OUT, &(ph->usage_data));
+            Phrases::Usage::index_preamble(OUT, &(ph->usage_data));
             if ((ph->declaration_node) &&
                 (Wordings::nonempty(Node::get_text(ph->declaration_node))))
                 Index::link(OUT, Wordings::first_wn(Node::get_text(ph->declaration_node)));
@@ -224,7 +224,7 @@ arguably shouldn't block compilation. Then again...
 
     phrase *ph;
     LOOP_OVER(ph, phrase) {
-        int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
+        int t = Phrases::Usage::get_timing_of_event(&(ph->usage_data));
         if (t >= 0) {  i.e., an actual time of day in minutes since midnight
             if (tt_count == 0) {
                 HTML_OPEN("p");
@@ -233,7 +233,7 @@ arguably shouldn't block compilation. Then again...
             }
             tt_count++;
             HTML_OPEN_WITH("p", "class=\"in2\"");
-            Phrases::Usage::index_preamble(OUT, &(ph->usage_data));
+            Phrases::Usage::index_preamble(OUT, &(ph->usage_data));
             if ((ph->declaration_node) &&
                 (Wordings::nonempty(Node::get_text(ph->declaration_node))))
                 Index::link(OUT, Wordings::first_wn(Node::get_text(ph->declaration_node)));
diff --git a/docs/imperative-module/4-sf.html b/docs/imperative-module/4-sf.html
index cdc0c7373..cc6115c02 100644
--- a/docs/imperative-module/4-sf.html
+++ b/docs/imperative-module/4-sf.html
@@ -159,7 +159,7 @@ wants to compile an I6 routine for some purpose other than to define a phrase.
     return &nonphrasal_stack_frame;
 }
 
-void Frames::remove_nonphrase_stack_frame(void) {
+void Frames::remove_nonphrase_stack_frame(void) {
     nonphrasal_stack_frame = Frames::new();  to prevent accidental lucky misuse
     nonphrasal_stack_frame_is_current = FALSE;
     Frames::remove_current();
@@ -187,7 +187,7 @@ if that's active, and otherwise must be set as needed.
 
 ph_stack_frame *current_frame = NULL;
 
-ph_stack_frame *Frames::current_stack_frame(void) {
+ph_stack_frame *Frames::current_stack_frame(void) {
     return current_frame;
 }
 
@@ -242,7 +242,7 @@ if that's active, and otherwise must be set as needed.
 

§10. Stacked variables.

-void Frames::set_stvol(ph_stack_frame *phsf, stacked_variable_owner_list *stvol) {
+void Frames::set_stvol(ph_stack_frame *phsf, stacked_variable_owner_list *stvol) {
     phsf->local_stvol = stvol;
 }
 
diff --git a/docs/imperative-module/6-cp.html b/docs/imperative-module/6-cp.html
index d7c53287e..7efcc3278 100644
--- a/docs/imperative-module/6-cp.html
+++ b/docs/imperative-module/6-cp.html
@@ -131,7 +131,7 @@ should always be supplied for "To..." phrases, but left null for rules.
 
 
     Routines::ToPhrases::comment_on_request(req);
-    Phrases::Usage::write_I6_comment_describing(&(ph->usage_data));
+    Phrases::Usage::write_I6_comment_describing(&(ph->usage_data));
 
  • This code is used in §2.

§2.2. Set up the stack frame for this compilation request2.2 = @@ -432,7 +432,7 @@ henceforth to be true, so we simply compile empty code in that case. current_sentence = to_compile; named_rulebook_outcome *nrbo = <<rp>>; if (phrase_being_compiled) { - int ram = Phrases::Usage::get_effect(&(phrase_being_compiled->usage_data)); + int ram = Phrases::Usage::get_effect(&(phrase_being_compiled->usage_data)); if ((ram != RULE_IN_RULEBOOK_EFF) && (ram != RULE_NOT_IN_RULEBOOK_EFF)) { Problems::quote_source(1, current_sentence); diff --git a/inform7/Figures/timings-diagnostics.txt b/inform7/Figures/timings-diagnostics.txt index 912f676a5..34b555b32 100644 --- a/inform7/Figures/timings-diagnostics.txt +++ b/inform7/Figures/timings-diagnostics.txt @@ -1,34 +1,37 @@ 100.0% in inform7 run - 67.1% in compilation to Inter - 25.5% in //Phrases::Manager::compile_first_block// + 66.2% in compilation to Inter + 25.8% in //Phrases::Manager::compile_first_block// 8.6% in //Phrases::Manager::compile_as_needed// - 6.9% in //Strings::compile_responses// - 6.3% in //InferenceSubjects::emit_all// - 4.1% in //MajorNodes::pre_pass// - 3.3% in //MajorNodes::pass_1// - 2.0% in //Phrases::Manager::RulePrintingRule_routine// - 1.8% in //Phrases::Manager::rulebooks_array// - 0.9% in //Phrases::Manager::traverse// - 0.9% in //RTVerbs::ConjugateVerb// + 7.0% in //Strings::compile_responses// + 5.9% in //InferenceSubjects::emit_all// + 3.8% in //MajorNodes::pre_pass// + 3.1% in //MajorNodes::pass_1// + 1.9% in //Phrases::Manager::RulePrintingRule_routine// + 1.9% in //Phrases::Manager::rulebooks_array// + 1.0% in //RTVerbs::ConjugateVerb// + 0.8% in //Phrases::Manager::traverse// + 0.5% in //World::stage_V// 0.3% in //MajorNodes::pass_2// 0.3% in //Phrases::Manager::compile_rulebooks// 0.3% in //Phrases::Manager::parse_rule_parameters// 0.3% in //RTRelations::compile_defined_relations// - 0.3% in //World::stage_V// + 0.1% in //RTCommandGrammars::compile_all// 0.1% in //RTKinds::compile_data_type_support_routines// 0.1% in //Task::make_built_in_kind_constructors// - 4.0% not specifically accounted for - 30.6% in running Inter pipeline - 10.1% in step preparation - 9.7% in inter step 2/12: link - 7.1% in inter step 12/12: generate inform6 -> auto.inf + 0.1% in //World::stages_II_and_III// + 3.3% not specifically accounted for + 31.4% in running Inter pipeline + 10.7% in step preparation + 10.1% in inter step 2/12: link + 7.0% in inter step 12/12: generate inform6 -> auto.inf + 0.3% in inter step 6/12: assimilate 0.3% in inter step 9/12: make-identifiers-unique 0.1% in inter step 10/12: reconcile-verbs 0.1% in inter step 11/12: eliminate-redundant-labels + 0.1% in inter step 4/12: parse-linked-matter 0.1% in inter step 5/12: resolve-conditional-compilation - 0.1% in inter step 6/12: assimilate 0.1% in inter step 7/12: resolve-external-symbols 0.1% in inter step 8/12: inspect-plugs - 2.1% not specifically accounted for - 2.0% in supervisor - 0.2% not specifically accounted for + 1.7% not specifically accounted for + 1.9% in supervisor + 0.4% not specifically accounted for diff --git a/inform7/imperative-module/Chapter 2/Rulebooks.w b/inform7/imperative-module/Chapter 2/Rulebooks.w index aaf893205..5080af646 100644 --- a/inform7/imperative-module/Chapter 2/Rulebooks.w +++ b/inform7/imperative-module/Chapter 2/Rulebooks.w @@ -469,139 +469,160 @@ void Rulebooks::detach_rule(rulebook *B, rule *R) { BookingLists::remove(B->contents, R); } -@h Name parsing of rulebooks. -The following internal finds the "stem" of a rule, that is, the part -which identifies which rulebook it will go into. For example, in +@h Rule stems. +The voracious nonterminal finds the "stem" of a rule, that is, +the part which identifies which rulebook it will go into. For example, in; >> Before printing the name of the peach: ... >> Instead of eating: ... -the stems are "before printing the name" and "instead". It makes use -of below, and then does some direct parsing. +the stems are "before printing the name" and "instead". + +The results are, however, too complicated to return from ; since +it is not used recursively, we store the results in |parsed_rm| on success. = typedef struct rulebook_match { struct rulebook *matched_rulebook; - int match_from; - int match_length; - int advance_words; - int tail_words; - struct article *article_used; - int placement_requested; + int match_from; /* first word of matched text */ + int match_length; /* number of words in matched text */ + int advance_words; /* how far the nonterminal should advance */ + int tail_words; /* for rulebook names split by scene start or end */ + struct article *article_used; /* or |NULL| if none was */ + int placement_requested; /* one of the |*_PLACEMENT| values */ } rulebook_match; +rulebook_match parsed_rm; +int parsed_scene_stem_len = 0; +rulebook *parsed_scene_stem_B = NULL; + @ = internal ? { - rulebook_match rm = Rulebooks::rb_match_from_description(W); - if (rm.matched_rulebook == NULL) { ==> { fail nonterminal }; } - parsed_rm = rm; - return Wordings::first_wn(W) + rm.advance_words - 1; + int initial_w1 = Wordings::first_wn(W); + parsed_scene_stem_len = 0; + parsed_scene_stem_B = NULL; + if ((W)) { + W = GET_RW(, 1); + int modifier_words = Wordings::first_wn(W) - initial_w1; + article_usage *au = (article_usage *) <>; + int pl = <>; + rulebook_match rm; + rm.match_length = 0; + rm.advance_words = 0; + rm.tail_words = 0; + rm.matched_rulebook = NULL; + if (Rulebooks::rb_match_from_description(W, parsed_scene_stem_B, + parsed_scene_stem_len, &rm)) { + parsed_rm = rm; + parsed_rm.match_length += modifier_words; + parsed_rm.advance_words += modifier_words; + parsed_rm.match_from = initial_w1; + parsed_rm.article_used = (au)?(au->article_used):NULL; + parsed_rm.placement_requested = pl; + return initial_w1 + parsed_rm.advance_words - 1; + } + } + ==> { fail nonterminal }; } @ Suppose this is our rule: >> The first rule for printing the name of something: ... -the following grammar peels away the easier-to-read indications at the -front. It notes the use of "The", and the placement "first"; it throws -away other verbiage so that matches - ->> printing the name of something - - then takes over again and searches for the longest possible -rulebook name at the start of the stem. So if there were a rulebook called -"printing", it wouldn't match here, because "printing the name" is longer. -( doesn't match the "of".) - -Productions (a) and (b) of are slightly hacky exceptions -to allow for the "when S begins" rulebooks, where S can be any description -of a scene rather than just a scene's name. In effect, the stem here consists -of the two outer words and is discontiguous. +the following grammar peels away the easier-to-read indications at the front. It +notes the use of "The", and the placement "first"; it throws away other verbiage so +that matches "printing the name of something". = ::= - | ==> { R[2], RP[1] } - | ==> { R[2], RP[1] } - ==> { R[1], NULL } + | ==> { R[2], RP[1] } + | ==> { R[2], RP[1] } + ==> { R[1], NULL } ::= - rule for/about/on | ==> { MIDDLE_PLACEMENT, -, <> = R[1] } - rule | ==> { MIDDLE_PLACEMENT, -, <> = R[1] } - first rule | ==> { FIRST_PLACEMENT, -, <> = R[1] } - first | ==> { FIRST_PLACEMENT, -, <> = R[1] } - last rule | ==> { LAST_PLACEMENT, -, <> = R[1] } - last | ==> { LAST_PLACEMENT, -, <> = R[1] } - ==> { MIDDLE_PLACEMENT, -, <> = R[1] } + rule for/about/on | ==> { MIDDLE_PLACEMENT, - } + rule | ==> { MIDDLE_PLACEMENT, - } + first rule | ==> { FIRST_PLACEMENT, - } + first | ==> { FIRST_PLACEMENT, - } + last rule | ==> { LAST_PLACEMENT, - } + last | ==> { LAST_PLACEMENT, - } + ==> { MIDDLE_PLACEMENT, - } ::= - {when ... begins} | ==> { 2, -, <> = Rulebooks::std(WHEN_SCENE_BEGINS_RB) } - {when ... ends} | ==> { 2, -, <> = Rulebooks::std(WHEN_SCENE_ENDS_RB) } - ... ==> { 0, -, <> = NULL } + {when ... begins} | ==> @ + {when ... ends} | ==> @ + ... ==> { -, - } -@ = -rulebook_match Rulebooks::rb_match_from_description(wording W) { - int initial_w1 = Wordings::first_wn(W), modifier_words; - int pl = MIDDLE_PLACEMENT; - rulebook *rb; - rulebook_match rm; +@ = + parsed_scene_stem_B = Rulebooks::std(WHEN_SCENE_BEGINS_RB); + parsed_scene_stem_len = 2; + ==> { -, - }; - (W); - W = GET_RW(, 1); - article_usage *au = (article_usage *) <>; pl = <>; +@ = + parsed_scene_stem_B = Rulebooks::std(WHEN_SCENE_ENDS_RB); + parsed_scene_stem_len = 2; + ==> { -, - }; - modifier_words = Wordings::first_wn(W) - initial_w1; +@ In this function, |SB| will be set for the hacky exceptional case where it's +known that the remaining text matches "when ... begins/ends", one of the scenes +rulebooks. This is all a bit inelegant, but we manage. - rm.match_length = 0; - rm.advance_words = 0; - rm.match_from = initial_w1; - rm.tail_words = 0; - rm.matched_rulebook = NULL; - rm.article_used = (au)?(au->article_used):NULL; - rm.placement_requested = pl; += +int Rulebooks::rb_match_from_description(wording W, rulebook *SB, int len, rulebook_match *rm) { + @; + if (rm->matched_rulebook == NULL) return FALSE; - LOOP_OVER(rb, rulebook) { + rm->advance_words = rm->match_length; + if (rm->matched_rulebook == SB) { + rm->tail_words = 1; + rm->match_length = 1; + } - if (rb == <>) { - if (rm.match_length < <>) { - rm.match_length = <>; - rm.matched_rulebook = rb; + @; + return TRUE; +} + +@ = + rulebook *B; + LOOP_OVER(B, rulebook) { + if (B == SB) { /* matches one of the scene begins/ends exceptions */ + if (rm->match_length < len) { + rm->match_length = len; + rm->matched_rulebook = B; } - } else { - if (Wordings::starts_with(W, rb->primary_name)) { - if (rm.match_length < Wordings::length(rb->primary_name)) { - rm.match_length = Wordings::length(rb->primary_name); - rm.matched_rulebook = rb; + } else { /* any other rulebook */ + if (Wordings::starts_with(W, B->primary_name)) { + if (rm->match_length < Wordings::length(B->primary_name)) { + rm->match_length = Wordings::length(B->primary_name); + rm->matched_rulebook = B; } - } else if (Wordings::starts_with(W, rb->alternative_name)) { - if (rm.match_length < Wordings::length(rb->alternative_name)) { - rm.match_length = Wordings::length(rb->alternative_name); - rm.matched_rulebook = rb; + } else if (Wordings::starts_with(W, B->alternative_name)) { + if (rm->match_length < Wordings::length(B->alternative_name)) { + rm->match_length = Wordings::length(B->alternative_name); + rm->matched_rulebook = B; } } } - } - if (rm.match_length == 0) return rm; +@ |action_stem_length| is zero except for rulebooks derived from actions, such +as "check taking". It is by definition the difference in length between the +rulebook name and the action name -- here, therefore, it's 2 - 1 = 1. - rm.advance_words = rm.match_length; +If the entire text |W| is the rulebook name -- in this case, "check taking" -- +we match that as normal. But if there is more text -- say, "check taking an +open container" -- then we retreat slightly and match only the prefix "check". +This ensures that something like "check taking or dropping something" is +initially, at least, put into the general check rulebook and not the specific +one for taking, where the "or dropping" part would never have effect. - if (rm.matched_rulebook == <>) { - rm.tail_words = 1; - rm.match_length = 1; - } - - if (rm.matched_rulebook->action_stem_length) { - int w1a = Wordings::first_wn(W) + rm.match_length - 1; +@ = + if (rm->matched_rulebook->action_stem_length > 0) { + int w1a = Wordings::first_wn(W) + rm->match_length - 1; if (w1a != Wordings::last_wn(W)) - rm.match_length = rm.matched_rulebook->action_stem_length; + rm->match_length = rm->matched_rulebook->action_stem_length; } - rm.match_length += modifier_words; - rm.advance_words += modifier_words; - return rm; -} - @h Standard rulebooks. A few rulebooks are special to Inform, in that they have built-in support either from the compiler, or from one of the kits, or both. The list below looks long, diff --git a/inform7/imperative-module/Chapter 3/Phrase Usage.w b/inform7/imperative-module/Chapter 3/Phrase Usage.w index f1d868139..da63f5e35 100644 --- a/inform7/imperative-module/Chapter 3/Phrase Usage.w +++ b/inform7/imperative-module/Chapter 3/Phrase Usage.w @@ -33,11 +33,6 @@ typedef struct ph_usage_data { int owning_rulebook_placement; /* ...and with this placement value: see Rulebooks */ } ph_usage_data; -@ We will need to store values temporarily here while parsing: - -= (early code) -rulebook_match parsed_rm; - @h The mid-morning predeclarations. Recall that early in Inform's run, we make a coarse parsing of the preamble of each rule to look for a name: if we find it, we declare it as a rule;