summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/parse.h
blob: 3139f7e890810e57c81d59d08619734c7140f4b9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
// parse.h -- Go frontend parser.     -*- C++ -*-

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#ifndef GO_PARSE_H
#define GO_PARSE_H

class Set_iota_traverse;
class Lex;
class Gogo;
class Named_object;
class Type;
class Typed_identifier;
class Typed_identifier_list;
class Function_type;
class Block;
class Expression;
class Expression_list;
class Struct_field_list;
class Case_clauses;
class Type_case_clauses;
class Select_clauses;
class Statement;
class Label;

// Parse the program.

class Parse
{
 public:
  Parse(Lex*, Gogo*);

  // Parse a program.
  void
  program();

 private:
  // Precedence values.
  enum Precedence
  {
    PRECEDENCE_INVALID = -1,
    PRECEDENCE_NORMAL = 0,
    PRECEDENCE_OROR,
    PRECEDENCE_ANDAND,
    PRECEDENCE_RELOP,
    PRECEDENCE_ADDOP,
    PRECEDENCE_MULOP
  };

  // We use this when parsing the range clause of a for statement.
  struct Range_clause
  {
    // Set to true if we found a range clause.
    bool found;
    // The index expression.
    Expression* index;
    // The value expression.
    Expression* value;
    // The range expression.
    Expression* range;

    Range_clause()
      : found(false), index(NULL), value(NULL), range(NULL)
    { }
  };

  // We use this when parsing the statement at the start of a switch,
  // in order to recognize type switches.
  struct Type_switch
  {
    // Set to true if we find a type switch.
    bool found;
    // The variable name.
    std::string name;
    // The location of the variable.
    Location location;
    // The expression.
    Expression* expr;

    Type_switch()
      : found(false), name(), location(UNKNOWN_LOCATION), expr(NULL)
    { }
  };

  // A variable defined in an enclosing function referenced by the
  // current function.
  class Enclosing_var
  {
   public:
    Enclosing_var(Named_object* var, Named_object* in_function,
		  unsigned int index)
      : var_(var), in_function_(in_function), index_(index)
    { }

    // We put these in a vector, so we need a default constructor.
    Enclosing_var()
      : var_(NULL), in_function_(NULL), index_(-1U)
    { }

    Named_object*
    var() const
    { return this->var_; }

    Named_object*
    in_function() const
    { return this->in_function_; }

    unsigned int
    index() const
    { return this->index_; }

   private:
    // The variable which is being referred to.
    Named_object* var_;
    // The function where the variable is defined.
    Named_object* in_function_;
    // The index of the field in this function's closure struct for
    // this variable.
    unsigned int index_;
  };

  // We store Enclosing_var entries in a set, so we need a comparator.
  struct Enclosing_var_comparison
  {
    bool
    operator()(const Enclosing_var&, const Enclosing_var&);
  };

  // A set of Enclosing_var entries.
  typedef std::set<Enclosing_var, Enclosing_var_comparison> Enclosing_vars;

  // Used to detect duplicate parameter/result names.
  typedef std::map<std::string, const Typed_identifier*> Names;

  // Peek at the current token from the lexer.
  const Token*
  peek_token();

  // Consume the current token, return the next one.
  const Token*
  advance_token();

  // Push a token back on the input stream.
  void
  unget_token(const Token&);

  // The location of the current token.
  Location
  location();

  // For break and continue we keep a stack of statements with
  // associated labels (if any).  The top of the stack is used for a
  // break or continue statement with no label.
  typedef std::vector<std::pair<Statement*, Label*> > Bc_stack;

  // Map from type switch variables to the variables they mask, so
  // that a use of the type switch variable can become a use of the
  // real variable.
  typedef Unordered_map(Named_object*, Named_object*) Type_switch_vars;

