Archived

This topic is now archived and is closed to further replies.

Odd the Hermit

boost::spirit examples?

Recommended Posts

Odd the Hermit    122
Does anyone have any experience with using the boost::spirit parser library? I''ve looked through the documentation, and it seems to be much more of "here''s the cool stuff you can do", rather than "here''s how to do this cool stuff". Are there any good examples floating around on how to use it? (Preferably, an example that doesn''t have "using namespace boost::spirit" in it, since I don''t want to do that, and I''d like to be able to see what Spirit provides, and what I need to do myself...) Thanks, -Odd the Hermit

Share this post


Link to post
Share on other sites
daerid    354
You''re probably gonna have to tough it out using the documentation.

I almost finished a small C-style scripting language using spirit, but have since lost the code.

Share this post


Link to post
Share on other sites
Odd the Hermit    122
Well, I haven't found any (useful) examples yet, though I did eventually find that I needed to replace the version I'd downloaded. The documentation for Spirit 1.7 claims that it compiles under MS Visual C++ service pack 5, but it doesn't (it uses partial template specialization, which MS doesn't like). I'd tried commenting out the offending lines, but that only lead to stuff not working (which should've been obvious to me...). So, last night, I downloaded Spirit 1.3 MSVC (a version specifically designed to work on MSVC service pack 3 or higher). Here's what I've got so far (note: this is all testing code, not meant for my actual game, though I'm hoping it'll lead in to that...):


#include <windows.h>
#include <boost/spirit/spirit.hpp>

// These functions are called by Spirit so I can see what it's matching.

void AnnounceComment(char const* first, char const* last) {
std::string str(first, last);
MessageBox( NULL, str.c_str(), "Comment!", MB_OK );
}
void AnnounceName(char const* first, char const* last) {
std::string str(first, last);
MessageBox( NULL, str.c_str(), "Name!", MB_OK );
}
void NameVal(char const* first, char const* last) {
std::string str(first, last);
MessageBox( NULL, str.c_str(), "NameVal!", MB_OK );
}
void String(char const* first, char const* last) {
std::string str(first, last-1);
MessageBox( NULL, str.c_str(), "String", MB_OK );
}
void Value(char const* first, char const* last) {
std::string str(first, last);
MessageBox( NULL, str.c_str(), "Value", MB_OK );
}
void ValueList(char const* first, char const* last) {
std::string str(first, last);
MessageBox( NULL, str.c_str(), "ValueList", MB_OK );
}

int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrev,
LPSTR lpCmdLine, int nCmdShow ) {
std::string str = "This=\"That\";\"The Other\"";

const char *mStr = str.c_str();
// Parse the line, with the magic of boost::spirit!

spirit::rule<const char*> rLine, rComment, rNameVal, rName, rValList, rVal, rString, rStrVal;

rLine = rComment | rNameVal;
rComment = spirit::strlit<>("
//") >> (*spirit::anychar)[ &AnnounceComment ];

rNameVal = ((spirit::ch_p('+')|'-') >> rName)[ &NameVal ] |
(rName >> '=' >> rValList)[ &NameVal ];
rValList = ( rVal >> *(';' >> rValList) )[ &ValueList ];
rName = (spirit::alpha >> *spirit::alnum)[ &AnnounceName ];
rVal = ( rString | spirit::real_p )[ &Value ];
rString = spirit::ch_p('"') >> (rStrVal)[ &String ];
rStrVal = spirit::ch_p('"') | spirit::anychar >> rStrVal;

spirit::parse_info<const char*> result = spirit::parse(mStr, rLine);

if (result.match) {
MessageBox( NULL, "
Matched!", "Test", MB_OK );
} else {
MessageBox( NULL, "
Didn't match!", "Test", MB_OK );
}
if (result.full) {
MessageBox( NULL, "
Full!", "Test", MB_OK );
} else {
MessageBox( NULL, "
Not full!", "Test", MB_OK );
}
MessageBox( NULL, str.c_str(), "
Test", MB_OK );
return 0;
}


This is an attempt to match the following style lines (basically, for settings):

// A comment.
+name
-name
name="string value"
name=123
name=123;"stringvalue"

etc. It may not be the most graceful way of doing it, but it works. If anyone is interested, I'll keep posting my progress.

-Odd the Hermit

EDIT: forgot to "#include <windows>". Of course, it should've been fairly obvious what my intent was, but for the sake of completeness...

[edited by - Odd the Hermit on August 10, 2003 7:46:21 AM]

Share this post


Link to post
Share on other sites
Odd the Hermit    122
One other thing I forgot to mention: Spirit 1.3 MSVC did not compile immediately for me. In boost\spirit\MSVC\impl\numerics.ipp, I had to change lines 388 and 413 from:

388: const arg_type lim = numeric_limits::max()/Radix;
413: if (pred(nextdigit) > numeric_limits::max() - n) {

to:
388: const arg_type lim = std::numeric_limits::max()/Radix;
413: if (pred(nextdigit) > std::numeric_limits::max() - n) {

I''m hoping that this is what they meant; this change allows everything to compile, and it seems to parse numbers correctly, so I''m hopeful that this is, indeed, a correct fix.

-Odd the Hermit

Share this post


Link to post
Share on other sites
petewood    819
I think the latest copy of CUJ has an article about it but I haven''t received mine yet.

What do you mean you don''t want an article that says ''using namespace boost::spirit''? That''s a bit odd.

Take a look at the code for Wave

Share this post


Link to post
Share on other sites
Odd the Hermit    122
quote:
Original post by petewood
What do you mean you don''t want an article that says ''using namespace boost::spirit''? That''s a bit odd.



I prefer to keep my namespaces clean--I prefer writing std::string over adding std to my namespace, since that can lead to inadvertent name collisions...all of the examples in the spirit library use the namespace, which I think is confusing (ie., is integer defined in spirit, or somewhere else?) So, that''s why I''d prefer examples that don''t muck around with the namespace. Chalk it up to personal preference. <shrug>

-Odd the Hermit

Share this post


Link to post
Share on other sites