]> git.lyx.org Git - lyx.git/blob - src/Lexer.h
Update Win installer for new dictionary links. Untested.
[lyx.git] / src / Lexer.h
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.
6  *
7  * \author Alejandro Aguilar Sierra
8  * \author Lars Gullik Bjønnes
9  *
10  * Full author contact details are available in file CREDITS.
11  */
12
13 //  Generalized simple lexical analizer.
14 //  It can be used for simple syntax parsers, like lyxrc,
15 //  texclass and others to come.
16
17 #ifndef LEXER_H
18 #define LEXER_H
19
20 #include "support/strfwd.h"
21 #include <string>
22
23 namespace lyx {
24
25 namespace support { class FileName; }
26
27 /** A helper structure to describe a keyword for the Lexer.
28         Usually used bundled in C style arrays and passed to the
29         Lexer using a LexerKeywordTable object.
30 */
31 struct LexerKeyword
32 {
33         /// the string to be recognized
34         char const * tag;
35         /// a corresponding numerical id
36         int code;
37 };
38
39
40 /** Generalized simple lexical analizer.
41         Use the method isOK() to check if there is still data available
42         for lexing. Use one of the the operators void* or ! to test if
43         the last reading operation was successful.
44
45         Example:
46
47         int readParam(LyxLex & lex)
48         {
49                 int param = 1;    // default value
50                 if (lex.isOK()) { // the lexer has data to read
51                         int p;          // temporary variable
52                         lex >> p;
53                         if (lex)
54                                 param = p; // only use the input if reading was successful
55                 }
56                 return param;
57         }
58
59     @see LyXRC.cpp for an example of usage.
60   */
61 class Lexer
62 {
63 public:
64         /// initialize Lexer with no special keywords.
65         Lexer();
66         /// initialize Lexer with a bunch of keywords
67         template<int N> Lexer(LexerKeyword (&table)[N])
68         : pimpl_(0), lastReadOk_(false) { init(table, N); }
69
70         ///
71         ~Lexer();
72
73         /// Lex basic codes
74         enum {
75                 ///
76                 LEX_UNDEF = -1,
77                 ///
78                 LEX_FEOF  = -2,
79                 ///
80                 LEX_DATA  = -3,
81                 ///
82                 LEX_TOKEN = -4
83         };
84
85         /// stream is open and end of stream is not reached
86         /// FIXME: test also if pushToken is not empty
87         /// FIXME: the method should be renamed to something like
88         ///        dataAvailable(), in order to reflect the real behavior
89         bool isOK() const;
90         /// FIXME: The next two operators should be replaced by one method
91         ///        called e.g. lastReadOk(), in order to reflect the real
92         ///        behavior
93         /// last read operation was successful.
94         operator void const *() const;
95         /// last read operation was not successful
96         bool operator!() const;
97         /// return true if able to open file, else false
98         bool setFile(support::FileName const & filename);
99         ///
100         void setStream(std::istream & is);
101         ///
102         std::istream & getStream();
103         /// Danger! Don't use it unless you know what you are doing.
104         void setLineNumber(int l);
105         /// Change the character that begins a comment. Default is '#'
106         void setCommentChar(char c);
107
108         /// returns a lex code
109         int lex();
110
111         /// Read the next string, as delimited by double quotes or
112         /// whitespace. If esc is true, then we remember that some chars
113         /// might be escaped: \" at least.
114         bool next(bool esc = false);
115
116         /// Read next token. This one is almost the same as next(),
117         /// but it will consider " as a regular character and always
118         /// split a word if it contains a backslash.
119         bool nextToken();
120
121         /// Puts the rest of the line in the buffer, where it will
122         /// be available via getString() or getDocString().
123         bool eatLine();
124
125         /// Push a token, that next token got from lyxlex.
126         void pushToken(std::string const &);
127
128         /// return the current line number
129         int lineNumber() const;
130
131         ///
132         int getInteger() const;
133         ///
134         bool getBool() const;
135         ///
136         double getFloat() const;
137         ///
138         std::string const getString(bool trim = false) const;
139         ///
140         docstring const getDocString(bool trim = false) const;
141         /** Get a long string, ended by the tag `endtoken'. This string
142             can span several lines. The first line serves as a template
143             for what sequence of tabs and spaces make up the indentation.
144             This prefix is skipped from each following line.
145         */
146         docstring getLongString(docstring const & endtoken);
147
148         /// Pushes a token list on a stack and replaces it with a new one.
149         template<int N> void pushTable(LexerKeyword (&table)[N])
150                 { pushTable(table, N); }
151
152         /** Pops a token list into void and replaces it with the one now
153             on top of the stack.
154         */
155         void popTable();
156
157         /** Prints an error message with the corresponding line number
158             and file name. If message contains the substring `$$Token',
159             it is replaced with the value of GetString()
160         */
161         void printError(std::string const & message) const;
162
163         /// Prints the current token table on the supplied ostream.
164         void printTable(std::ostream &);
165         /// Used to dispaly context information in case of errors.
166         void setContext(std::string const & functionName);
167
168         /// extract string
169         Lexer & operator>>(std::string &);
170         /// extract docstring
171         Lexer & operator>>(docstring &);
172         /// extract double
173         Lexer & operator>>(double &);
174         /// extract integer
175         Lexer & operator>>(int &);
176         /// extract unsigned integer
177         Lexer & operator>>(unsigned int &);
178         /// extract bool
179         Lexer & operator>>(bool &);
180         /// extract first char of the string
181         Lexer & operator>>(char &);
182
183         /// read and check a required token
184         Lexer & operator>>(char const * required);
185         /// check for an optional token and swallow it if present.
186         bool checkFor(char const * required);
187
188         /// Quotes a string so that reading it again with Lexer::next(true)
189         /// gets the original string
190         static std::string quoteString(std::string const &);
191         /// Quotes a docstring so that reading it again with Lexer::next(true)
192         /// gets the original string
193         static docstring quoteString(docstring const &);
194
195 private:
196         /// noncopyable
197         Lexer(Lexer const &);
198         void operator=(Lexer const &);
199
200         ///
201         friend class PushPopHelper;
202
203         ///
204         void init(LexerKeyword *, int);
205         void pushTable(LexerKeyword *, int);
206
207         ///
208         class Pimpl;
209         ///
210         Pimpl * pimpl_;
211         ///
212         mutable bool lastReadOk_;
213 };
214
215
216 /// extract something constructable from a string, i.e. a LaTeX length
217 template <class T>
218 Lexer & operator>>(Lexer & lex, T & t)
219 {
220         if (lex.next())
221                 t = T(lex.getString());
222         return lex;
223 }
224
225
226 /** Use to enable multiple exit points.
227     This is needed to ensure that the pop is done upon exit from methods
228     with more than one exit point or that can return as a response to
229     exceptions.
230     @author Lgb
231 */
232 class PushPopHelper
233 {
234 public:
235         ///
236         template<int N>
237         PushPopHelper(Lexer & l, LexerKeyword (&table)[N])
238                 : lex(l)
239         {
240                 lex.pushTable(table, N);
241         }
242         ///
243         ~PushPopHelper()
244         {
245                 lex.popTable();
246         }
247         ///
248         Lexer & lex;
249 };
250 /** Avoid wrong usage of PushPopHelper.
251     To avoid wrong usage:
252     PushPopHelper(...); // wrong
253     PushPopHelper pph(...); // right
254 */
255 #define PushPopHelper(x, y, z) unnamed_PushPopHelper;
256 // Tip gotten from Bobby Schmidt's column in C/C++ Users Journal
257
258
259 } // namespace lyx
260
261 #endif