  // Parser nonterminals.
  void identifier_list(Typed_identifier_list*);
  Expression_list* expression_list(Expression*, bool may_be_sink,
				   bool may_be_composite_lit);
  bool qualified_ident(std::string*, Named_object**);
  Type* type();
  bool type_may_start_here();
  Type* type_name(bool issue_error);
  Type* array_type(bool may_use_ellipsis);
  Type* map_type();
  Type* struct_type();
  void field_decl(Struct_field_list*);
  Type* pointer_type();
  Type* channel_type();
  void check_signature_names(const Typed_identifier_list*, Names*);
  Function_type* signature(Typed_identifier*, Location);
  bool parameters(Typed_identifier_list**, bool* is_varargs);
  Typed_identifier_list* parameter_list(bool* is_varargs);
  void parameter_decl(bool, Typed_identifier_list*, bool*, bool*);
  bool result(Typed_identifier_list**);
  Location block();
  Type* interface_type();
  void method_spec(Typed_identifier_list*);
  void declaration();
  bool declaration_may_start_here();
  void decl(void (Parse::*)(void*), void*);
  void list(void (Parse::*)(void*), void*, bool);
  void const_decl();
  void const_spec(Type**, Expression_list**);
  void type_decl();
  void type_spec(void*);
  void var_decl();
  void var_spec(void*);
  void init_vars(const Typed_identifier_list*, Type*, Expression_list*,
		 bool is_coloneq, Location);
  bool init_vars_from_call(const Typed_identifier_list*, Type*, Expression*,
			   bool is_coloneq, Location);
  bool init_vars_from_map(const Typed_identifier_list*, Type*, Expression*,
			  bool is_coloneq, Location);
  bool init_vars_from_receive(const Typed_identifier_list*, Type*,
			      Expression*, bool is_coloneq, Location);
  bool init_vars_from_type_guard(const Typed_identifier_list*, Type*,
				 Expression*, bool is_coloneq,
				 Location);
  Named_object* init_var(const Typed_identifier&, Type*, Expression*,
			 bool is_coloneq, bool type_from_init, bool* is_new);
  Named_object* create_dummy_global(Type*, Expression*, Location);
  void simple_var_decl_or_assignment(const std::string&, Location,
				     bool may_be_composite_lit,
				     Range_clause*, Type_switch*);
  void function_decl();
  Typed_identifier* receiver();
  Expression* operand(bool may_be_sink);
  Expression* enclosing_var_reference(Named_object*, Named_object*,
				      Location);
  Expression* composite_lit(Type*, int depth, Location);
  Expression* function_lit();
  Expression* create_closure(Named_object* function, Enclosing_vars*,
			     Location);
  Expression* primary_expr(bool may_be_sink, bool may_be_composite_lit,
			   bool* is_type_switch);
  Expression* selector(Expression*, bool* is_type_switch);
  Expression* index(Expression*);
  Expression* call(Expression*);
  Expression* expression(Precedence, bool may_be_sink,
			 bool may_be_composite_lit, bool* is_type_switch);
  bool expression_may_start_here();
  Expression* unary_expr(bool may_be_sink, bool may_be_composite_lit,
			 bool* is_type_switch);
  Expression* qualified_expr(Expression*, Location);
  Expression* id_to_expression(const std::string&, Location);
  void statement(Label*);
  bool statement_may_start_here();
  void labeled_stmt(const std::string&, Location);
  Expression* simple_stat(bool, bool*, Range_clause*, Type_switch*);
  bool simple_stat_may_start_here();
  void statement_list();
  bool statement_list_may_start_here();
  void expression_stat(Expression*);
  void send_stmt(Expression*);
  void inc_dec_stat(Expression*);
  void assignment(Expression*, bool may_be_composite_lit, Range_clause*);
  void tuple_assignment(Expression_list*, bool may_be_composite_lit,
			Range_clause*);
  void send();
  void go_or_defer_stat();
  void return_stat();
  void if_stat();
  void switch_stat(Label*);
  Statement* expr_switch_body(Label*, Expression*, Location);
  void expr_case_clause(Case_clauses*, bool* saw_default);
  Expression_list* expr_switch_case(bool*);
  Statement* type_switch_body(Label*, const Type_switch&, Location);
  void type_case_clause(Named_object*, Type_case_clauses*, bool* saw_default);
  void type_switch_case(std::vector<Type*>*, bool*);
  void select_stat(Label*);
  void comm_clause(Select_clauses*, bool* saw_default);
  bool comm_case(bool*, Expression**, Expression**, Expression**,
		 std::string*, std::string*, bool*);
  bool send_or_recv_stmt(bool*, Expression**, Expression**, Expression**,
			 std::string*, std::string*);
  void for_stat(Label*);
  void for_clause(Expression**, Block**);
  void range_clause_decl(const Typed_identifier_list*, Range_clause*);
  void range_clause_expr(const Expression_list*, Range_clause*);
  void push_break_statement(Statement*, Label*);
  void push_continue_statement(Statement*, Label*);
  void pop_break_statement();
  void pop_continue_statement();
  Statement* find_bc_statement(const Bc_stack*, const std::string&);
  void break_stat();
  void continue_stat();
  void goto_stat();
  void package_clause();
  void import_decl();
  void import_spec(void*);

  void reset_iota();
  int iota_value();
  void increment_iota();

  // Skip past an error looking for a semicolon or OP.  Return true if
  // all is well, false if we found EOF.
  bool
  skip_past_error(Operator op);

  // Verify that an expression is not a sink, and return either the
  // expression or an error.
  Expression*
  verify_not_sink(Expression*);

  // Return the statement associated with a label in a Bc_stack, or
  // NULL.
  Statement*
  find_bc_statement(const Bc_stack*, const std::string&) const;

  // Mark a variable as used.
  void
  mark_var_used(Named_object*);

  // The lexer output we are parsing.
  Lex* lex_;
  // The current token.
  Token token_;
  // A token pushed back on the input stream.
  Token unget_token_;
  // Whether unget_token_ is valid.
  bool unget_token_valid_;
  // Whether the function we are parsing had errors in the signature.
  bool is_erroneous_function_;
  // The code we are generating.
  Gogo* gogo_;
  // A stack of statements for which break may be used.
  Bc_stack* break_stack_;
  // A stack of statements for which continue may be used.
  Bc_stack* continue_stack_;
  // The current iota value.
  int iota_;
  // References from the local function to variables defined in
  // enclosing functions.
  Enclosing_vars enclosing_vars_;
  // Map from type switch variables to real variables.
  Type_switch_vars type_switch_vars_;
};


#endif // !defined(GO_PARSE_H)