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.
20 #include "support/strfwd.h"
25 namespace support { class FileName; }
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.
35 /// the string to be recognized
37 /// a corresponding numerical id
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.
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
56 param = p; // only use the input if reading was successful
61 @see LyXRC.cpp for an example of usage.
66 /// initialize Lexer with no special keywords.
68 /// initialize Lexer with a bunch of keywords
69 template<int N> Lexer(LexerKeyword (&table)[N])
70 : pimpl_(0), lastReadOk_(false) { init(table, N); }
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
92 /// FIXME: The next two operators should be replaced by one method
93 /// called e.g. lastReadOk(), in order to reflect the real
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
113 /// Read the next string, as delimited by double quotes or
114 /// whitespace. If esc is true, then we remember that some chars
115 /// 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.
123 /// Puts the rest of the line in the buffer, where it will
124 /// be available via getString() or getDocString().
127 /// Push a token, that next token got from lyxlex.
128 void pushToken(std::string const &);
130 /// return the current line number
131 int lineNumber() const;
134 int getInteger() const;
136 bool getBool() const;
138 double getFloat() const;
140 std::string const getString(bool trim = false) const;
142 docstring const getDocString(bool trim = false) const;
143 /** Get a long string, ended by the tag `endtag'.
144 This string can span several lines. The first line
145 serves as a template for how many spaces the lines
146 are indented. This much white space is skipped from
147 each following line. This mechanism does not work
148 perfectly if you use tabs.
150 std::string const getLongString(std::string const & endtag);
152 /// Pushes a token list on a stack and replaces it with a new one.
153 template<int N> void pushTable(LexerKeyword (&table)[N])
154 { pushTable(table, N); }
156 /** Pops a token list into void and replaces it with the one now
161 /** Prints an error message with the corresponding line number
162 and file name. If message contains the substring `$$Token',
163 it is replaced with the value of GetString()
165 void printError(std::string const & message) const;
167 /// Prints the current token table on the supplied ostream.
168 void printTable(std::ostream &);
169 /// Used to dispaly context information in case of errors.
170 void setContext(std::string const & functionName);
173 Lexer & operator>>(std::string &);
174 /// extract docstring
175 Lexer & operator>>(docstring &);
177 Lexer & operator>>(double &);
179 Lexer & operator>>(int &);
180 /// extract unsigned integer
181 Lexer & operator>>(unsigned int &);
183 Lexer & operator>>(bool &);
184 /// extract first char of the string
185 Lexer & operator>>(char &);
187 /// read and check a required token
188 Lexer & operator>>(char const * required);
189 /// check for an optional token and swallow it if present.
190 bool checkFor(char const * required);
192 /// Quotes a string so that reading it again with Lexer::next(true)
193 /// gets the original string
194 static std::string quoteString(std::string const &);
195 /// Quotes a docstring so that reading it again with Lexer::next(true)
196 /// gets the original string
197 static docstring quoteString(docstring const &);
201 Lexer(Lexer const &);
202 void operator=(Lexer const &);
205 friend class PushPopHelper;
208 void init(LexerKeyword *, int);
209 void pushTable(LexerKeyword *, int);
216 mutable bool lastReadOk_;
220 /// extract something constructable from a string, i.e. a LaTeX length
222 Lexer & operator>>(Lexer & lex, T & t)
225 t = T(lex.getString());
230 /** Use to enable multiple exit points.
231 This is needed to ensure that the pop is done upon exit from methods
232 with more than one exit point or that can return as a response to
241 PushPopHelper(Lexer & l, LexerKeyword (&table)[N])
244 lex.pushTable(table, N);
254 /** Avoid wrong usage of PushPopHelper.
255 To avoid wrong usage:
256 PushPopHelper(...); // wrong
257 PushPopHelper pph(...); // right
259 #define PushPopHelper(x, y, z) unnamed_PushPopHelper;
260 // Tip gotten from Bobby Schmidt's column in C/C++ Users Journal