Simple script parser - how to ?

Please support our C++ advertiser: Intel Parallel Studio Home
Reply

Join Date: Apr 2007
Posts: 12
Reputation: MaestroS is an unknown quantity at this point 
Solved Threads: 0
MaestroS MaestroS is offline Offline
Newbie Poster

Simple script parser - how to ?

 
0
  #1
Apr 28th, 2007
I really want to know WHERE I can find a simple example of parser for own script language for games.

I found one on gamedev.pl [polish site], but I can't stick together all parts of the code.

It'd be nice if someone can post a links to examples.

I mean about SIMPLE parsers (interpreters) to edit and re-build.

Thanks in advance!


#edit
If someone don't know.

I've file:
monster.mas

and it contents:
  1. setMonsterHP(10);
  2. setMonsterPos(10);

and this parser should just translate this code to be understoodable by game
Last edited by MaestroS; Apr 28th, 2007 at 12:51 pm.
Reply With Quote Quick reply to this message  
Join Date: May 2006
Posts: 1,580
Reputation: Infarction has a spectacular aura about Infarction has a spectacular aura about Infarction has a spectacular aura about 
Solved Threads: 52
Infarction's Avatar
Infarction Infarction is offline Offline
Battle Programmer

Re: Simple script parser - how to ?

 
0
  #2
Apr 28th, 2007
If you're reading in from a file, you can write an input method which expects the data to be formatted a certain way, and then parse it yourself by just reading in pieces at a time, as you need them.
Reply With Quote Quick reply to this message  
Join Date: Jun 2006
Posts: 7,600
Reputation: ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of 
Solved Threads: 462
Super Moderator
Featured Poster
~s.o.s~'s Avatar
~s.o.s~ ~s.o.s~ is offline Offline
Failure as a human

Re: Simple script parser - how to ?

 
0
  #3
Apr 28th, 2007
Though reinventing the wheel won't be such a good idea unless your aim here is to learn how to create custom parsers and not the game.
I don't accept change; I don't deserve to live.
Reply With Quote Quick reply to this message  
Join Date: May 2006
Posts: 1,580
Reputation: Infarction has a spectacular aura about Infarction has a spectacular aura about Infarction has a spectacular aura about 
Solved Threads: 52
Infarction's Avatar
Infarction Infarction is offline Offline
Battle Programmer

Re: Simple script parser - how to ?

 
0
  #4
Apr 28th, 2007
I'd think that if you kept a simple format, it wouldn't be that much more work. I could easily be wrong though, last time I did something like this was in high school like 5 years ago...
Last edited by Infarction; Apr 28th, 2007 at 3:12 pm.
Reply With Quote Quick reply to this message  
Join Date: Jun 2006
Posts: 7,600
Reputation: ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of ~s.o.s~ has much to be proud of 
Solved Threads: 462
Super Moderator
Featured Poster
~s.o.s~'s Avatar
~s.o.s~ ~s.o.s~ is offline Offline
Failure as a human

Re: Simple script parser - how to ?

 
0
  #5
Apr 28th, 2007
I don't accept change; I don't deserve to live.
Reply With Quote Quick reply to this message  
Join Date: Apr 2007
Posts: 12
Reputation: MaestroS is an unknown quantity at this point 
Solved Threads: 0
MaestroS MaestroS is offline Offline
Newbie Poster

Re: Simple script parser - how to ?

 
0
  #6
Apr 28th, 2007
All I know is that data must be readed from file.

For example:

File monster.mas:
  1. create monster 10 10 2

When the file is loaded, parser is checking each line and is interpreting it.

I got something like this:


Open file
  1. #include <cstdio>
  2. #include <string>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <vector>
  6.  
  7. using namespace std;
  8.  
  9. string bufor;
  10.  
  11. int main()
  12. {
  13. ifstream plik;
  14. plik.open("skrypt.txt");
  15. char c;
  16. while(true)
  17. {
  18. c = plik.get();
  19. if(plik.eof()) break;
  20. bufor += c;
  21. }
  22. plik.close();
  23. }


Definitions of global variables for tokens and parameters
  1. const char* WS_SET = " \t\r\n";
  2. const char* BR_SET = "\r\n";
  3.  
  4. #define NOT_FOUND string::npos
  5. #define POS_END string::npos
  6.  
  7. string bufor, cword, err_str;
  8. int pos = 0, param = 0;

