• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdesdk API Reference
  • KDE Home
  • Contact Us
 

umbrello/umbrello

  • sources
  • kde-4.12
  • kdesdk
  • umbrello
  • umbrello
  • codeimport
  • kdevcppparser
lexer.cpp
Go to the documentation of this file.
1 /* This file is part of KDevelop
2  Copyright (C) 2002, 2003 Roberto Raggi <[email protected]>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "lexer.h"
21 
22 #include "debug_utils.h"
23 #include "lookup.h"
24 #include "keywords.lut.h"
25 
26 #include <klocale.h>
27 
28 #include <QChar>
29 #include <QList>
30 #include <QMap>
31 #include <QRegExp>
32 
33 #include <boost/bind.hpp>
34 #include <boost/function.hpp>
35 #include <boost/spirit/include/classic_if.hpp>
36 #include <boost/spirit/include/phoenix1_functions.hpp>
37 
38 #include "assignFunctor.hpp"
39 
40 namespace boost {
41  namespace spirit {
42  namespace classic {
43  namespace impl {
44  bool isalnum_(QChar const& c) { return isalnum_(c.toAscii()); }
45  bool isalpha_(QChar const& c) { return isalpha_(c.toAscii()); }
46  bool isblank_(QChar const& c) { return isblank_(c.toAscii()); }
47  bool isdigit_(QChar const& c) { return isdigit_(c.toAscii()); }
48  bool isxdigit_(QChar const& c) { return isxdigit_(c.toAscii()); }
49  }
50  }
51  }
52 }
53 
54 template <class _Tp>
55 struct tilde : public std::unary_function<_Tp, _Tp> {
56  _Tp operator()(_Tp& __x) const {
57  return ~__x;
58  }
59 };
60 
61 using namespace boost::spirit::classic;
62 using phoenix::arg1;
63 using phoenix::arg2;
64 using phoenix::arg3;
65 using phoenix::construct_;
66 using phoenix::function;
67 using phoenix::var;
68 
69 SkipRule Lexer::m_SkipRule = nothing_p;
70 
71 #if defined(KDEVELOP_BGPARSER)
72 #include <QThread>
73 
74 class KDevTread: public QThread
75 {
76 public:
77  static void yield() { msleep(0); }
78 };
79 
80 inline void qthread_yield()
81 {
82  KDevTread::yield();
83 }
84 
85 #endif
86 
90 template < typename ResultT >
91 struct result_closure : closure<result_closure<ResultT>, ResultT> {
92  typedef closure<result_closure<ResultT>, ResultT> base_t;
93  typename base_t::member1 result_;
94 };
95 
97 struct constructQString_impl {
98  template <typename _Arg1, typename _Arg2>
99  struct result {
100  typedef QString type;
101  };
102 
103  template <typename _Arg1, typename _Arg2>
104  QString operator()(_Arg1 const& first, _Arg2 const& last) {
105  return QString(&*first, &*last - &*first);
106  }
107 };
108 
109 const function<constructQString_impl> constructQString =
110  constructQString_impl();
111 
112 struct identifier :
113  grammar<identifier, result_closure<QString>::context_t> {
114  template < typename ScannerT >
115  struct definition {
116  typedef rule<ScannerT> rule_t;
117  rule_t main;
118 
119  rule_t const& start() const {
120  return main;
121  }
122 
123  definition(identifier const& self) {
124  main = (lexeme_d[
125  ((alpha_p | '_') >> *(alnum_p | '_'))
126  [self.result_ = constructQString(arg1, arg2)]
127  ]);
128  }
129  };
130 } identifier_g;
131 
132 struct operator_ :
133  grammar<operator_, result_closure<Token>::context_t> {
134  template < typename ScannerT >
135  struct definition {
136  typedef rule<ScannerT, result_closure<int>::context_t> rule_t;
137  rule_t main;
138 
139  rule_t const& start() const {
140  return main;
141  }
142 
143  definition(operator_ const& self) {
144  main =
145  (str_p("::")[ main.result_ = Token_scope]
146  | (str_p("->*") | ".*")[ main.result_ = Token_ptrmem]
147  | (str_p("<<=") | ">>=" | "+=" | "-=" | "*=" | "/=" | "%=" | "^=" | "&=" | "|=")[ main.result_ = Token_assign]
148  | str_p("<<")[ main.result_ = Token_left_shift]
149  | (str_p("==") | "!=")[ main.result_ = Token_eq]
150  | str_p("<=")[ main.result_ = Token_leq]
151  | str_p(">=")[ main.result_ = Token_geq]
152  | str_p("&&")[ main.result_ = Token_and]
153  | str_p("||")[ main.result_ = Token_or]
154  | str_p("++")[ main.result_ = Token_incr]
155  | str_p("--")[ main.result_ = Token_decr]
156  | str_p("->")[ main.result_ = Token_arrow]
157  | str_p("##")[ main.result_ = Token_concat]
158  | str_p("...")[ main.result_ = Token_ellipsis]
159  )
160  [ self.result_ = construct_<Token>(main.result_, arg1, arg2)];
161  }
162  };
163 } operator_g;
164 
165 struct charLiteral :
166  grammar<charLiteral, result_closure<Token>::context_t> {
167  template < typename ScannerT >
168  struct definition {
169  typedef rule<ScannerT, result_closure<int>::context_t> rule_t;
170  rule_t main;
171 
172  rule_t const& start() const {
173  return main;
174  }
175 
176  definition(charLiteral const& self) {
177  main =
178  (!ch_p('L') >> ch_p('\'')
179  >> *((anychar_p - '\'' - '\\') | gr_escapeSequence)
180  >> '\'')
181  [ self.result_ = construct_<Token>(Token_char_literal, arg1, arg2)];
182  }
183  };
184 } charLiteral_g;
185 
186 struct numberLiteral :
187  grammar<numberLiteral, result_closure<Token>::context_t> {
188  template < typename ScannerT >
189  struct definition {
190  typedef rule<ScannerT, result_closure<int>::context_t> rule_t;
191  rule_t main;
192 
193  rule_t const& start() const {
194  return main;
195  }
196 
197  definition(numberLiteral const& self) {
198  main =
199  (ch_p('0') >> ch_p('x') >> + xdigit_p | + digit_p)
200  [ self.result_ = construct_<Token>(Token_number_literal, arg1, arg2)];
201  }
202  };
203 } numberLiteral_g;
204 
205 typedef std::pair<QString, int> Dependency;
206 
207 struct DependencyClosure
208  : boost::spirit::classic::closure<DependencyClosure, QString, int> {
209  member1 m_word;
210  member2 m_scope;
211 };
212 
213 Lexer::CharRule gr_stringLiteral =
214  ch_p('"') >> *((anychar_p - '"' - '\\') | gr_escapeSequence) >> '"';
215 Lexer::CharRule gr_whiteSpace = blank_p | (ch_p('\\') >> eol_p);
216 Lexer::CharRule gr_lineComment = (str_p("//") >> (*(anychar_p - eol_p)));
217 Lexer::CharRule gr_multiLineComment = confix_p("/*", *anychar_p, "*/");
218 Lexer::CharRule gr_skipTillEol =
219  *(gr_whiteSpace | gr_lineComment | gr_multiLineComment | charLiteral_g
220  | gr_stringLiteral | (anychar_p - '\\' - eol_p) | (ch_p('\\') >> eol_p));
221 
222 Token::Token()
223  : m_type(-1),
224  m_start(),
225  m_end(),
226  m_text()
227 {
228 }
229 
230 Token::Token(int type, CharIterator start, CharIterator end)
231  : m_type(type),
232  m_start(start.get_position()),
233  m_end(end.get_position()),
234  m_text(&*start, &*end - &*start)
235 {
236 }
237 
238 Token& Token::operator=(Token const & p)
239 {
240  if (this != &p) {
241  m_type = p.m_type;
242  m_start = p.m_start;
243  m_end = p.m_end;
244  m_text = p.m_text;
245  }
246  return *this;
247 }
248 
249 QDebug operator<<(QDebug out, const Token &t)
250 {
251  out << "Token("
252  << "type:" << t.type()
253  << "text:" << t.text()
254  << "start:" << t.getStartPosition()
255  << "end:" << t.getEndPosition()
256  << ")";
257  return out;
258 }
259 
260 Token Lexer::Source::createToken(int type, CharIterator start,
261  CharIterator end) const
262 {
263  return Token(type, start, end);
264 }
265 
266 using namespace std;
267 
268 struct LexerData {
269  typedef QMap<QString, QString> Scope;
270  typedef QList<Scope> StaticChain;
271 
272  StaticChain staticChain;
273 
274  void beginScope() {
275  Scope scope;
276  staticChain.push_front(scope);
277  }
278 
279  void endScope() {
280  staticChain.pop_front();
281  }
282 
283  void bind(const QString& name, const QString& value) {
284  Q_ASSERT(staticChain.size() > 0);
285  staticChain.front().insert(name, value);
286  }
287 
288  bool hasBind(const QString& name) const {
289  StaticChain::ConstIterator it = staticChain.begin();
290  while (it != staticChain.end()) {
291  const Scope& scope = *it;
292  ++it;
293 
294  if (scope.contains(name))
295  return true;
296  }
297 
298  return false;
299  }
300 
301  QString apply(const QString& name) const {
302  StaticChain::ConstIterator it = staticChain.begin();
303  while (it != staticChain.end()) {
304  const Scope& scope = *it;
305  ++it;
306 
307  if (scope.contains(name))
308  return scope[ name ];
309  }
310 
311  return QString();
312  }
313 
314 };
315 
316 Lexer::Lexer(Driver* driver)
317  : m_driver(driver),
318  m_recordComments(false),
319  m_preprocessLexer(m_driver)
320 {
321  reset();
322 }
323 
324 Lexer::~Lexer()
325 {
326 }
327 
328 bool Lexer::setSource(const QString& source,
329  const QString& p_filename)
330 {
331  reset();
332  m_preprocessLexer.setSource(source, p_filename);
333  m_source.set_filename(p_filename);
334  return tokenize();
335 
336 }
337 
338 void Lexer::reset()
339 {
340  m_tokens.clear();
341  m_source.reset();
342 }
343 
344 Position const& Lexer::getTokenPosition(const Token& token) const
345 {
346  return token.getStartPosition();
347 }
348 
349 void Lexer::nextToken(Token& tk)
350 {
351  m_source.parse(*gr_whiteSpace);
352 
353  Position startPosition(currentPosition());
354 
355  QChar ch = m_source.currentChar();
356  if (ch.isNull() || ch.isSpace()) {
357  /* skip */
358  } else if (m_source.get_startLine()
359  && m_source.parse(ch_p('#') >> *gr_whiteSpace).hit) {
360  m_source.set_startLine(false);
361 
362  QString directive;
363  m_source.parse(identifier_g[ assign(directive)]); // read the directive
364 
365  handleDirective(directive);
366  } else if (m_source.parse
367  (
368  if_p(var(m_recordComments))
369  [ gr_lineComment | gr_multiLineComment
370  [var(tk) = construct_<Token>(Token_comment, arg1, arg2)]
371  ]
372  .else_p[ gr_lineComment | gr_multiLineComment]
373  | charLiteral_g[assign(tk)]
374  |
375  gr_stringLiteral
376  [var(tk) = construct_<Token>(Token_string_literal, arg1, arg2)]
377  ).hit) {
378  } else if (ch.isLetter() || ch == '_') {
379  CharIterator start = m_source.get_ptr();
380  QString ide;
381  m_source.parse(identifier_g[assign(ide)]);
382  int k = Lookup::find(&keyword, ide);
383  if (k != -1) {
384  tk = m_source.createToken(k, start);
385  } else {
386  tk = m_source.createToken(Token_identifier, start);
387  }
388  } else if (m_source.parse(numberLiteral_g[assign(tk)]
389  | operator_g[ assign(tk)]
390  ).hit) {
391  } else {
392  CharIterator l_ptr = m_source.get_ptr();
393  m_source.nextChar();
394  tk = m_source.createToken(ch.unicode(), l_ptr);
395  }
396  if (m_source.parse(eol_p).hit)
397  m_source.set_startLine(true);
398  else
399  m_source.set_startLine(false);
400 }
401 
402 bool Lexer::tokenize()
403 {
404  if (!m_preprocessLexer.preprocess())
405  return false;
406 #if 0
407  QByteArray l_tmp = m_preprocessLexer.preprocessedString().toAscii();
408  for (int i = 0; i < l_tmp.size(); ++i)
409  std::cout << l_tmp.at(i);
410  std::cout << std::endl;
411 #endif
412  m_source.set_source(m_preprocessLexer.preprocessedString());
413  m_source.set_startLine(true);
414  for (;;) {
415  Token tk;
416  nextToken(tk);
417 
418  if (tk.type() != -1)
419  m_tokens.push_back(tk);
420 
421  if (m_source.currentChar().isNull())
422  break;
423  }
424 
425  Token tk = m_source.createToken(Token_eof, m_source.get_ptr());
426  m_tokens.push_back(tk);
427  return true;
428 }
429 
430 void Lexer::handleDirective(const QString& directive)
431 {
432  Q_UNUSED(directive);
433  assert(directive != "define");
434  assert(directive != "else");
435  assert(directive != "elif");
436  assert(directive != "endif");
437  assert(directive != "if");
438  assert(directive != "ifdef");
439  assert(directive != "ifndef");
440  assert(directive != "include");
441  assert(directive != "undef");
442  assert(0);
443  // skip line
444  m_source.parse(gr_skipTillEol);
445 }
446 
447 // *IMPORTANT*
448 // please, don't include lexer.moc here, because Lexer isn't a QObject class!!
449 // if you have problem while recompiling try to remove cppsupport/.deps,
450 // cppsupport/Makefile.in and rerun automake/autoconf
451 
Lexer::currentPosition
Position currentPosition() const
Definition: lexer.h:75
boost::spirit::classic::impl::isalnum_
bool isalnum_(QChar const &c)
Definition: lexer.cpp:44
Dependency
std::pair< QString, int > Dependency
Definition: lexer.cpp:205
assignFunctor.hpp
Token_concat
Definition: preprocesslexer.h:81
keywords.lut.h
PreprocessLexer::preprocessedString
QString const & preprocessedString() const
Definition: preprocesslexer.h:207
main
int main(int argc, char *argv[])
Definition: docgenerators/main.cpp:42
gr_escapeSequence
PreprocessLexer::CharRule gr_escapeSequence
Definition: preprocesslexer.cpp:1022
lookup.h
identifier_g
identifier identifier_g
Token_ptrmem
Definition: preprocesslexer.h:70
Token_decr
Definition: preprocesslexer.h:78
Token_comment
Definition: preprocesslexer.h:66
PreprocessLexer::setSource
void setSource(const QString &source, const QString &p_filename)
Definition: preprocesslexer.cpp:314
Lexer::Lexer
Lexer(Driver *driver)
Definition: lexer.cpp:316
gr_skipTillEol
Lexer::CharRule gr_skipTillEol
Definition: lexer.cpp:218
operator<<
QDebug operator<<(QDebug out, const Token &t)
Definition: lexer.cpp:249
gr_lineComment
Lexer::CharRule gr_lineComment
Definition: lexer.cpp:216
Token_incr
Definition: preprocesslexer.h:77
debug_utils.h
Token_eq
Definition: preprocesslexer.h:74
boost::spirit::classic::impl::isxdigit_
bool isxdigit_(QChar const &c)
Definition: lexer.cpp:48
Token_leq
Definition: preprocesslexer.h:75
gr_whiteSpace
Lexer::CharRule gr_whiteSpace
Definition: lexer.cpp:215
Token_char_literal
Definition: preprocesslexer.h:63
gr_stringLiteral
Lexer::CharRule gr_stringLiteral
Definition: lexer.cpp:213
Token_arrow
Definition: preprocesslexer.h:79
Position
Definition: position.h:32
Lexer::~Lexer
~Lexer()
Definition: lexer.cpp:324
boost::spirit::classic::impl::isblank_
bool isblank_(QChar const &c)
Definition: lexer.cpp:46
Token_string_literal
Definition: preprocesslexer.h:64
Lookup::find
static int find(const struct HashTable *table, const QString &s)
Find an entry in the table, and return its value (i.e.
Definition: lookup.cpp:83
lexer.h
gr_multiLineComment
Lexer::CharRule gr_multiLineComment
Definition: lexer.cpp:217
Lexer::CharRule
rule< scanner< CharIterator, CharPolicies > > CharRule
Definition: lexer.h:63
boost::spirit::classic::impl::isdigit_
bool isdigit_(QChar const &c)
Definition: lexer.cpp:47
Token::getStartPosition
Position const & getStartPosition() const
Definition: preprocesslexer.h:182
boost::spirit::classic::impl::isalpha_
bool isalpha_(QChar const &c)
Definition: lexer.cpp:45
Driver
Definition: driver.h:161
Token_number_literal
Definition: preprocesslexer.h:62
Lexer::getTokenPosition
Position const & getTokenPosition(const Token &token) const
Definition: lexer.cpp:344
Token_left_shift
Definition: preprocesslexer.h:73
Token_assign
Definition: preprocesslexer.h:69
Lexer::setSource
bool setSource(const QString &source, const QString &p_filename)
Definition: lexer.cpp:328
constructQString
const function< constructQString_impl > constructQString
Definition: lexer.cpp:109
charLiteral_g
charLiteral charLiteral_g
Token::type
int type() const
Definition: preprocesslexer.h:180
Token_identifier
Definition: preprocesslexer.h:61
SkipRule
rule< scanner< CharIterator > > SkipRule
Definition: lexer.h:52
PreprocessLexer::preprocess
bool preprocess()
Definition: preprocesslexer.cpp:621
Token::getEndPosition
Position const & getEndPosition() const
Definition: preprocesslexer.h:183
Token
Definition: preprocesslexer.h:168
numberLiteral_g
numberLiteral numberLiteral_g
Token::text
QString const & text() const
Definition: preprocesslexer.h:186
QThread
Token_or
Definition: preprocesslexer.h:133
Token_ellipsis
Definition: preprocesslexer.h:71
operator_g
operator_ operator_g
Token_and
Definition: preprocesslexer.h:92
keyword
static const struct HashTable keyword
Definition: keywords.lut.h:123
Token::Token
Token()
Definition: lexer.cpp:222
Token_scope
Definition: preprocesslexer.h:72
Token_eof
Definition: preprocesslexer.h:60
CharIterator
Definition: position.h:75
QList
Token_geq
Definition: preprocesslexer.h:76
Token::operator=
Token & operator=(Token const &p)
Definition: lexer.cpp:238
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:06:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

umbrello/umbrello

Skip menu "umbrello/umbrello"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdesdk API Reference

Skip menu "kdesdk API Reference"
  • kapptemplate
  • kcachegrind
  • kompare
  • lokalize
  • okteta
  • umbrello
  •   umbrello

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal