root/lang/c/partty/kazuhiki/kazuhiki_extend.h @ 3319

Revision 3319, 5.5 kB (checked in by frsyuki, 5 years ago)

lang/c/partty: imported.

Line 
1/*
2 * Kazuhiki
3 *
4 * Copyright (c) 2007 FURUHASHI Sadayuki
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24
25#ifndef KAZUHIKI_EXTEND_H__
26#define KAZUHIKI_EXTEND_H__ 1
27
28#include "kazuhiki/kazuhiki.h"
29#include "kazuhiki/kazuhiki_basic.h"
30
31namespace Kazuhiki {
32
33
34
35////
36// Command
37//
38class CommandParser : public RecursiveParser {
39public:
40        CommandParser(bool required = true) : m_required(required) {}
41public:
42
43        class Command : public LeafParser {
44        public:
45                Command(const std::string& str, bool& set) :
46                        LeafParser(&set),
47                        m_str(str) {}
48                Command(const std::string& str) :
49                        m_str(str) {}
50        public:
51                template <typename T>
52                Command& operator<< (T state) {
53                        LeafParser::push(state);
54                        return *this;
55                }
56        public:
57                virtual bool complete_match(const std::string& v) const { return m_str == v; }
58                virtual bool partial_match(const std::string& part) const {
59                        if( part.length() > m_str.length() ) { return false; }
60                        return part == m_str.substr(0, part.length());
61                }
62        public:
63                void make_error_list(ArgumentError* err) { (*err) << m_str; }
64        private:
65                std::string m_str;
66        };
67
68public:
69        unsigned int parse(int argc, const char* const argv[])
70        {
71                if( argc == 0 ) {
72                        if( m_required ) {
73                                ArgumentError err("one of commands have to be set");
74                                throw make_error_list( m_commands.begin(), m_commands.end(), err );
75                        } else {
76                                return 0;
77                        }
78                }
79
80                for(commands_type::iterator it(m_commands.begin()), it_end(m_commands.end());
81                                it != it_end;
82                                ++it ) {
83                        if( (*it)->complete_match(argv[0]) ) {
84                                return (*it)->parse(argc-1, &argv[1]) + 1;
85                        }
86                }
87
88                std::vector<Command*> match;
89                for(commands_type::iterator it(m_commands.begin()), it_end(m_commands.end());
90                                it != it_end;
91                                ++it ) {
92                        if( (*it)->partial_match(argv[0]) ) {
93                                match.push_back(*it);
94                        }
95                }
96                if( match.size() == 1 ) {
97                        return match[0]->parse(argc-1, &argv[1]) + 1;
98                } else if( match.size() > 1 ) {
99                        ArgumentError err("ambiguity command");
100                        err << ArgumentError::inspect_string(argv[0]);
101                        make_error_list( match.begin(), match.end(), err );
102                        throw err;
103                }
104                ArgumentError err("unknown command");
105                err << ArgumentError::inspect_string(argv[0]);
106                throw make_error_list( m_commands.begin(), m_commands.end(), err );
107        }
108        void destruct(void)
109        {
110                std::for_each(  m_commands.begin(),
111                                m_commands.end(),
112                                BranchParser::each_destruct
113                             );
114        }
115public:
116        template <typename T>
117        CommandParser& operator% (T cmd) {
118                m_commands.push_back( new T(cmd) );
119                return *this;
120        }
121private:
122        template <class InputIterator>
123        ArgumentError& make_error_list(InputIterator first, InputIterator last, ArgumentError& err) {
124                err << "(";
125                std::for_each(  first,
126                                last,
127                                std::bind2nd(
128                                        std::mem_fun( &Command::make_error_list ),
129                                        &err
130                                        )
131                             );
132                err << ")";
133                return err;
134        }
135private:
136        typedef std::vector<Command*> commands_type;
137        commands_type m_commands;
138        const bool m_required;
139};
140
141
142
143////
144// Switch
145//
146class SwitchParser : public RecursiveParser {
147public:
148        SwitchParser() :
149                m_other(NULL),
150                m_other_set(NULL) {}
151public:
152
153        class Switch : public LeafParser {
154        public:
155                Switch(const std::string& str, bool& set) :
156                        LeafParser(&set),
157                        m_str(str) {}
158                Switch(const std::string& str) :
159                        m_str(str) {}
160        public:
161                template <typename T>
162                Switch& operator<< (T state) {
163                        LeafParser::push(state);
164                        return *this;
165                }
166        public:
167                bool match(const std::string& v) const { return m_str == v; }
168        private:
169                std::string m_str;
170        };
171
172        class Other : public LeafParser {
173        public:
174                template <typename T>
175                Other& operator<< (T state) {
176                        LeafParser::push(state);
177                        return *this;
178                }
179        };
180
181public:
182        unsigned int parse(int argc, const char* const argv[])
183        {
184                if( argc == 0 ) {
185                        if( m_other_set ) { *m_other_set = true; }
186                        return m_other->parse(argc, argv);
187                }
188
189                for(switches_type::iterator it(m_switches.begin()), it_end(m_switches.end());
190                                it != it_end;
191                                ++it ) {
192                        if( (*it)->match(argv[0]) ) {
193                                return (*it)->parse(argc-1, &argv[1]) + 1;
194                        }
195                }
196                if( m_other_set ) { *m_other_set = true; }
197                return m_other->parse(argc, argv);
198        }
199        void destruct(void)
200        {
201                std::for_each(  m_switches.begin(),
202                                m_switches.end(),
203                                BranchParser::each_destruct
204                             );
205                delete m_other;
206        }
207public:
208        template <typename T>
209        SwitchParser& operator% (T sw) {
210                m_switches.push_back( new T(sw) );
211                return *this;
212        }
213        SwitchParser& operator% (Other sw) {
214                m_other = new Other(sw);
215                return *this;
216        }
217private:
218        typedef std::vector<Switch*> switches_type;
219        switches_type m_switches;
220        Other* m_other;
221        bool* m_other_set;
222};
223
224
225
226}  // namespace Kazuhiki
227
228#endif /* kazuhiki_extend.h */
Note: See TracBrowser for help on using the browser.