This function is taking each command as token
  1. bool get_token()
  2. {
  3. int tmp_pos, tmp_pos2;
  4.  
  5. tmp_pos = bufor.find_first_not_of(WS_SET, pos);
  6. if(tmp_pos == NOT_FOUND)
  7. {
  8. cword.clear();
  9. pos = POS_END;
  10. return false;
  11. }
  12. tmp_pos2 = bufor.find_first_of(WS_SET, tmp_pos);
  13. if(tmp_pos2 == NOT_FOUND)
  14. {
  15. pos = bufor.length()-1;
  16. cword = bufor.substr(tmp_pos, bufor.length()-tmp_pos);
  17. }
  18. else
  19. {
  20. pos = tmp_pos2;
  21. cword = bufor.substr(tmp_pos, tmp_pos2-tmp_pos);
  22. }
  23. return true;
  24. }

Function that is taking parameter from each command
  1. bool get_param()
  2. {
  3. int tmp_pos, tmp_pos2;
  4. string s_number;
  5.  
  6. tmp_pos = bufor.find_first_not_of(WS_SET, pos);
  7. if(tmp_pos == NOT_FOUND)
  8. {
  9. param = 0;
  10. pos = POS_END;
  11. return false;
  12. }
  13. tmp_pos2 = bufor.find_first_of(WS_SET, tmp_pos);
  14. cword.clear();
  15. if(tmp_pos2 == NOT_FOUND)
  16. {
  17. tmp_pos2 = bufor.find_last_not_of(WS_SET, tmp_pos);
  18. if(tmp_pos2 == tmp_pos)
  19. {
  20. s_number = bufor[tmp_pos];
  21. }
  22. pos = tmp_pos2;
  23. }
  24. if(s_number.empty())
  25. {
  26. s_number = bufor.substr(tmp_pos, tmp_pos2-tmp_pos);
  27. pos = tmp_pos2;
  28. }
  29.  
  30. param = atoi(s_number.c_str());

Ignoring line for comments
  1. void ignore_line()
  2. {
  3. int tmp_pos;
  4. tmp_pos = bufor.find_first_of(BR_SET, pos);
  5. if(tmp_pos == NOT_FOUND)
  6. {
  7.  
  8. pos = POS_END;
  9. return;
  10. }
  11. tmp_pos = bufor.find_first_not_of(BR_SET, tmp_pos);
  12. if(tmp_pos == NOT_FOUND)
  13. {
  14. pos = POS_END;
  15. return;
  16. }
  17. pos = tmp_pos;
  18. }
  19. return true;
  20. }


Example of a parser code
  1. bool parse()
  2. {
  3. COMMAND_INFO cmd_info = { CMD_UNKNOWN }; // zaraz wyjaśnimy, co to jest ;-)
  4.  
  5. do
  6. {
  7. if(!get_token()) return true;
  8. if(cword.length() > 1)
  9. {
  10. if(cword.substr(0, 2) == "//") // komentarz - ignoruj resztę wiersza
  11. {
  12. ignore_line();
  13. continue;
  14. }
  15. }
  16.  
  17. // ***
  18. if(cword == "create_monster")
  19. {
  20. // ...
  21. if(!get_param()) return false; // taking first argument
  22. // ...
  23. if(!get_token()) //taking second argument
  24. {
  25. cout << "BŁĄD, spodziewałem się jakiegoś słowa..." << endl;
  26. return false;
  27. }
  28. // ...
  29. if(!get_param()) return false; // taking third argument
  30. // ...
  31. if(!get_param()) return false; // taking fourth argument
  32. // ...
  33. }
  34. else if(cword == "create_item")
  35. {
  36. // ...
  37. if(!get_param()) return false;
  38. // ...
  39. if(!get_param()) return false;
  40. // ...
  41. if(!get_param()) return false;
  42. // ...
  43. }
  44. else if(cword == "equip_monster")
  45. {
  46. // ...
  47. if(!get_token())
  48. {
  49. cout << "ERROR: a command expected..." << endl;
  50. return false;
  51. }
  52. // ...
  53. if(!get_param()) return false;
  54. // ...
  55. }
  56. else
  57. {
  58. cout << "Command not recognized: " << cword << endl;
  59. return false;
  60. }
  61. // ...
  62. // ***
  63.  
  64.  
  65. }
  66. while(pos < bufor.length()-1)
  67.  
  68. return true;
  69. }


