OSDN Git Service

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