Parsing a line ?

Started by
7 comments, last by nookiepl 21 years, 10 months ago
Hi i''m trying to make a console in my program, but im very lame on C++ for example we have line like this: set vid_mode 1 how to parse teh string that, first word is a command second, var, and the third one is value ?? and another example: say i''m lame How to make parsing code to work on both examples ? becouse teh first one is with spaces between every word, and in the second i want to rcognize function say, and the rest is teh string (with spaces) that it should display ?? Please help Thanks in advance Nookie
Nookienookie@net.is.pl
Advertisement
Well you are probably going to want to start with some form of a variable system. CVARs, in quake-talk. They need to contain the data and the variable name (as known by the console). Usually people use a linked list for this, but arrays of structs work too.

Next you oughta try parsing the commands. Tokenize it first (aka do a large switch command or something on the first word to find out the command, and then set some variable). Then if you find that the command is set, then read the first parameter, the variable name, and find what data they are refering to. Then read the last parameter, the value, and set the variable to it. If you want to be able to set variables to variables, you will have to repeat the variable search.

All the while make sure to have error checking (aka command existing, variable existing, valid value to set to). Not too difficult, really! The trick is making a good one...

L8r,
The Rainmaker
The script arcticle might help you too.
I know i''ll have to parse it, and search it in my cvars structure, the question is how to tokenize string, and parse it ??
Nookienookie@net.is.pl
You can use strchr to find spaces, and you might be able to make some sense of strtok, although I''ve never used it.
---visit #directxdev on afternet <- not just for directx, despite the name
Try something like this:

enum all_my_commands_e
{
COMMAND_SET=0,
// other commands...
};

int TokenizeCommand(char *command)
{
if(strcmp(command,"set")==0)
{
return COMMAND_SET;
} // else if for other commands
return -1; // errornous
}

char* GetCommand(char *input)
{
int i=0;
char *pChar=input;
char ret[256];
memset(ret,0,sizeof(char)*256);
while(pChar && pChar != '' '')
{
ret[i++] = pChar;
}
return ret;
}

void ParseString(char *input)
{
int command;
command = TokenizeCommand(GetCommand(input));
// ...
}

something like that. Not sure if that would work, but probably would.

L8r,
The Rainmaker
straight C++


  #include <sstream>#include <string>struct command{  std::string command;  std::string variable;  long l;};command parse( std::string& line ){  // create a stream for reading from the string  std::stringstream ss( line );  command com;  ss >> com.command >> com.variable >> com.l;  return com;}  


straight C


  #include <stdio.h>struct command{  std::string command;  std::string variable;  long l;};struct command parse( char* line ){  struct command com;  sscanf( line, "%s %s %d", &com.command, &com.variable, &com.l   return com);  


Using boost::tokenizer and boost::lexical_cast


  #include <vector>#include <string>#include <boost/tokenizer.hpp>typedef vector<std::string> command;command parse( std::string& line ){  boost::tokenizer tok( line );  return command( tok.begin(), tok.end() );};// com is now a vector of strings// you can access each word by simple indexing// and use boost::lexical_cast to convert to// numerical values. In your case :command com = parse( line );long l = boost::lexical_cast<long>( com[2] );// That way, each command can take whatever parameter// it wants.  





Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
And for boost::tokenizer to process quoted strings ("say"), here is my very own tokenizing function :


    #ifndef BOOST_MSVC	template <typename Char, 		typename Traits = typename std::basic_string<Char>::traits_type >#else	template <typename Char, 		typename Traits = std::basic_string<Char>::traits_type >#endif	class quoted_separator	{		typedef std::basic_string<Char,Traits> string_type;	public:		explicit quoted_separator() : m_quoted( false ) {};		inline bool is_quote( Char q ) { return q == '\"'; };		void reset() { m_quoted = false; }		template <typename InputIterator, typename Token>			bool operator()(InputIterator& next, InputIterator end, Token& tok)		{			tok = Token();			// skip past all dropped_delims			if (!m_quoted)				for (; next != end  && std::isspace(*next); ++next)				{ }				if (next == end)					return false;				else if( next!= end && is_quote(*next) )				{					m_quoted = !m_quoted;					++next;				}				if( m_quoted )					for(; next != end && !is_quote(*next); ++next )						tok += *next;				else					for(; next != end && !is_quote(*next) && !isspace(*next); ++next )						tok += *next;				if( next!= end && is_quote(*next) )				{					m_quoted = !m_quoted;					++next;				}				return true;		}	private:		bool m_quoted;	};    


which you just feed to boost::tokenizer as a template parameter.


  command parse( std::string& line ){  boost::tokenizer<quoted_separator<char> > tok ( line );  return command( tok.begin(), tok.end() );}  


Enjoy

Documents [ GDNet | MSDN | STL | OpenGL | Formats | RTFM | Asking Smart Questions ]
C++ Stuff [ MinGW | Loki | SDL | Boost. | STLport | FLTK | ACCU Recommended Books ]


[edited by - Fruny on June 9, 2002 6:42:25 PM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
I would prob. build a recursive descent parser.
Thoose are pretty fast/easy to code & work nice.
Once you get your grammar going it''s very easy to expand it.

The idea is that you have one functionA that "looks" for a "set"
inside functionA you look for "Vid_Mode"...inside function Vid_Mode you look for "Nummber" etc..etcc..
______________________________Only dead fish go with the main-stream.

This topic is closed to new replies.

Advertisement