Debugging Preform for Greek Noun Declensions (Preform)

Hello everyone,

I’m currently working on a Greek language extension for Inform 7. I’ve hit a roadblock while implementing noun declensions and was hoping someone might have some advice on how to get more diagnostic information from the compiler.

My specific goal is to get the parser to recognize the accusative case. For example, it should understand that “όλμο” (olmo) is the accusative form of the noun “όλμος” (olmos).

I’ve been studying the official documentation on inflections.

My understanding, especially from paragraph 50, is that the system matches a noun to a group number in <noun-declension-group>, and then applies the rule from the corresponding line in <noun-declension-tables>.

To isolate the problem, I’ve created a very simplified test case, but it still doesn’t work. When I define “Ο όλμος” as a thing, the parser fails to recognize it when I refer to it by its accusative form “όλμο”.

Here is my Preform code for this specific reason:

language Greek
<grammatical-case-names> ::=
    nominative | accusative

<noun-declension> ::=
    * <gr-noun-declension-group> <gr-noun-declension-tables>

<gr-noun-declension-group> ::=
    *ος     1 |  [Masculine ending in -os]
    *ας     2 |  [Masculine ending in -ας]
    *ης     3 |  [Masculine ending in -ης]
    * 		4    [Default]

<gr-noun-declension-tables> ::=
    <gr-declension-os> |
    <gr-declension-as> |
    <gr-declension-is> |
    <gr-declension-uninflected>

[Για -ος: π.χ. όλμος -> όλμο | όλμοι | όλμους]
<gr-declension-os> ::=
    0 | 2ο | 2οι | 2ους

[Για -ας: π.χ. άντρας -> άντρα | άντρες | άντρες]
<gr-declension-as> ::=
    0 | 2α | 2ες | 2ες

[Για -ης: π.χ. μαθητής -> μαθητή | μαθητές | μαθητές]
<gr-declension-is> ::=
    0 | 2ή | 2ές | 2ές

[Για άκλιτα]
<gr-declension-uninflected> ::=
    0 | 0 | 0 | 0

I’m also struggling to get any diagnostic output to see what the compiler is doing with these rules.

My main questions are:

  1. Looking at my code above, is there any other obvious logical or syntactical error that I might be overlooking?
  2. What is the recommended way to get a detailed trace or log of the Preform compilation process?

Any help or guidance would be hugely appreciated!

P.S. : You can take a look at my whole codebase for this extension, in case you need more information. But due to Unicode character issues, the only way to test the extension is by building the latest version of Inform 7 from scratch, and running it from the command-line.

3 Likes

I was waiting for people who understand the deep stuff better than me to chime in, but just to check: When you say “the parser fails to recognize it when I refer to it by its accusative form”, are you talking about the compiler’s parser (for your source code) or the generated game’s parser (for player commands)?

Thanks for your reply and for the clarifying question. I am not really experienced and sometimes I mix things up :sweat_smile:

To answer your question, the problem is with the generated game’s parser (for player commands).

The Inform 7 compiler successfully compiles the source code where I define the object (e.g., "Ο όλμος is a thing"). The failure happens at runtime, within the game itself. When the player enters a command using the accusative case (e.g., >εξέτασε τον όλμο), the game’s parser fails to understand that “τον όλμο” should refer to the “όλμος” object that was defined.

So, the Preform inflection rules, which are meant to teach the game’s parser about the different noun cases, don’t seem to be having the desired effect.

Thanks again for helping me narrow this down!

OK. So, as I understand it, Preform only affects the compiler’s ability to parse source code, and does not have much effect on any generated game’s parser. (The only way that it would that I can see is via automatic generation of plural names for objects of the same kind, and that doesn’t seem to apply here.)

I am not a grammar expert, but I will point you to the Inform Designer’s Manual, 4th edition, aka DM4, which has an example for handling accusative vs. dative forms in section 35 “Case and parsing noun phrases”. That’s for Inform 6, though, and you would need to do some tinkering with parser kit code in Inform 10 to make the information provided useful for your purposes.

