Libksieve

impl/lexer.h
1 /* -*- c++ -*-
2  impl/lexer.h
3 
4  Internal header file. Subject to change without notice. DO NOT USE.
5 
6  This file is part of KSieve,
7  the KDE internet mail/usenet news message filtering library.
8  SPDX-FileCopyrightText: 2003 Marc Mutz <[email protected]>
9 
10  SPDX-License-Identifier: GPL-2.0-only
11 */
12 
13 #pragma once
14 
15 #include <ksieve/error.h>
16 #include <ksieve/lexer.h>
17 
18 #include <QStack>
19 
20 namespace KSieve
21 {
22 class Lexer::Impl
23 {
24 public:
25  Impl(const char *scursor, const char *send, int options);
26 
27  bool ignoreComments() const
28  {
29  return mIgnoreComments;
30  }
31 
32  bool ignoreLineFeeds() const
33  {
34  return mIgnoreLF;
35  }
36 
37  const Error &error() const
38  {
39  return mState.error;
40  }
41 
42  bool atEnd() const
43  {
44  return mState.cursor >= mEnd;
45  }
46 
47  int column() const
48  {
49  return mState.cursor - mState.beginOfLine;
50  }
51 
52  int line() const
53  {
54  return mState.line;
55  }
56 
57  void save()
58  {
59  mStateStack.push(mState);
60  }
61 
62  void restore()
63  {
64  mState = mStateStack.pop();
65  }
66 
67  Lexer::Token nextToken(QString &tokenValue);
68 
69 private:
70  /** Cursor must be positioned on the \r or the \n. */
71  bool eatCRLF();
72 
73  /** Cursor must be positioned after the opening hash (#). If
74  parsing is successful, cursor is positioned behind the CRLF
75  that ended the comment's line (or past the end). */
76  bool parseHashComment(QString &result, bool reallySave = false);
77 
78  /** Cursor must be positioned after the opening slash-asterisk */
79  bool parseBracketComment(QString &result, bool reallySave = false);
80 
81  /** Cursor must be positioned on the opening '/'or '#' */
82  bool parseComment(QString &result, bool reallySave = false);
83 
84  /** Eats whitespace, but not comments */
85  bool eatWS();
86 
87  /** Eats comments and whitespace */
88  bool eatCWS();
89 
90  /** Cursor must be positioned on the first character */
91  bool parseIdentifier(QString &result);
92 
93  /** Cursor must be positioned after the initial ':' */
94  bool parseTag(QString &result);
95 
96  /** Cursor must be positioned on the first digit */
97  bool parseNumber(QString &result);
98 
99  /** Cursor must be positioned after the "text:" token. */
100  bool parseMultiLine(QString &result);
101 
102  /** Cursor must be positioned after the initial " */
103  bool parseQuotedString(QString &result);
104 
105  struct State {
106  State(const char *s = nullptr)
107  : cursor(s)
108  , beginOfLine(s)
109  , error()
110  {
111  }
112 
113  const char *cursor;
114  int line = 0;
115  const char *beginOfLine;
116  Error error;
117  } mState;
118 
119  const char *const mEnd;
120  const bool mIgnoreComments : 1;
121  const bool mIgnoreLF : 1;
122  QStack<State> mStateStack;
123 
124  const char *beginOfLine() const
125  {
126  return mState.beginOfLine;
127  }
128 
129  int _strnicmp(const char *left, const char *right, size_t len) const
130  {
131  return charsLeft() >= len ? qstrnicmp(left, right, len) : 1;
132  }
133 
134  void clearErrors()
135  {
136  mState.error = Error();
137  }
138 
139  unsigned int charsLeft() const
140  {
141  return mEnd - mState.cursor < 0 ? 0 : mEnd - mState.cursor;
142  }
143 
144  void makeError(Error::Type e)
145  {
146  makeError(e, line(), column());
147  }
148 
149  void makeError(Error::Type e, int errorLine, int errorCol)
150  {
151  mState.error = Error(e, errorLine, errorCol);
152  }
153 
154  void makeIllegalCharError(char ch);
155  void makeIllegalCharError()
156  {
157  makeIllegalCharError(*mState.cursor);
158  }
159 
160  /** Defines the current char to end a line.
161  Warning: increases @p mCursor!
162  **/
163  void newLine()
164  {
165  ++mState.line;
166  mState.beginOfLine = ++mState.cursor;
167  }
168 
169  bool skipTo(char c, bool acceptEnd = false)
170  {
171  while (!atEnd()) {
172  if (*mState.cursor == '\n' || *mState.cursor == '\r') {
173  if (!eatCRLF()) {
174  return false;
175  }
176  } else if (*mState.cursor == c) {
177  return true;
178  } else {
179  ++mState.cursor;
180  }
181  }
182  return acceptEnd;
183  }
184 
185  bool skipToCRLF(bool acceptEnd = true)
186  {
187  for (; !atEnd(); ++mState.cursor) {
188  if (*mState.cursor == '\n' || *mState.cursor == '\r') {
189  return eatCRLF();
190  }
191  }
192  return acceptEnd;
193  }
194 
195  void skipTo8BitEnd()
196  {
197  while (!atEnd() && (signed char)*mState.cursor < 0) {
198  ++mState.cursor;
199  }
200  }
201 
202  void skipToDelim();
203 };
204 }
205 
void error(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
const QList< QKeySequence > & save()
State
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Apr 16 2021 23:09:33 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.