OSDN Git Service

Fix defer/recover at high optimization levels.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / lex.h
1 // lex.h -- Go frontend lexer.     -*- C++ -*-
2
3 // Copyright 2009 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 #ifndef GO_LEX_H
8 #define GO_LEX_H
9
10 #include <gmp.h>
11 #include <mpfr.h>
12
13 #include "operator.h"
14
15 struct Unicode_range;
16
17 // The keywords.  These must be in sorted order, other than
18 // KEYWORD_INVALID.  They must match the Keywords::mapping_ array in
19 // lex.cc.
20
21 enum Keyword
22 {
23   KEYWORD_INVALID,      // Not a keyword.
24   KEYWORD_ASM,
25   KEYWORD_BREAK,
26   KEYWORD_CASE,
27   KEYWORD_CHAN,
28   KEYWORD_CONST,
29   KEYWORD_CONTINUE,
30   KEYWORD_DEFAULT,
31   KEYWORD_DEFER,
32   KEYWORD_ELSE,
33   KEYWORD_FALLTHROUGH,
34   KEYWORD_FOR,
35   KEYWORD_FUNC,
36   KEYWORD_GO,
37   KEYWORD_GOTO,
38   KEYWORD_IF,
39   KEYWORD_IMPORT,
40   KEYWORD_INTERFACE,
41   KEYWORD_MAP,
42   KEYWORD_PACKAGE,
43   KEYWORD_RANGE,
44   KEYWORD_RETURN,
45   KEYWORD_SELECT,
46   KEYWORD_STRUCT,
47   KEYWORD_SWITCH,
48   KEYWORD_TYPE,
49   KEYWORD_VAR
50 };
51
52 // A token returned from the lexer.
53
54 class Token
55 {
56  public:
57   // Token classification.
58   enum Classification
59   {
60     // Token is invalid.
61     TOKEN_INVALID,
62     // Token indicates end of input.
63     TOKEN_EOF,
64     // Token is a keyword.
65     TOKEN_KEYWORD,
66     // Token is an identifier.
67     TOKEN_IDENTIFIER,
68     // Token is a string of characters.
69     TOKEN_STRING,
70     // Token is an operator.
71     TOKEN_OPERATOR,
72     // Token is an integer.
73     TOKEN_INTEGER,
74     // Token is a floating point number.
75     TOKEN_FLOAT,
76     // Token is an imaginary number.
77     TOKEN_IMAGINARY
78   };
79
80   ~Token();
81   Token(const Token&);
82   Token& operator=(const Token&);
83
84   // Get token classification.
85   Classification
86   classification() const
87   { return this->classification_; }
88
89   // Make a token for an invalid value.
90   static Token
91   make_invalid_token(source_location location)
92   { return Token(TOKEN_INVALID, location); }
93
94   // Make a token representing end of file.
95   static Token
96   make_eof_token(source_location location)
97   { return Token(TOKEN_EOF, location); }
98
99   // Make a keyword token.
100   static Token
101   make_keyword_token(Keyword keyword, source_location location)
102   {
103     Token tok(TOKEN_KEYWORD, location);
104     tok.u_.keyword = keyword;
105     return tok;
106   }
107
108   // Make an identifier token.
109   static Token
110   make_identifier_token(const std::string& value, bool is_exported,
111                         source_location location)
112   {
113     Token tok(TOKEN_IDENTIFIER, location);
114     tok.u_.identifier_value.name = new std::string(value);
115     tok.u_.identifier_value.is_exported = is_exported;
116     return tok;
117   }
118
119   // Make a quoted string token.
120   static Token
121   make_string_token(const std::string& value, source_location location)
122   {
123     Token tok(TOKEN_STRING, location);
124     tok.u_.string_value = new std::string(value);
125     return tok;
126   }
127
128   // Make an operator token.
129   static Token
130   make_operator_token(Operator op, source_location location)
131   {
132     Token tok(TOKEN_OPERATOR, location);
133     tok.u_.op = op;
134     return tok;
135   }
136
137   // Make an integer token.
138   static Token
139   make_integer_token(mpz_t val, source_location location)
140   {
141     Token tok(TOKEN_INTEGER, location);
142     mpz_init(tok.u_.integer_value);
143     mpz_swap(tok.u_.integer_value, val);
144     return tok;
145   }
146
147   // Make a float token.
148   static Token
149   make_float_token(mpfr_t val, source_location location)
150   {
151     Token tok(TOKEN_FLOAT, location);
152     mpfr_init(tok.u_.float_value);
153     mpfr_swap(tok.u_.float_value, val);
154     return tok;
155   }
156
157   // Make a token for an imaginary number.
158   static Token
159   make_imaginary_token(mpfr_t val, source_location location)
160   {
161     Token tok(TOKEN_IMAGINARY, location);
162     mpfr_init(tok.u_.float_value);
163     mpfr_swap(tok.u_.float_value, val);
164     return tok;
165   }
166
167   // Get the location of the token.
168   source_location
169   location() const
170   { return this->location_; }
171
172   // Return whether this is an invalid token.
173   bool
174   is_invalid() const
175   { return this->classification_ == TOKEN_INVALID; }
176
177   // Return whether this is the EOF token.
178   bool
179   is_eof() const
180   { return this->classification_ == TOKEN_EOF; }
181
182   // Return the keyword value for a keyword token.
183   Keyword
184   keyword() const
185   {
186     go_assert(this->classification_ == TOKEN_KEYWORD);
187     return this->u_.keyword;
188   }
189
190   // Return whether this is an identifier.
191   bool
192   is_identifier() const
193   { return this->classification_ == TOKEN_IDENTIFIER; }
194
195   // Return the identifier.
196   const std::string&
197   identifier() const
198   {
199     go_assert(this->classification_ == TOKEN_IDENTIFIER);
200     return *this->u_.identifier_value.name;
201   }
202
203   // Return whether the identifier is exported.
204   bool
205   is_identifier_exported() const
206   {
207     go_assert(this->classification_ == TOKEN_IDENTIFIER);
208     return this->u_.identifier_value.is_exported;
209   }
210
211   // Return whether this is a string.
212   bool
213   is_string() const
214   {
215     return this->classification_ == TOKEN_STRING;
216   }
217
218   // Return the value of a string.  The returned value is a string of
219   // UTF-8 characters.
220   std::string
221   string_value() const
222   {
223     go_assert(this->classification_ == TOKEN_STRING);
224     return *this->u_.string_value;
225   }
226
227   // Return the value of an integer.
228   const mpz_t*
229   integer_value() const
230   {
231     go_assert(this->classification_ == TOKEN_INTEGER);
232     return &this->u_.integer_value;
233   }
234
235   // Return the value of a float.
236   const mpfr_t*
237   float_value() const
238   {
239     go_assert(this->classification_ == TOKEN_FLOAT);
240     return &this->u_.float_value;
241   }
242
243   // Return the value of an imaginary number.
244   const mpfr_t*
245   imaginary_value() const
246   {
247     go_assert(this->classification_ == TOKEN_IMAGINARY);
248     return &this->u_.float_value;
249   }
250
251   // Return the operator value for an operator token.
252   Operator
253   op() const
254   {
255     go_assert(this->classification_ == TOKEN_OPERATOR);
256     return this->u_.op;
257   }
258
259   // Return whether this token is KEYWORD.
260   bool
261   is_keyword(Keyword keyword) const
262   {
263     return (this->classification_ == TOKEN_KEYWORD
264             && this->u_.keyword == keyword);
265   }
266
267   // Return whether this token is OP.
268   bool
269   is_op(Operator op) const
270   { return this->classification_ == TOKEN_OPERATOR && this->u_.op == op; }
271
272   // Print the token for debugging.
273   void
274   print(FILE*) const;
275
276  private:
277   // Private constructor used by make_..._token functions above.
278   Token(Classification, source_location);
279
280   // Clear the token.
281   void
282   clear();
283
284   // The token classification.
285   Classification classification_;
286   union
287   {
288     // The keyword value for TOKEN_KEYWORD.
289     Keyword keyword;
290     // The token value for TOKEN_IDENTIFIER.
291     struct
292     {
293       // The name of the identifier.  This has been mangled to only
294       // include ASCII characters.
295       std::string* name;
296       // Whether this name should be exported.  This is true if the
297       // first letter in the name is upper case.
298       bool is_exported;
299     } identifier_value;
300     // The string value for TOKEN_STRING.
301     std::string* string_value;
302     // The token value for TOKEN_INTEGER.
303     mpz_t integer_value;
304     // The token value for TOKEN_FLOAT or TOKEN_IMAGINARY.
305     mpfr_t float_value;
306     // The token value for TOKEN_OPERATOR or the keyword value
307     Operator op;
308   } u_;
309   // The source location.
310   source_location location_;
311 };
312
313 // The lexer itself.
314
315 class Lex
316 {
317  public:
318   Lex(const char* input_file_name, FILE* input_file);
319
320   ~Lex();
321
322   // Return the next token.
323   Token
324   next_token();
325
326   // Return whether the identifier NAME should be exported.  NAME is a
327   // mangled name which includes only ASCII characters.
328   static bool
329   is_exported_name(const std::string& name);
330
331   // A helper function.  Append V to STR.  IS_CHARACTER is true if V
332   // is a Unicode character which should be converted into UTF-8,
333   // false if it is a byte value to be appended directly.  The
334   // location is used to warn about an out of range character.
335   static void
336   append_char(unsigned int v, bool is_charater, std::string* str,
337               source_location);
338
339   // A helper function.  Fetch a UTF-8 character from STR and store it
340   // in *VALUE.  Return the number of bytes read from STR.  Return 0
341   // if STR does not point to a valid UTF-8 character.
342   static int
343   fetch_char(const char* str, unsigned int *value);
344
345  private:
346   ssize_t
347   get_line();
348
349   bool
350   require_line();
351
352   // The current location.
353   source_location
354   location() const;
355
356   // A position CHARS column positions before the current location.
357   source_location
358   earlier_location(int chars) const;
359
360   static bool
361   is_hex_digit(char);
362
363   static unsigned char
364   octal_value(char c)
365   { return c - '0'; }
366
367   Token
368   make_invalid_token()
369   { return Token::make_invalid_token(this->location()); }
370
371   Token
372   make_eof_token()
373   { return Token::make_eof_token(this->location()); }
374
375   Token
376   make_operator(Operator op, int chars)
377   { return Token::make_operator_token(op, this->earlier_location(chars)); }
378
379   Token
380   gather_identifier();
381
382   static bool
383   could_be_exponent(const char*, const char*);
384
385   Token
386   gather_number();
387
388   Token
389   gather_character();
390
391   Token
392   gather_string();
393
394   Token
395   gather_raw_string();
396
397   const char*
398   advance_one_utf8_char(const char*, unsigned int*, bool*);
399
400   const char*
401   advance_one_char(const char*, bool, unsigned int*, bool*);
402
403   static bool
404   is_unicode_digit(unsigned int c);
405
406   static bool
407   is_unicode_letter(unsigned int c);
408
409   static bool
410   is_unicode_uppercase(unsigned int c);
411
412   static bool
413   is_in_unicode_range(unsigned int C, const Unicode_range* ranges,
414                       size_t range_size);
415
416   Operator
417   three_character_operator(char, char, char);
418
419   Operator
420   two_character_operator(char, char);
421
422   Operator
423   one_character_operator(char);
424
425   bool
426   skip_c_comment();
427
428   void
429   skip_cpp_comment();
430
431   // The input file name.
432   const char* input_file_name_;
433   // The input file.
434   FILE* input_file_;
435   // The line buffer.  This holds the current line.
436   char* linebuf_;
437   // The size of the line buffer.
438   size_t linebufsize_;
439   // The nmber of characters in the current line.
440   size_t linesize_;
441   // The current offset in linebuf_.
442   size_t lineoff_;
443   // The current line number.
444   size_t lineno_;
445   // Whether to add a semicolon if we see a newline now.
446   bool add_semi_at_eol_;
447 };
448
449 #endif // !defined(GO_LEX_H)