I use the following win32 console code to try to parse the B Machine grammar embedded in C ++ using the Boost Spirit grammar pattern. I am a relatively new Boost user. The code compiles, but when I run the .exe file created by VC ++ 2008, the program partially parses the input file. I believe that the problem is related to my definition of grammar or functions fixed as semantic attacks.
The code is below:
#include <boost/spirit/core.hpp>
#include <boost/tokenizer.hpp>
#include <iostream>
#include <string>
#include <fstream>
#include <vector>
#include <utility>
using namespace std;
using namespace boost::spirit;
vector<string> strVect;
namespace
{
void do_noint(char const* str, char const* end)
{
string s(str, end);
if(atoi(str))
{
;
}
else
{
strVect.push_back(s);
cout << "PUSH(" << s << ')' << endl;
}
}
void do_add(char const*, char const*)
{
cout << "ADD" << endl;
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi)
cout << *vi << " ";
}
void do_subt(char const*, char const*)
{
cout << "SUBTRACT" << endl;
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi)
cout << *vi << " ";
}
void do_mult(char const*, char const*)
{
cout << "\nMULTIPLY" << endl;
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi)
cout << *vi << " ";
cout << "\n";
}
void do_div(char const*, char const*)
{
cout << "\nDIVIDE" << endl;
for(vector<string>::iterator vi = strVect.begin(); vi < strVect.end(); ++vi)
cout << *vi << " ";
}
void do_sSubst(char const* str, char const* end)
{
string s(str, end);
typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
boost::char_separator<char> sep("-+/*:=()");
Tokenizer tok(s, sep);
Tokenizer::iterator tok_iter = tok.begin();
pair<string, string > dependency;
dependency.first = *tok.begin();
vector<string> dx;
for( ; tok_iter != tok.end(); ++tok_iter)
{
dx.push_back(*tok_iter );
}
vector<string> d_hat;
string dep;
for(int unsigned i=1; i < dx.size()-1; i++)
{
dependency.second = dx.at(i);
dep = dependency.first + "|->" + dependency.second + " ";
d_hat.push_back(dep);
}
cout << "PUSH(" << s << ')' << endl;
for(int unsigned i=0; i < d_hat.size(); i++)
cout <<"\n...\n" << d_hat.at(i) << " ";
cout << "\nSIMPLE SUBSTITUTION\n";
}
void do_mSubst(char const* str, char const* end)
{
string s(str, end);
typedef boost::tokenizer<boost::char_separator<char> > Tok;
boost::char_separator<char> sep("-+/*:=()");
Tok tok(s, sep);
Tok::iterator tok_iter = tok.begin();
vector<string> mx;
for( ; tok_iter != tok.end(); ++tok_iter)
{
mx.push_back(*tok_iter );
}
mx.push_back("END\n");
for(unsigned int i=0; i<mx.size(); i++)
{
cout << "\nTokens ... " << mx.at(i) << " ";
}
cout << "PUSH(" << s << ')' << endl;
cout << "MULTIPLE SUBSTITUTION\n";
}
}
struct Substitution : public grammar<Substitution>
{
template <typename ScannerT>
struct definition
{
definition(Substitution const& )
{
multi_subst
= (simple_subst [&do_mSubst]
>> +( str_p("||") >> simple_subst [&do_mSubst])
)
;
simple_subst
= (Identifier >> str_p(":=")
>> expression)[&do_sSubst]
;
Identifier
= alpha_p >> +alnum_p
;
expression
= term
>> *( ('+' >> term)[&do_add]
| ('-' >> term)[&do_subt]
)
;
term
= factor
>> *( ('*' >> factor)[&do_mult]
| ('/' >> factor)[&do_div]
)
;
factor
= lexeme_d[( (alpha_p >> +alnum_p) | +digit_p)[&do_noint]]
| '(' >> expression >> ')'
| ('+' >> factor)
;
}
rule<ScannerT> expression, term, factor, Identifier, simple_subst,
multi_subst ;
rule<ScannerT> const&
start() const
{
return multi_subst;
}
};
};
int
main()
{
cout << "************************************************************\n\n";
cout << "\t\t...Machine Parser...\n\n";
cout << "************************************************************\n\n";
cout << "Please enter a filename...or [q or Q] to quit:\n\n ";
char strFilename[256];
cin >> strFilename;
ifstream inFile(strFilename);
Substitution elementary_subst;
string str, next;
while (inFile >> str)
{
getline(cin, next);
str += next;
if (str.empty() || str[0] == 'q' || str[0] == 'Q')
break;
parse_info<> info = parse(str.c_str(), elementary_subst, space_p);
if (info.full)
{
cout << "\n-------------------------\n";
cout << "Parsing succeeded\n";
cout << "\n-------------------------\n";
}
else
{
cout << "\n-------------------------\n";
cout << "Parsing failed\n";
cout << "stopped at: \": " << info.stop << "\"\n";
cout << "\n-------------------------\n";
}
}
cout << "Please enter a filename...or [q or Q] to quit\n";
cin >> strFilename;
return 0;
}
The contents of the file I tried to parse, which I named "mf7.txt" is given below:
debt:=(LoanRequest+outstandingLoan1)*20 || newDebt := loanammount-paidammount
The output when I execute the program is:
************************************************************
...Machine Parser...
************************************************************
Please enter a filename...or [q or Q] to quit:
c:\tplat\mf7.txt
PUSH(LoanRequest)
PUSH(outstandingLoan1)
ADD
LoanRequest outstandingLoan1
MULTIPLY
LoanRequest outstandingLoan1
PUSH(debt:=(LoanRequest+outstandingLoan1)*20)
...
debt|->LoanRequest
...
debt|->outstandingLoan1
SIMPLE SUBSTITUTION
Tokens ... debt
Tokens ... LoanRequest
Tokens ... outstandingLoan1
Tokens ... 20
Tokens ... END
PUSH(debt:=(LoanRequest+outstandingLoan1)*20)
MULTIPLE SUBSTITUTION
-------------------------
Parsing failedstopped at: ": "
-------------------------
My intention is to commit only the variables in the file that I managed to do before "||" line. Obviously, the program is not parsed outside of "||" string in the input file. I would appreciate help in correcting the grammar. SOS, please.