QCodeEdit  2.2
qnfa.h
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
4 **
5 ** This file is part of the Edyuk project <http://edyuk.org>
6 **
7 ** This file may be used under the terms of the GNU General Public License
8 ** version 3 as published by the Free Software Foundation and appearing in the
9 ** file GPL.txt included in the packaging of this file.
10 **
11 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13 **
14 ****************************************************************************/
15 
16 #ifndef _Q_NFA_H_
17 #define _Q_NFA_H_
18 
24 #include <QChar>
25 #include <QList>
26 #include <QHash>
27 #include <QStack>
28 #include <QString>
29 
30 #include "light_vector.h"
31 
32 struct QNFA;
33 
35 
36 class QNFABranch : public light_vector<QNFA*>
37 {
38  public:
39  ~QNFABranch();
40 };
41 
42 enum NFAType
43 {
44  Char = 0,
45 
46  Match = 1,
47 
48  CxtBeg = 2,
49  CxtEnd = 4,
50  CxtEsc = 8,
51 
52  ContextBegin = Match | CxtBeg,
53  ContextEnd = Match | CxtEnd,
54  EscapeSeq = Match | CxtEsc,
55 
56  Escaped = 16,
57  Exclusive = 32,
58  StayOnLine = 64,
59 
60  Reserved = 128
61 };
62 
63 enum NFAAssertion
64 {
65  NoAssertion = 0,
66 
67  One = 0, // default standard
68  ZeroOrOne = 1, // ?
69  ZeroOrMore = 2, // *
70  OneOrMore = 4, // +
71 
72  WordStart = 8,
73  WordEnd = 16,
74 
75  Word = 32,
76  NonWord = 64,
77 
78  Digit = 128,
79  NonDigit = 256,
80 
81  Space = 512,
82  NonSpace = 1024,
83 
84  CaseSensitive = 2048
85 };
86 
87 struct QCharTreeNode;
88 
89 typedef QHash<quint16, QCharTreeNode> QCharTreeLevel;
90 
92 {
93  inline QCharTreeNode(quint16 v = 0) { value.unicode = v; }
94  inline QCharTreeNode(const QCharTreeNode& o) { value = o.value; next = o.next; }
95 
96  union
97  {
98  int action;
99  quint16 unicode;
100  } value;
101 
102  QCharTreeLevel next;
103 };
104 
105 Q_DECLARE_TYPEINFO(QCharTreeNode, Q_MOVABLE_TYPE);
106 
107 typedef QCharTreeLevel QCharTree;
108 
109 struct QNFA
110 {
111  QNFA();
112  ~QNFA();
113 
114  QNFASet c;
115  QCharTree tree;
116 
117  union
118  {
119  QNFA *next;
120  QNFABranch *branch;
121  } out;
122 
123  quint8 type;
124  quint16 assertion;
125 
126  int actionid;
127 
128  static quint32 _count;
129 };
130 
132 {
133  inline QNFAMatchContext(QNFA *root = 0) : context(root) {}
134 
135  inline QNFAMatchContext& operator = (QNFAMatchContext *c)
136  {
137  if ( c )
138  {
139  context = c->context;
140  parents = c->parents;
141  meaningless = c->meaningless;
142  } else {
143  reset();
144  }
145 
146  return *this;
147  }
148 
149  inline QNFAMatchContext& operator = (const QNFAMatchContext& c)
150  {
151  context = c.context;
152  parents = c.parents;
153  meaningless = c.meaningless;
154 
155  return *this;
156  }
157 
158  inline void reset()
159  {
160  context = 0;
161 
162  while ( parents.count() )
163  context = parents.pop();
164  }
165 
166  QNFA *context;
167  QNFASet meaningless;
168  QStack<QNFA*> parents;
169 };
170 
172 {
173  public:
174  virtual ~QNFAMatchHandler() {}
175 
176  virtual void matched(int pos, int len, int action) = 0;
177 };
178 
180 {
181  private:
182  struct Command
183  {
184  inline Command(int p, int len, int act)
185  : pos(p), length(len), action(act) {}
186 
187  int pos;
188  int length;
189  int action;
190  };
191 
192  typedef QList<Command> CommandList;
193 
194  public:
196  : handler(h) {}
197 
198  inline QNFAMatchNotifier& operator = (const QNFAMatchNotifier& n)
199  {
200  handler = n.handler;
201 
202  return *this;
203  }
204 
205  inline void operator () (int pos, int len, int action)
206  {
207  if ( handler && (m_buffers.isEmpty() || m_pending.count()) )
208  handler->matched(pos, len, action);
209  else
210  m_buffers.top() << Command(pos, len, action);
211  }
212 
213  inline int bufferLevel() const
214  {
215  return m_buffers.count();
216  }
217 
218  inline void startBuffering()
219  {
220  m_buffers.push(CommandList());
221  }
222 
223  inline void stopBuffering()
224  {
225  m_pending = m_buffers.pop();
226  }
227 
228  inline void flush()
229  {
230  foreach ( Command c, m_pending )
231  handler->matched(c.pos, c.length, c.action);
232 
233  m_pending.clear();
234  }
235 
236  inline void clear()
237  {
238  m_pending.clear();
239  m_buffers.clear();
240  }
241 
242  private:
243  QNFAMatchHandler *handler;
244 
245  CommandList m_pending;
246  QStack<CommandList> m_buffers;
247 };
248 
249 void match( QNFAMatchContext *lexer,
250  const QChar *d,
251  int length,
252  QNFAMatchNotifier notify);
253 
254 inline void match( QNFAMatchContext *lexer,
255  const QString& s,
256  QNFAMatchNotifier notify)
257 { match(lexer, s.constData(), s.length(), notify); }
258 
259 QNFA* lexer();
260 
261 void squeeze(QNFA *nfa);
262 void squeeze(QCharTreeLevel& lvl);
263 
264 QNFA* sharedContext(const QString& start,
265  QNFA *other,
266  bool cs);
267 
268 QNFA* context( const QString& start,
269  const QString& stop,
270  const QString& escape,
271  int action,
272  QNFA **handler = 0,
273  bool cs = true);
274 
275 inline void addNFA(QNFA *context, QNFA *nfa)
276 { context->out.branch->append(nfa); }
277 
278 bool plain(const QString& word, QString *dest);
279 
280 void addWord( QCharTree& tree,
281  const QString& w,
282  int action,
283  bool cs);
284 
285 void addWord( QNFA *lexer,
286  const QString& w,
287  int action,
288  bool cs);
289 
290 void addSequence( QNFA *lexer,
291  const QString& w,
292  int action,
293  bool cs);
294 
295 QNFA* sequence( const QChar *d,
296  int length,
297  QNFA **end,
298  bool cs);
299 
300 inline QNFA* sequence(
301  const QString& s,
302  QNFA **end,
303  bool cs)
304 { return sequence(s.constData(), s.length(), end, cs); }
305 
306 #endif
Definition: qnfa.h:171
Definition: qnfa.h:179
Definition: qnfa.h:109
Definition: qnfa.h:36
Definition of the light_vector class.
Definition: qnfa.h:131
Definition: qnfa.h:91