1 | #include <boost/xpressive/xpressive.hpp>
|
---|
2 | #include <boost/xpressive/regex_actions.hpp>
|
---|
3 |
|
---|
4 | //Class hierarchy into which we would like to parse the data
|
---|
5 | class testnode
|
---|
6 | {
|
---|
7 | public:
|
---|
8 | testnode(){};
|
---|
9 | testnode(testnode* pChild){m_pChildren.push_back(pChild);};
|
---|
10 | protected:
|
---|
11 | std::vector<testnode*> m_pChildren;
|
---|
12 | };
|
---|
13 |
|
---|
14 | class testnodetext : public testnode
|
---|
15 | {
|
---|
16 | public:
|
---|
17 | testnodetext(std::string sVal){m_sVal=sVal;};
|
---|
18 | private:
|
---|
19 | std::string m_sVal;
|
---|
20 | };
|
---|
21 |
|
---|
22 | class testnodeor : public testnode
|
---|
23 | {
|
---|
24 | public:
|
---|
25 | testnodeor(testnode* pL,testnode* pR){m_pChildren.push_back(pL);m_pChildren.push_back(pR);}
|
---|
26 | };
|
---|
27 |
|
---|
28 | class testnodeand : public testnode
|
---|
29 | {
|
---|
30 | public:
|
---|
31 | testnodeand(testnode* pL,testnode* pR){m_pChildren.push_back(pL);m_pChildren.push_back(pR);}
|
---|
32 | };
|
---|
33 |
|
---|
34 | class testnodenot : public testnode
|
---|
35 | {
|
---|
36 | public:
|
---|
37 | testnodenot(testnode* pNot){m_pChildren.push_back(pNot);};
|
---|
38 | };
|
---|
39 |
|
---|
40 |
|
---|
41 |
|
---|
42 | //Boiler plate base class that does most of the 'work' creating the parse tree
|
---|
43 | //This is somewhat 'equivalent' to the grammar class of spirit
|
---|
44 | //We can re-use this base for every pointer based grammar we would like to create
|
---|
45 | template <typename TBase> class XpressiveGrammarBase
|
---|
46 | {
|
---|
47 | public:
|
---|
48 | protected:
|
---|
49 | //Functions to allow us to create new nodes as needed
|
---|
50 | template<typename Tmk> struct mknode_impl
|
---|
51 | {
|
---|
52 | mknode_impl(std::deque<TBase*>* paStack): m_paStack(paStack){};
|
---|
53 | typedef void result_type;
|
---|
54 | void operator()() const
|
---|
55 | {
|
---|
56 | m_paStack->push_back(new Tmk());
|
---|
57 | }
|
---|
58 | template<typename Value1> void operator()(Value1 const &val1) const
|
---|
59 | {
|
---|
60 | m_paStack->push_back(new Tmk(val1));
|
---|
61 | }
|
---|
62 | template<typename Value1,typename Value2> void operator()(Value1 const &val1,Value2 const &val2) const
|
---|
63 | {
|
---|
64 | m_paStack->push_back(new Tmk(val1,val2));
|
---|
65 | }
|
---|
66 | std::deque<TBase*>* m_paStack;
|
---|
67 | };
|
---|
68 | template<typename Tmk> typename boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const>::result_type const mknode_()
|
---|
69 | {
|
---|
70 | return boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const>()((mknode_impl<Tmk>(&m_aStack)));
|
---|
71 | }
|
---|
72 | template<typename Tmk, typename A0> typename boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const, A0 const &>::result_type const mknode_(A0 const &a0)
|
---|
73 | {
|
---|
74 | return boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const, A0 const &>()((mknode_impl<Tmk>(&m_aStack)), a0);
|
---|
75 | }
|
---|
76 | template<typename Tmk, typename A0, typename A1> typename boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const, A0 const &, A1 const &>::result_type const mknode_(A0 const &a0,A1 const &a1)
|
---|
77 | {
|
---|
78 | return boost::xpressive::detail::make_function::impl<mknode_impl<Tmk> const, A0 const &, A1 const &>()((mknode_impl<Tmk>(&m_aStack)), a0, a1);
|
---|
79 | }
|
---|
80 | //Function to retrieve previously created child nodes (so that we can create composite nodes etc.)
|
---|
81 | struct getnode_impl
|
---|
82 | {
|
---|
83 | getnode_impl(std::deque<TBase*>* paStack): m_paStack(paStack){};
|
---|
84 | typedef TBase* result_type;
|
---|
85 | TBase* operator()() const
|
---|
86 | {
|
---|
87 | TBase* pRet = m_paStack->front();
|
---|
88 | m_paStack->pop_front();
|
---|
89 | return pRet;
|
---|
90 | }
|
---|
91 | std::deque<TBase*>* m_paStack;
|
---|
92 | };
|
---|
93 | typename boost::xpressive::detail::make_function::impl<getnode_impl const>::result_type const getnode_()
|
---|
94 | {
|
---|
95 | return boost::xpressive::detail::make_function::impl<getnode_impl const>()((getnode_impl(&m_aStack)));
|
---|
96 | }
|
---|
97 | private:
|
---|
98 | std::deque<TBase*> m_aStack;
|
---|
99 | };
|
---|
100 |
|
---|
101 |
|
---|
102 | //Example of an actual grammar
|
---|
103 | class testgrammar: public XpressiveGrammarBase<testnode>
|
---|
104 | {
|
---|
105 | public:
|
---|
106 | testgrammar(std::string sSearch,testnode*& pRoot)
|
---|
107 | {
|
---|
108 | using namespace boost::xpressive;
|
---|
109 |
|
---|
110 | rulestart = bos >> by_ref(rulenode) >> eos
|
---|
111 | [ref(pRoot)=getnode_()];;
|
---|
112 |
|
---|
113 | rulenode = (by_ref(ruletextnode)|by_ref(rulenotnode)|by_ref(ruleandnode)|by_ref(ruleornode));
|
---|
114 |
|
---|
115 | ruletextnode = (s1 = +(~(set='!','&','|')))
|
---|
116 | [mknode_<testnodetext>(s1)];
|
---|
117 |
|
---|
118 | rulenotnode = '!' >> by_ref(rulenode)
|
---|
119 | [mknode_<testnodenot>(getnode_())];
|
---|
120 |
|
---|
121 | ruleandnode = (by_ref(ruletextnode)|by_ref(rulenotnode)|by_ref(ruleornode)) >> '&' >> by_ref(rulenode)
|
---|
122 | [mknode_<testnodeand>(getnode_(),getnode_())];
|
---|
123 |
|
---|
124 | ruleornode = (by_ref(ruletextnode)|by_ref(rulenotnode)) >> '|' >> by_ref(rulenode)
|
---|
125 | [mknode_<testnodeor>(getnode_(),getnode_())];
|
---|
126 |
|
---|
127 | regex_search(sSearch,rulestart);
|
---|
128 | }
|
---|
129 | protected:
|
---|
130 | private:
|
---|
131 | boost::xpressive::sregex rulestart, rulenode, rulenotnode, ruleornode, ruleandnode, ruletextnode;
|
---|
132 | };
|
---|
133 |
|
---|
134 | int main(int argc, char *argv[])
|
---|
135 | {
|
---|
136 | std::string sTest = "abcd|!xyz|qwerty";
|
---|
137 | testnode* pRoot=NULL;
|
---|
138 | testgrammar grammar(sTest,pRoot);
|
---|
139 | if(pRoot)
|
---|
140 | {
|
---|
141 | //Success
|
---|
142 | //->testnodeor
|
---|
143 | // -> testnodetext ("abcd")
|
---|
144 | // ->testnodeor
|
---|
145 | // ->testnodenot
|
---|
146 | // ->testnodetext("xyz")
|
---|
147 | // ->testnodetext ("qwerty")
|
---|
148 | }
|
---|
149 | else
|
---|
150 | {
|
---|
151 | //Failed
|
---|
152 | }
|
---|
153 | return 0;
|
---|
154 | }
|
---|