EDIT: I’ll add that for the simplest handling of the problem, i.e. one that doesn’t actually try to enforce the correct noun case, you should just be able to add Understand "<accusative>" as <object name>. to get the game parser to recognize the word as applying to the object.

1 Like

Thank you a lot, I will try to figure it out!

Unfortunately, very few people here have used Preform. I’d be interested in seeing the solution to this, but I think the number of people with extensive Preform experience can be counted on one hand.

I haven’t looked into it too much, but I do believe that Preform mostly only affects how Inform understand the source code.

To make a game’s parser understand Greek cases or whatever, the “official” way is to use the Inform 6/Inter routine LanguageToInformese to convert a Greek command to a form that resemble the subset of English that the parser can understand (verb + object + preposition + object word order, no declension, this kind of thing). It’s explained in the DM4 as mentioned above.

1 Like

Following up on this with a question, to make sure that I’m not sending you on any unnecessary detours…

Are you able to use accusative and dative to refer to the same object in your source code? Since you don’t mention any problems with this, I’m assuming that there is no problem with this aspect. If you are able to refer to a single object using both dative and accusative forms, then it suggests to me that you are correctly using Preform to tell the compiler how to interpret your source code.

I am 100% positive (OK, 99.99%) that nothing you do in Preform would be able to make a game parser automatically understand the accusative and dative forms. The parsing algorithm gets what it needs to match user input to game objects from a combination of a .name property and/or a .parse_name() method for each object. This is why I’m saying that the only way Preform could affect parsing would be if it’s affecting automatic plural name generation – the compiler does append plural versions of words to the .name property of the relevant objects, and it seems reasonable (though I don’t know for sure) that Preform governs the translation from singular to plural.

(I guess there might be a feature to automatically apply additional forms to the .name property, but if so I’ve never heard of it. Might be worth a feature request, if it doesn’t exist.)

Part of the problem is that the game parser sees words at an atomic level; it doesn’t understand word pieces like suffixes or individual letters. (Though it can be told to compare a text property to a command word letter-by-letter.) The good news is that none of that really matters if all you want is for the game to understand the accusative form – you just need to tell it which words apply to which object. The bad news is that it’s a completely separate project using a totally different set of knowledge to modify the kit code, language definition and Standard Rules so that the game being generated can be played in Greek.

I don’t know Greek, and English doesn’t do noun cases that way, but I’ll try to explain as best as I can. Suppose your source code includes an object declaration:

A thingX is a thing. [supposed to be equivalent to your "Ο όλμος"]

Unless I’m misunderstanding, the “Ο” is an indefinite article and “όλμος” is the nominative case for the noun.

When the game is generated, an I6 object declaration similar to the following is created (this was generated by 9.3/6M62, but the same ideas apply to 10+):

Object I136_thingx ""
	class K2_thing
	with name 'thingx' 'things//p'	! the .name property: note that only the object name and a plural for the kind are included
	...
;

Where it says 'thingx', that’s not a string, that’s a dictionary word, an atomic piece of text for parsing commands. (You’ll have to read about the Z-machine and Glulx virtual machines to understand more about this.)

If you add to your source the following:

Understand "thingX-a" as thingX. [simulating an accusative form with -a suffix]

then the I6 declaration will change:

Object I136_thingx ""
	class K2_thing
	with name 'thingx' 'things//p' 'thingx-a'	! the accusative form has been added to the .name property of the object
	with parse_name Parse_Name_GV96				! a .parse_name() method has been attached, but it doesn't do anything of interest
	...
;

The parser will now allow either the accusative or nominative word to apply to the object:

>GET THINGX-A
Taken.

>DROP THINGX
Dropped.

>GET THINGX
Taken.

>PUT THINGX-A IN BUCKET
You put the thingX into the bucket.

The last command shows a potential problem. If I’m understanding correctly, you would ideally want the equivalent of You put the thingX-a into the bucket. as output. This is possible, but it would take new code written by you in your source. I don’t think you can leverage Preform at all, though obviously that would be powerful, and it certainly seems like something that could be implemented within the compiler in theory.

In the short run, if you’re interested in writing a game in which the language of play (as opposed to the language of source) is Greek, you can probably set up a system along the lines of:

