Reading strings for a simple parser

Hello everybody. I'm a C++ learner and today I'm here because I would like to receive some help for a little programming problem. I want to write a really simple text game with a few commands. After reading some topics on the web I decided to read strings from input and to parse those strings to perform action.

I also decided to use a grammar to parse the strings the user enter in the program. For example if the user enter :
drink potion

My program will follow this grammar to understand if the sentence is valid :

Sentence :
Noun Verb

Noun
* these noun are just for example :
"potion"
"map"

Verb
* also verbs are just for example :
"drink"
"see"


So the program will start by looking for a verb (I decided to read every command as a : verb + noun and not as : noun + verb) and it will check if the inserted verb is available as a possible verb to use in the program, after, the program will do the same for the noun.

I tried to write a little version to understand the problem better but I can't understand how should I treat illogical input as : drink map. For my grammar this command is correct, but from a logical point of view you can't drink a map!!. So my question is about how should I check for such kind of illogical input ?? Is it possible ? I thought that after the check of the verb and the noun I could check create a vector of possible noun for a verb so that for a command as : drink map

I could do this :
1) check verb
2) check noun
3) call a function associated with that verb and check if the noun that follows the verb is in a vector wich contains logical nouns for that verb, if not, print an error message.

This may sound stupid but I don't know how to treat this kind of error. Can you help me ?? Thank ;).


Last edited on
This kind of project is terribly fun to work on, unfortunately language is full of nuance and while the patterns are clear there are many exceptions to the rules. One of the reasons we have strictly defined rules in programming is to fill the gap between natural language and machine understanding- but those walls will break as you and I develop new levels of machine interaction.

When you program anything think about how you as a human would do it. How do you know that "drink map" is not a correct sentence? What synaptic patterns do you use to determine that? In this case drink map is entirely possible, but illogical because of experiences you have. As a little kid if you saw someone "drink" a map (with some visual illusion) you would immediately accept that as possible and move on with your life. A computer doesn't have that history to pull from, so you either have to establish iron clad patterns of reality (good luck) or you have to give it knowledge to make informed decisions.

If I were in your shoes, I would inform the user of the parser that the language must follow a very specific pattern (Adjective Subject Modifier Time Adverb Verb Adjective Object or something similar) then rely on that definition of language. Either don't worry about situations you can't currently handle or innovate.

I think its possible using struct or class for verb and noun
then add something like bool drinkable as a member for noun and verb
then check if the certain word have a same criteria
for example map.drinkable=false and drink.toExpressDrink=true, they are not match so you can output an error here
Last edited on
Given your intended use (to parse basic commands and perform actions based on them in a game) it pretty much makes sense. Though not as a general solution for handling natural text input.

If you're set of nouns for each verb is small, then you approach would be fine. But I think LendraDwi suggestion -- to add an attribute to the noun to work out if the verb can act on it (rather than giving each verb a list of nouns it can act on) -- also makes sense.

I would probably use a list of category names or IDs rather than a group of bool variables (drinkable, eatable, pickupable, ...) as you don't know how many of there you'll need. (IDs will take up less space.)

Andy

PS For a general solution you'd have to be able to handle the fact that words can have different functions. Even in your little example lists I can see three (out of four) words that can function as either noun or verb - drink, see, and map.
@andywestken I just started using classes and I got a new idea for the program, I would like to create a classefor verbs , then I would like to give to this classe two publics data member called name (wich indicates the name of the verb) and state (wich indicates something like : "drinkable" to indicate that this verb refers to a noun wich can be drinked). My problem is that I don't know how to create a vector of Verbs objects and initialize the data members of every elements of this vector. For example :

1
2
3
4
5
6
7
8
class Verb {
public : 
string name = "drink"; // name of the verb 
string state = "drinkable"; // the verb refers to a drinkable object 
}; 

vector<Verb> my_vector; // how can I initialize every elements of the vector now ? 


I would like to understand how to initialize every elements in the sense of initializing both the data members of my Verb objects......
Last edited on
how to create a vector of Verbs objects and initialize the data members of every elements of this vector.

Are you using a C++11 compliant compiler? If so, you can do it like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
#include <vector>
using namespace std;

class Verb {
public : 
    string name;  // name of the verb 
    string state; // the verb refers to a drinkable object 
}; 

int main() {
    // I've assume you're using a fixed set of verbs so made the vector const
    const vector<Verb> verbs = {
        { "drink", "potable"  }, // potable = safe to drink (see PS)
        { "eat"  , "edible"   },
        { "bend" , "pliable"  },
        { "carry", "portable" }
    };

    for(auto v : verbs) {
        cout << v.name << ", " << v.state << "\n";
    }

    return 0;
}


I would like to give to this classe two publics data member called name (wich indicates the name of the verb) and state

It would be better practice to enclose your class members (i.e. make them private) when you get you code properly up and running. Name probably just needs an accessor. But you might consider giving the verb class a method along the lines of canActOn(const Noun&) or canPerformActionOn(const Noun&).

And you need to find a better variable name than 'state', as 'drinkable' is not a state of the verb (as currently implied.)

Andy

PS Some people do use drinkable in the sense of potable -- "safe to drink" -- but it can also be used to mean "nice to drink -- e.g. "that Merlot was a very drinkable wine!".
http://www.quora.com/Where-do-the-word-potable-and-edible-come-from-and-why-dont-people-use-drinkable-and-eatable-instead
Drinkable is a word, but it means something different. It tends to mean "of adequate quality" but is sometimes used sarcastically to mean "absolutely fantastic". Thus, if I say "that wine is drinkable" I am not saying "it isn't poison" I am saying "it isn't bad".

Last edited on
Topic archived. No new replies allowed.