I don’t have one to share, but I did find some notes from several decades ago, which by happy coincidence, are about the basic steps for a parser that does verb, object, indirect object.
These notes - with some invent-on-the-fly-improvements - did result in a usable parser. I regret to say that I did not make any notes about those improvements.
Before reading the rest of this post, I recommend going to look at
Then come back and read the rest of this post.
Keep in mind that the central goal of a simple parser is to take the {verb}{noun} as typed by the player
and translate to [action][object]. IOW, you should define a Chompskian ‘deep language’ of actions upon objects to keep track of what is really happening. From that you determine what changes need to be made to the world.
Good luck. If you have any questions, feel free to post them here.
===================================================================
The player makes a request/command
The parser goal is to determine what changes that makes in the world - and on the screen.
The player may speak in terms of {verb}{noun}
The parser should translate to [action][object]
And then into changes.
The first pass of the parser resolves alphabetic strings into words
Those words are looked up in a dictionary.
Any misspellings or unknowns are clarified through conversation with the player.
Once a sequence of valid dictionary entries is obtained
The parser assigns a part of speech to each word.
Some such assignations may be uncertain.
These are noted as alternate entries in the part of speech data.
In the second pass, nouns and adjectives must be translated into objects.
This is done by ANDing arrays of bits.
This may involve some clarifying conversation with the player.
Eventually we reach the point in which all nouns and adjectives have been translated into unique objects.
Then a second part of speech pass is made to resolve alternates.
Example:
‘With’ can be turned into ‘using’, if the inventory bit array confirms that the player has the object.
Or it can be turned into ‘wearing’ or ‘carrying’ or ‘holding’ if another person has it.
The difference in how an object is possessed should be another field in a dictionary entry.
At this point all words should have parts of speech assigned,
And all nouns and adjectives have been resolved to unique objects.
Verbs ( and maybe indirect objects ) must be translated into actions.
Non-core verbs map N to 1 on to core verbs.
( example:‘hit’, ‘attack’, ‘strike’ all map to ‘attack’ )
Next we resolve the ID - if any - as a verb modifier.
Then we have the two indices into a 2D array of [verb]x[VM].
Each element in the array is an action.
Once we have a unique action and a unique direct object,
Then we use those as indices into a 2D array of [action]x[DO]
Each element of that array is a change (or a list of changes)
Each change is expressed as a new value of some variable, and/or some text written to the screen.
The execution of that change may depend the state of other variables.
If/then clauses are part of the content of a change.