pretending English is more like Greek
A thing has some text called accusative form.
A thing has some text called dative form.

[These are handy but make your game slower. They make the compiler generate a complicated I6 .parse_name() method that does letter-by-letter comparison.]
Understand the accusative form property as describing a thing.
Understand the dative form property as describing a thing.

A grammatical case is dative. [The grammatical case kind of value is already defined in English with two values: nominative and accusative.]

Current noun case is initially nominative.

Printing a noun case is an activity.

After printing a noun case:
	now current noun case is nominative.

To say (T - thing) in (C - grammatical case) :
	now current noun case is C;
	begin the printing a noun case activity;
	say T;
	end the printing a noun case activity.

To say the (T - thing) in (C - grammatical case) :
	now current noun case is C;
	begin the printing a noun case activity;
	say the T;
	end the printing a noun case activity.

To say a (T - thing) in (C - grammatical case) :
	now current noun case is C;
	begin the printing a noun case activity;
	say a T;
	end the printing a noun case activity.

For printing the name of something (called T) when current noun case is accusative:
	if T provides the property accusative form:
		unless the accusative form of T is empty:
			say accusative form of T;
			stop;
	say printed name of T.

For printing the name of something (called T) when current noun case is dative:
	if T provides the property dative form:
		unless the dative form of T is empty:
			say dative form of T;
			stop;
	say printed name of T.


[minimal demonstration scenario follows]
Place is a room.

[Declarations like this will allow X, X-a and X-d to refer to an object; the game parser won't care about correct usage.]
A tray is a supporter with accusative form "tray-a" and dative form "tray-d". It is here.

A bucket is a container with accusative form "bucket-a" and dative form "bucket-d". It is here.

A thingX is a thing with accusative form "thingX-a" and dative form "thingX-d". It is in the bucket.

[the default object name corresponds to the nominative case; does that work for you?]
When play begins:
	say "Nom: [thingX in nominative].";
	say "Acc: [thingX in accusative].";
	say "Dat: [thingX in dative].";

[You'll be translating all of these, anyway.]
The standard report inserting rule response (A) is "[The actor] [put] [the noun in accusative] into [the second noun in dative]."

The standard report putting rule response (A) is "[The actor] [put] [the noun in accusative] onto [the second noun in dative]."

Sample output:

Place
You can see a tray and a bucket (in which is a thingX) here.

>GET BUCKET-A [parser understands accusative form in command but is not actually checking for proper grammar]
Taken.

>PUT IT ON TRAY
You put the bucket-a onto the tray-d. [note accusative form for bucket in output]

>GET THINGX
Taken.

>PUT IT ON TRAY [parser doesn't care that player says TRAY instead of TRAY-D]
You put the thingX-a onto the tray-d. [... but does use the correct form in the response]

>PUT IT IN BUCKET
(first taking the thingX) [maybe this should be accusative? there are other responses to modify]
You put the thingX-a into the bucket-d. [note dative form for bucket]
1 Like

Thanks for following up on this.

To answer it directly: actually there was a problem with the source code aspect as well. I did initially try to make the different cases refer to the same object in the source, but I wasn’t successful.

My main focus has been on the game’s parser for player commands. The primary goal of the extension is to make the experience as beginner-friendly as possible, so that a new player doesn’t need to read documentation on linguistic limitations and can simply type commands naturally in Greek.

Side note about dative case

The dative case isn’t actually used in Modern Greek. It’s a feature of Ancient Greek, which is an extremely difficult language even for native speakers, so it’s very unlikely anyone would try to use Inform for it.

Your explanation of how the compiler handles dictionary words also sheds light on another difficulty I’ve faced. It can be time-consuming to debug the generated Inform 6 files, as a simple Greek word like “όλμος” is represented in the story file like this, which makes it hard to read at a glance:

'@{03cc}@{03bb}@{03bc}@{03bf}@{03c2}'

All that said, the system and the complete example you provided are fantastic! This gives me a clear path forward. I will definitely be working to incorporate these rules into the extension.

Thanks again for your amazing help!