Ticket #6460: XpressiveGrammarSample.hpp

File XpressiveGrammarSample.hpp, 4.6 KB (added by Eric Niebler, 11 years ago)
Line 
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
5class testnode
6{
7public:
8 testnode(){};
9 testnode(testnode* pChild){m_pChildren.push_back(pChild);};
10protected:
11 std::vector<testnode*> m_pChildren;
12};
13
14class testnodetext : public testnode
15{
16public:
17 testnodetext(std::string sVal){m_sVal=sVal;};
18private:
19 std::string m_sVal;
20};
21
22class testnodeor : public testnode
23{
24public:
25 testnodeor(testnode* pL,testnode* pR){m_pChildren.push_back(pL);m_pChildren.push_back(pR);}
26};
27
28class testnodeand : public testnode
29{
30public:
31 testnodeand(testnode* pL,testnode* pR){m_pChildren.push_back(pL);m_pChildren.push_back(pR);}
32};
33
34class testnodenot : public testnode
35{
36public:
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
45template <typename TBase> class XpressiveGrammarBase
46{
47public:
48protected:
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 }
97private:
98 std::deque<TBase*> m_aStack;
99};
100
101
102//Example of an actual grammar
103class testgrammar: public XpressiveGrammarBase<testnode>
104{
105public:
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 }
129protected:
130private:
131 boost::xpressive::sregex rulestart, rulenode, rulenotnode, ruleornode, ruleandnode, ruletextnode;
132};
133
134int 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}