This more or less completes the re-implementation of this class. The
[lyx.git] / src / Lexer.h
blobba085ed0e426e1528679cf852968da9ca9ca89be
1 // -*- C++ -*-
2 /**
3 * \file Lexer.h
4 * This file is part of LyX, the document processor.
5 * Licence details can be found in the file COPYING.
7 * \author Alejandro Aguilar Sierra
8 * \author Lars Gullik Bjønnes
10 * Full author contact details are available in file CREDITS.
13 // Generalized simple lexical analizer.
14 // It can be used for simple syntax parsers, like lyxrc,
15 // texclass and others to come.
17 #ifndef LEXER_H
18 #define LEXER_H
20 #include "support/strfwd.h"
23 namespace lyx {
25 namespace support { class FileName; }
27 class PushPopHelper;
29 /** A helper structure to describe a keyword for the Lexer.
30 Usually used bundled in C style arrays and passed to the
31 Lexer using a LexerKeywordTable object.
33 struct LexerKeyword
35 /// the string to be recognized
36 char const * tag;
37 /// a corresponding numerical id
38 int code;
42 /** Generalized simple lexical analizer.
43 Use the method isOK() to check if there is still data available
44 for lexing. Use one of the the operators void* or ! to test if
45 the last reading operation was successful.
47 Example:
49 int readParam(LyxLex & lex)
51 int param = 1; // default value
52 if (lex.isOK()) { // the lexer has data to read
53 int p; // temporary variable
54 lex >> p;
55 if (lex)
56 param = p; // only use the input if reading was successful
58 return param;
61 @see LyXRC.cpp for an example of usage.
63 class Lexer
65 public:
66 /// initialize Lexer with no special keywords.
67 Lexer();
68 /// initialize Lexer with a bunch of keywords
69 template<int N> Lexer(LexerKeyword (&table)[N])
70 : pimpl_(0) { init(table, N); }
72 ///
73 ~Lexer();
75 /// Lex basic codes
76 enum {
77 ///
78 LEX_UNDEF = -1,
79 ///
80 LEX_FEOF = -2,
81 ///
82 LEX_DATA = -3,
83 ///
84 LEX_TOKEN = -4
87 /// stream is open and end of stream is not reached
88 /// FIXME: test also if pushToken is not empty
89 /// FIXME: the method should be renamed to something like
90 /// dataAvailable(), in order to reflect the real behavior
91 bool isOK() const;
92 /// FIXME: The next two operators should be replaced by one method
93 /// called e.g. lastReadOk(), in order to reflect the real
94 /// behavior
95 /// last read operation was successful.
96 operator void const *() const;
97 /// last read operation was not successful
98 bool operator!() const;
99 /// return true if able to open file, else false
100 bool setFile(support::FileName const & filename);
102 void setStream(std::istream & is);
104 std::istream & getStream();
105 /// Danger! Don't use it unless you know what you are doing.
106 void setLineNumber(int l);
107 /// Change the character that begins a comment. Default is '#'
108 void setCommentChar(char c);
110 /// returns a lex code
111 int lex();
113 /** Just read the next word. If esc is true remember that
114 some chars might be escaped: "\ at least
116 bool next(bool esc = false);
118 /** Read next token. This one is almost the same as next,
119 but it will consider " as a regular character and always
120 split a word if it contains a backslash.
122 bool nextToken();
123 /// Push a token, that next token got from lyxlex.
124 void pushToken(std::string const &);
126 /// return the current line number
127 int lineNumber() const;
130 int getInteger() const;
132 bool getBool() const;
134 double getFloat() const;
136 std::string const getString() const;
139 docstring const getDocString() const;
141 /** Get a long string, ended by the tag `endtag'.
142 This string can span several lines. The first line
143 serves as a template for how many spaces the lines
144 are indented. This much white space is skipped from
145 each following line. This mechanism does not work
146 perfectly if you use tabs.
148 std::string const getLongString(std::string const & endtag);
151 bool eatLine();
153 /// Pushes a token list on a stack and replaces it with a new one.
154 template<int N> void pushTable(LexerKeyword (&table)[N])
155 { pushTable(table, N); }
157 /** Pops a token list into void and replaces it with the one now
158 on top of the stack.
160 void popTable();
162 /** Prints an error message with the corresponding line number
163 and file name. If message contains the substring `$$Token',
164 it is replaced with the value of GetString()
166 void printError(std::string const & message) const;
168 /// Prints the current token table on the supplied ostream.
169 void printTable(std::ostream &);
170 /// Used to dispaly context information in case of errors.
171 void setContext(std::string const & functionName);
173 /// extract string
174 Lexer & operator>>(std::string &);
175 /// extract docstring
176 Lexer & operator>>(docstring &);
177 /// extract double
178 Lexer & operator>>(double &);
179 /// extract integer
180 Lexer & operator>>(int &);
181 /// extract unsigned integer
182 Lexer & operator>>(unsigned int &);
183 /// extract bool
184 Lexer & operator>>(bool &);
185 /// extract first char of the string
186 Lexer & operator>>(char &);
188 /// read and check a required token
189 Lexer & operator>>(char const * required);
190 /// check for an optional token and swallow it if present.
191 bool checkFor(char const * required);
193 /// Quotes a string so that reading it again with Lexer::next(true)
194 /// gets the original string
195 static std::string quoteString(std::string const &);
196 /// Quotes a docstring so that reading it again with Lexer::next(true)
197 /// gets the original string
198 static docstring quoteString(docstring const &);
200 private:
201 /// noncopyable
202 Lexer(Lexer const &);
203 void operator=(Lexer const &);
206 friend class PushPopHelper;
209 void init(LexerKeyword *, int);
210 void pushTable(LexerKeyword *, int);
213 class Pimpl;
215 Pimpl * pimpl_;
217 mutable bool lastReadOk_;
221 /// extract something constructable from a string, i.e. a LaTeX length
222 template <class T>
223 Lexer & operator>>(Lexer & lex, T & t)
225 if (lex.next())
226 t = T(lex.getString());
227 return lex;
231 /** Use to enable multiple exit points.
232 This is needed to ensure that the pop is done upon exit from methods
233 with more than one exit point or that can return as a response to
234 exceptions.
235 @author Lgb
237 class PushPopHelper
239 public:
241 template<int N>
242 PushPopHelper(Lexer & l, LexerKeyword (&table)[N])
243 : lex(l)
245 lex.pushTable(table, N);
248 ~PushPopHelper()
250 lex.popTable();
253 Lexer & lex;
255 /** Avoid wrong usage of PushPopHelper.
256 To avoid wrong usage:
257 PushPopHelper(...); // wrong
258 PushPopHelper pph(...); // right
260 #define PushPopHelper(x, y, z) unnamed_PushPopHelper;
261 // Tip gotten from Bobby Schmidt's column in C/C++ Users Journal
264 } // namespace lyx
266 #endif