Hi,
I am trying to use Spirit (in the latest Boost 1_30_0) for a project.
I want to parse a file whose structure is the following:
section1 {
something;
}
I am using the file_iterator to iterate on the input file and then
define comment as well as the grammar. I am at my wits end why my
parser keeps failing. (When this simple grammar works, I want to make
the parser more complex.) My code is attached below. (Note: I used
the example in the distribution c_grammar.cpp as the starting point
for it.)
Thanks.
-surinder
PS: This input file structure is going to be, of course, more
complicated than the example shown above. Inside the setions, I would
like to pass on flags and statements to the code. If it is better for
me to use another approach to parse this file structure, please
suggest me.
#include <iostream>
#include <fstream>
#include <vector>
#include
/* Input file for this looks like:
file { something; }
*/
//////////////////////////////////////////////////////////////////////
/////////
// used namespaces
using namespace boost::spirit;
using namespace std;
//////////////////////////////////////////////////////////////////////
/////////
// parsing helper function
// Here's our comment rule
struct skip_grammar : public grammar
{
template <typename ScannerT>
struct definition
{
definition(skip_grammar const& /*self*/)
{
skip
= space_p
| comment_p("//") // C++ comment
| comment_p("/*", "*/") // C comment
| comment_p("#") // added for correctly
;
}
rule<ScannerT> skip;
rule<ScannerT> const&
start() const { return skip; }
};
};
//////////////////////////////////////////////////////////////////////
/////////
// typedef
typedef char CharT;
typedef file_iterator <CharT> IteratorT;
typedef scanner <IteratorT> ScannerT;
typedef rule <ScannerT> RuleT;
template<typename GrammarT>
void
parse(GrammarT const& g, char const* filename)
{
ifstream in(filename);
if (!in) {
cerr << "Could not open input file: " << filename << endl;
return;
}
IteratorT start(filename);
if (!start) {
cerr << "Could not open the file " << endl;
return ;
}
IteratorT end = start.make_end();
skip_grammar skip;
parse_info<IteratorT> result = parse(start, end, g, skip);
if (result.full)
cerr << filename << " Parses OK" << endl;
else {
cerr << filename << " Fails Parsing" << endl;
for (int i = 0; i < 50; i++)
{
if (result.stop == end)
break;
cerr << *result.stop++;
}
cerr << endl;
}
}
struct c_grammar : public grammar
{
template <typename ScannerT>
struct definition
{
definition(c_grammar const& /*self*/) :
SEMICOLON(';'), COMMA(','), COLON(':'), ASSIGN('='),
LEFT_PAREN('('), RIGHT_PAREN(')')
{
// C keywords
keywords =
"file", "physics", "math";
// C operators
LEFT_BRACE = chlit<>('{') | strlit<>("<%");
RIGHT_BRACE = chlit<>('}') | strlit<>("%>");
LEFT_BRACKET = chlit<>('[') | strlit<>("<:");
RIGHT_BRACKET = chlit<>(']') | strlit<>(":>");
// Tokens
FILE = strlit<>("file");
PHYSICS = strlit<>("physics");
MATH = strlit<>("math");
// string literals
STRING_LITERAL_PART =
lexeme_d[
!chlit<>('L') >> chlit<>('\"') >>
*( strlit<>("\\\"") | anychar_p - chlit<>('\"') ) >>
chlit<>('\"')
]
;
STRING_LITERAL = +STRING_LITERAL_PART;
// Rules
file_statement =
FILE >> LEFT_BRACE >>
*(anychar_p) >>
RIGHT_BRACE; // does not work
// file_statement = *(anychar_p); // parses OK
translation_unit = file_statement;
}
symbols<> keywords;
chlit<>
SEMICOLON, COMMA, COLON, ASSIGN, LEFT_PAREN, RIGHT_PAREN;
rule<ScannerT>
LEFT_BRACE, RIGHT_BRACE, LEFT_BRACKET, RIGHT_BRACKET;
rule<ScannerT> FILE, PHYSICS, MATH, STRING_LITERAL,
STRING_LITERAL_PART;
rule<ScannerT> file_statement, translation_unit;
rule<ScannerT> const&
start() const { return translation_unit; }
};
};
//////////////////////////////////////////////////////////////////////
/////////
// main entrypoint
int
main(int argc, char* argv[])
{
// Start grammar definition
cerr << "C Grammar checker implemented with Spirit ..." << endl;
// main driver code
c_grammar g;
if (2 == argc)
parse(g, argv[1]);
else
cerr << "No filename given" << endl;
return 0;
}