// 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 Channel_type; 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_vars; // Used to detect duplicate parameter/result names. typedef std::map 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 > 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, Expression_list* vars, Expression_list* vals); Named_object* create_dummy_global(Type*, Expression*, Location); void finish_init_vars(Expression_list* vars, Expression_list* vals, Location); void simple_var_decl_or_assignment(const std::string&, Location, bool may_be_composite_lit, Range_clause*, Type_switch*); void function_decl(bool saw_nointerface); Typed_identifier* receiver(); Expression* operand(bool may_be_sink, bool *is_parenthesized); 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, bool* is_parenthesized); 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 *is_parenthesized); bool expression_may_start_here(); Expression* unary_expr(bool may_be_sink, bool may_be_composite_lit, bool* is_type_switch, bool* is_parenthesized); Type* reassociate_chan_direction(Channel_type*, Location); 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*, 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)