1 | #include <sstream>
|
---|
2 | #include <iostream>
|
---|
3 |
|
---|
4 | #include <boost/spirit/include/lex_lexertl.hpp>
|
---|
5 | #include <boost/spirit/include/lex_lexertl_position_token.hpp>
|
---|
6 | #include <boost/spirit/include/support_istream_iterator.hpp>
|
---|
7 |
|
---|
8 | // if this gets defined, my parse passes and all input is consumed
|
---|
9 | // #define BOOST_SPIRIT_DEBUG
|
---|
10 | // if it is not defined, my parse passes but not all input is consumed
|
---|
11 | #include <boost/spirit/include/qi.hpp>
|
---|
12 | #include <boost/spirit/include/phoenix.hpp>
|
---|
13 | #include <boost/lexical_cast.hpp>
|
---|
14 |
|
---|
15 | #include "keyword.h"
|
---|
16 |
|
---|
17 | // typedef for stream iterator we will use
|
---|
18 | typedef boost::spirit::istream_iterator LefDefIter;
|
---|
19 |
|
---|
20 | // A skip parser for LEF/DEF comments and spaces
|
---|
21 | // adapted from a presentation at Boostcon 2010 by Michael Caisse
|
---|
22 | template <typename Iterator>
|
---|
23 | struct lefdefskipper : boost::spirit::qi::grammar< Iterator >
|
---|
24 | {
|
---|
25 | lefdefskipper() : lefdefskipper::base_type(skip_it)
|
---|
26 | {
|
---|
27 | using namespace boost::spirit::qi;
|
---|
28 |
|
---|
29 | comment = '#' >> *( char_ - eol ) >> eol ;
|
---|
30 | skip_it = comment | space ;
|
---|
31 | }
|
---|
32 | boost::spirit::qi::rule<Iterator> skip_it;
|
---|
33 | boost::spirit::qi::rule<Iterator> comment;
|
---|
34 | };
|
---|
35 |
|
---|
36 | template <typename Iterator>
|
---|
37 | struct lefparser : boost::spirit::qi::grammar<Iterator,
|
---|
38 | lefdefskipper<Iterator> >
|
---|
39 | {
|
---|
40 |
|
---|
41 | lefparser() : lefparser::base_type(lef_file)
|
---|
42 | {
|
---|
43 | using namespace boost::spirit::qi;
|
---|
44 | using namespace distinct;
|
---|
45 | using boost::phoenix::ref; // for storing parsing info into parser var (instead of attributes)
|
---|
46 |
|
---|
47 | // here's MY bug: ">" binds more tightly than "|"
|
---|
48 | // the ON/OFF options need parens
|
---|
49 | // it's in trying to debug this that I noticed the BOOST_SPIRIT_DEBUG problem
|
---|
50 | casesens = keyword["NAMESCASESENSITIVE"] >
|
---|
51 | (string("ON")[ref(case_on) = true] |
|
---|
52 | string("OFF")[ref(case_on) = false]) > ';' ;
|
---|
53 |
|
---|
54 | lef_file = -casesens >> -string("END") ;
|
---|
55 |
|
---|
56 | BOOST_SPIRIT_DEBUG_NODE(casesens);
|
---|
57 | BOOST_SPIRIT_DEBUG_NODE(lef_file);
|
---|
58 | }
|
---|
59 | bool case_on;
|
---|
60 | typedef boost::spirit::qi::rule<Iterator, lefdefskipper<Iterator> > NoAttrRule;
|
---|
61 | NoAttrRule lef_file, casesens;
|
---|
62 | };
|
---|
63 |
|
---|
64 | int main() {
|
---|
65 | lefparser<LefDefIter> lefParser;
|
---|
66 | lefdefskipper<LefDefIter> lefdefSkipper;
|
---|
67 |
|
---|
68 | std::stringstream testlef("NAMESCASESENSITIVE ON ;\nEND\n");
|
---|
69 | testlef.unsetf(std::ios::skipws);
|
---|
70 | LefDefIter beg = LefDefIter(testlef), end;
|
---|
71 |
|
---|
72 | if (!phrase_parse(beg, end, lefParser, lefdefSkipper)) {
|
---|
73 | std::cerr << "parse failed\n";
|
---|
74 | return 1;
|
---|
75 | } else if (beg != end) {
|
---|
76 | std::cerr << "Not all input consumed. Remaining input:|";
|
---|
77 | std::copy(beg, end, std::ostream_iterator<char>(std::cerr));
|
---|
78 | std::cerr << "|\n";
|
---|
79 | return 1;
|
---|
80 | }
|
---|
81 | std::cerr << "parse passed\n";
|
---|
82 | return 0;
|
---|
83 | }
|
---|