]> git.lyx.org Git - lyx.git/blob - src/Lexer.h
introduce a header to forward declare std::string.
[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
22 #include <iosfwd>
23
24
25 namespace lyx {
26
27 namespace support { class FileName; }
28
29 ///
30 struct keyword_item {
31         ///
32         char const * tag;
33         ///
34         int code;
35 };
36
37 /** Generalized simple lexical analizer.
38         Use the method isOK() to check if there is still data available
39         for lexing. Use one of the the operators void* or ! to test if
40         the last reading operation was successful.
41
42         Example:
43
44         int readParam(LyxLex &lex) {
45                 int param = 1; // default value
46                 if (lex.isOK()) { // the lexer has data to read
47                         int p;    // temporary variable
48                         lex >> p;
49                         if (lex) param = p; // only use the input if reading was successful
50                 }
51                 return param;
52         }
53
54     @see LyXRC.cpp for an example of usage.
55   */
56 class Lexer {
57 public:
58         ///
59         Lexer(keyword_item *, int);
60         ///
61         ~Lexer();
62
63         /// Lex basic codes
64         enum {
65                 ///
66                 LEX_UNDEF = -1,
67                 ///
68                 LEX_FEOF  = -2,
69                 ///
70                 LEX_DATA  = -3,
71                 ///
72                 LEX_TOKEN = -4
73         };
74
75         /// stream is open and end of stream is not reached
76         /// FIXME: test also if pushTok is not empty
77         /// FIXME: the method should be renamed to something like
78         ///        dataAvailable(), in order to reflect the real behavior
79         bool isOK() const;
80         /// FIXME: The next two operators should be replaced by one method
81         ///        called e.g. lastReadOk(), in order to reflect the real
82         ///        behavior
83         /// last read operation was successful.
84         operator void const *() const;
85         /// last read operation was not successful
86         bool operator!() const;
87         /// return true if able to open file, else false
88         bool setFile(support::FileName const & filename);
89         ///
90         void setStream(std::istream & is);
91         ///
92         std::istream & getStream();
93         /// Danger! Don't use it unless you know what you are doing.
94         void setLineNo(int l);
95         /// Change the character that begins a comment. Default is '#'
96         void setCommentChar(char c);
97
98         /// returns a lex code
99         int lex();
100
101         /** Just read the next word. If esc is true remember that
102             some chars might be escaped: "\ atleast
103         */
104         bool next(bool esc = false);
105
106         /** Read next token. This one is almost the same as next,
107             but it will consider " as a regular character and always
108             split a word if it contains a backslash.
109         */
110         bool nextToken();
111         /// Push a token, that next token got from lyxlex.
112         void pushToken(std::string const &);
113
114         ///
115         int getLineNo() const;
116
117         ///
118         int getInteger() const;
119         ///
120         bool getBool() const;
121         ///
122         double getFloat() const;
123         ///
124         std::string const getString() const;
125
126         ///
127         docstring const getDocString() const;
128
129         /** Get a long string, ended by the tag `endtag'.
130             This string can span several lines. The first line
131             serves as a template for how many spaces the lines
132             are indented. This much white space is skipped from
133             each following line. This mechanism does not work
134             perfectly if you use tabs.
135         */
136         std::string const getLongString(std::string const & endtag);
137
138         ///
139         bool eatLine();
140
141         /// Pushes a token list on a stack and replaces it with a new one.
142         void pushTable(keyword_item *, int);
143
144         /** Pops a token list into void and replaces it with the one now
145             on top of the stack.
146         */
147         void popTable();
148
149         /** Prints an error message with the corresponding line number
150             and file name. If message contains the substring `$$Token',
151             it is replaced with the value of GetString()
152         */
153         void printError(std::string const & message) const;
154
155         /// Prints the current token table on the supplied ostream.
156         void printTable(std::ostream &);
157
158         /// extract string
159         Lexer & operator>>(std::string &);
160         /// extract docstring
161         Lexer & operator>>(docstring &);
162         /// extract double
163         Lexer & operator>>(double &);
164         /// extract integer
165         Lexer & operator>>(int &);
166         /// extract unsigned integer
167         Lexer & operator>>(unsigned int &);
168         /// extract bool
169         Lexer & operator>>(bool &);
170
171         /// Quotes a string so that reading it again with Lexer::next(true)
172         /// gets the original string
173         static std::string const quoteString(std::string const &);
174
175 private:
176         /// noncopiable
177         Lexer(Lexer const &);
178         void operator=(Lexer const &);
179
180         ///
181         class Pimpl;
182         ///
183         Pimpl * pimpl_;
184         ///
185         mutable bool lastReadOk_;
186 };
187
188
189 /** Use to enable multiple exit points.
190     This is needed to ensure that the pop is done upon exit from methods
191     with more than one exit point or that can return as a response to
192     exceptions.
193     @author Lgb
194 */
195 class PushPopHelper {
196 public:
197         ///
198         PushPopHelper(Lexer & lexrc, keyword_item * i, int s) : lex(lexrc) {
199                 lex.pushTable(i, s);
200         }
201         ///
202         ~PushPopHelper() {
203                 lex.popTable();
204         }
205         ///
206         Lexer & lex;
207 };
208 /** Avoid wrong usage of PushPopHelper.
209     To avoid wrong usage:
210     PushPopHelper(...); // wrong
211     PushPopHelper pph(...); // right
212 */
213 #define PushPopHelper(x, y, z) unnamed_PushPopHelper;
214 // Tip gotten from Bobby Schmidt's column in C/C++ Users Journal
215
216
217 } // namespace lyx
218
219 #endif