But now, omg.... can someone stick it together to work functionally or re-build ... ? : /
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Simple script parser - how to ?

 
1
  #7
Apr 29th, 2007
if you are comfortable with c++ (ie. you can do more than write c code using c++ syntax), you would find the spirit recursive descent parser framework (part of the boost libraries) easy to use. internally, it uses template meta-programming techniques; but to use it productively, you just need to be familiar with mainstream c++ (primarily generic programming).

here is an example of parsing a text file:
file key_and_values.txt
------------------------------

phone_numbers = 1234, 5678 : 987,564:0:0
line 2 is a parse error
primes_2_to_19 = 2, 3, 5, 7, 11:13:17:19
primitive_pythagorian_triplet_1 = 8,15 : 7
line = 5 also an error
_12_34 = 1:2, 3:4
_daniweb_thread_numbers = 12345:56789:34567, 78901
primitive_pythagorian_triplet_2 = 9,12 : 15
adds_up_to_12 = -24 : +48 , -12


essentially it contains lines of the form
key = value, value : value.
keys have the same structure as valid c++ identifiers.
values are integers seperated by either a , or a :
white spaces are ignored.

here is a sample program that parses such a file:
  1. #include <boost/spirit/core.hpp>
  2. #include <boost/spirit/actor.hpp>
  3. #include <iostream>
  4. #include <fstream>
  5. #include <vector>
  6. #include <string>
  7. #include <algorithm>
  8. #include <iterator>
  9. using namespace std;
  10. using namespace boost::spirit;
  11.  
  12. bool parse_it( const char* cstr, string& key, vector<int>& values )
  13. {
  14. return parse( cstr,
  15. ( ( ( (alpha_p|'_') >> *(alnum_p|'_') )[ assign_a(key) ] ) >> ( '=' >>
  16. ( int_p[ push_back_a( values ) ] >> *( ( ch_p(',') | ':' ) >> int_p[ push_back_a( values ) ] ) ) ) ),
  17. space_p ).full ;
  18. }
  19.  
  20. int main()
  21. {
  22. const char* const file_name = "key_and_values.txt" ;
  23. ifstream file( file_name ) ;
  24. string str ;
  25. for( int line=1 ; getline( file, str ) ; ++line )
  26. {
  27. cout << "line " << line ;
  28. string key ; vector<int> values;
  29. if( parse_it( str.c_str(), key, values ) )
  30. {
  31. cout << "\nkey: " << key << "\nvalues: " ;
  32. copy( values.begin(), values.end(), ostream_iterator<int>(cout," ") ) ;
  33. cout << '\n' ;
  34. }
  35. else
  36. cout << " *parse error\n" ;
  37. cout << "-----------------------\n" ;
  38. }
  39. }
the parsing rule is inlined in lines 15 and 16; the rest is just boiler plate code.
here is the output:

line 1
key: phone_numbers
values: 1234 5678 987 564 0 0
-----------------------
line 2 *parse error
-----------------------
line 3
key: primes_2_to_19
values: 2 3 5 7 11 13 17 19
-----------------------
line 4
key: primitive_pythagorian_triplet_1
values: 8 15 7
-----------------------
line 5 *parse error
-----------------------
line 6
key: _12_34
values: 1 2 3 4
-----------------------
line 7
key: _daniweb_thread_numbers
values: 12345 56789 34567 78901
-----------------------
line 8
key: primitive_pythagorian_triplet_2
values: 9 12 15
-----------------------
line 9
key: adds_up_to_12
values: -24 48 -12
-----------------------

for more information see http://spirit.sourceforge.net/ or the boost libraries documentation.
this example is written using spirit 1.8 version 2 is due in mid-may (during BoostCon '07)
Last edited by vijayan121; Apr 29th, 2007 at 3:56 am.
Reply With Quote Quick reply to this message  
Join Date: Apr 2007
Posts: 12
Reputation: MaestroS is an unknown quantity at this point 
Solved Threads: 0
MaestroS MaestroS is offline Offline
Newbie Poster

Re: Simple script parser - how to ?

 
0
  #8
Apr 29th, 2007
@up
thanks for it

#refresh
if someone has easier idea - reply!
Reply With Quote Quick reply to this message  
Reply

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC