mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
14.0.6 is the latest release at https://pypi.org/project/clang-format/#history, hopefully 15.0.0 will be out soon. Looks like ssciwr/clang-format-wheel#49 is noting issues for this particular release process though.
1287 lines
37 KiB
Plaintext
1287 lines
37 KiB
Plaintext
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||
// Exceptions. See /LICENSE for license information.
|
||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||
|
||
// -----------------------------------------------------------------------------
|
||
// Bison Configuration
|
||
// -----------------------------------------------------------------------------
|
||
|
||
%require "3.2"
|
||
%language "c++"
|
||
|
||
// We don't need a separate header for Bison locations.
|
||
%define api.location.file none
|
||
|
||
// Use a type-safe C++ variant for semantic values
|
||
%define api.value.type variant
|
||
|
||
// Have Bison generate the functions ‘make_TEXT’ and ‘make_NUMBER’, but also
|
||
// ‘make_YYEOF’, for the end of input.
|
||
%define api.token.constructor
|
||
|
||
// Generate the parser as `::Carbon::Parser`.
|
||
%define api.namespace { Carbon }
|
||
%define api.parser.class { Parser }
|
||
|
||
// Make parse error messages more detailed
|
||
%define parse.error verbose
|
||
|
||
// Enable support for parser debugging
|
||
%define parse.trace true
|
||
|
||
// Generate location structs.
|
||
%locations
|
||
|
||
// Parameters to the parser and lexer.
|
||
//
|
||
// Parameters to the parser are stored therein as protected data members, and
|
||
// thus available to its methods.
|
||
|
||
// "inout" parameters passed to both the parser and the lexer.
|
||
%param {Nonnull<Arena*> arena}
|
||
%param {yyscan_t yyscanner}
|
||
%param {ParseAndLexContext& context}
|
||
|
||
// "out" parameter passed to the parser, where the AST is written.
|
||
%parse-param {std::optional<AST>* ast}
|
||
|
||
// No shift-reduce conflicts are expected.
|
||
// See README.md#precedence-and-associativity for a description of how
|
||
// operator precedence is expressed.
|
||
%expect 0
|
||
|
||
// -----------------------------------------------------------------------------
|
||
|
||
%code top {
|
||
#include <algorithm>
|
||
#include <cstdarg>
|
||
#include <cstdio>
|
||
#include <cstdlib>
|
||
#include <vector>
|
||
|
||
#include "explorer/syntax/parse_and_lex_context.h"
|
||
#include "llvm/ADT/StringExtras.h"
|
||
#include "llvm/Support/FormatVariadic.h"
|
||
#include "llvm/Support/raw_ostream.h"
|
||
} // %code top
|
||
|
||
%code requires {
|
||
#include <optional>
|
||
|
||
#include "explorer/ast/ast.h"
|
||
#include "explorer/ast/declaration.h"
|
||
#include "explorer/ast/expression.h"
|
||
#include "explorer/ast/paren_contents.h"
|
||
#include "explorer/ast/pattern.h"
|
||
#include "explorer/ast/value_category.h"
|
||
#include "explorer/common/arena.h"
|
||
#include "explorer/common/nonnull.h"
|
||
#include "explorer/syntax/bison_wrap.h"
|
||
|
||
namespace Carbon {
|
||
class ParseAndLexContext;
|
||
} // namespace Carbon
|
||
|
||
typedef void* yyscan_t;
|
||
} // %code requires
|
||
|
||
%code {
|
||
void Carbon::Parser::error(const location_type&, const std::string& message) {
|
||
context.RecordSyntaxError(message);
|
||
}
|
||
} // %code
|
||
|
||
%token <int> integer_literal
|
||
%token <std::string> identifier
|
||
%token <IntrinsicExpression::Intrinsic> intrinsic_identifier
|
||
%token <std::string> sized_type_literal
|
||
%token <std::string> string_literal
|
||
%type <std::string> designator
|
||
%type <ImplKind> impl_kind
|
||
%type <Nonnull<Expression*>> impl_type
|
||
%type <std::pair<LibraryName, bool>> package_directive
|
||
%type <LibraryName> import_directive
|
||
%type <std::vector<LibraryName>> import_directives
|
||
%type <std::string> optional_library_path
|
||
%type <bool> api_or_impl
|
||
%type <ClassExtensibility> class_declaration_extensibility
|
||
%type <std::optional<Nonnull<Expression*>>> class_declaration_extends
|
||
%type <Nonnull<Declaration*>> declaration
|
||
%type <Nonnull<FunctionDeclaration*>> function_declaration
|
||
%type <Nonnull<DestructorDeclaration*>> destructor_declaration;
|
||
%type <Nonnull<MixDeclaration*>> mix_declaration
|
||
%type <Nonnull<AliasDeclaration*>> alias_declaration
|
||
%type <std::vector<Nonnull<Declaration*>>> declaration_list
|
||
%type <std::vector<Nonnull<Declaration*>>> class_body
|
||
%type <std::vector<Nonnull<Declaration*>>> mixin_body
|
||
%type <std::vector<Nonnull<Declaration*>>> interface_body
|
||
%type <std::vector<Nonnull<Declaration*>>> impl_body
|
||
%type <Nonnull<Statement*>> statement
|
||
%type <Nonnull<If*>> if_statement
|
||
%type <std::optional<Nonnull<Block*>>> optional_else
|
||
%type <std::pair<Nonnull<Expression*>, bool>> return_expression
|
||
%type <Nonnull<Block*>> block
|
||
%type <std::vector<Nonnull<Statement*>>> statement_list
|
||
%type <Nonnull<Expression*>> primary_expression
|
||
%type <Nonnull<Expression*>> postfix_expression
|
||
%type <Nonnull<Expression*>> ref_deref_expression
|
||
%type <Nonnull<Expression*>> type_expression
|
||
%type <Nonnull<Expression*>> fn_type_expression
|
||
%type <Nonnull<Expression*>> minus_expression
|
||
%type <Nonnull<Expression*>> complement_expression
|
||
%type <Nonnull<Expression*>> unary_expression
|
||
%type <Nonnull<Expression*>> simple_binary_operand
|
||
%type <Nonnull<Expression*>> multiplicative_lhs
|
||
%type <Nonnull<Expression*>> multiplicative_expression
|
||
%type <Nonnull<Expression*>> additive_operand
|
||
%type <Nonnull<Expression*>> additive_lhs
|
||
%type <Nonnull<Expression*>> additive_expression
|
||
%type <Nonnull<Expression*>> modulo_expression
|
||
%type <Nonnull<Expression*>> bitwise_and_lhs
|
||
%type <Nonnull<Expression*>> bitwise_and_expression
|
||
%type <Nonnull<Expression*>> bitwise_or_lhs
|
||
%type <Nonnull<Expression*>> bitwise_or_expression
|
||
%type <Nonnull<Expression*>> bitwise_xor_lhs
|
||
%type <Nonnull<Expression*>> bitwise_xor_expression
|
||
%type <Nonnull<Expression*>> bitwise_expression
|
||
%type <Nonnull<Expression*>> bit_shift_expression
|
||
%type <Nonnull<Expression*>> as_expression
|
||
%type <Nonnull<Expression*>> unimpl_expression
|
||
%type <Nonnull<Expression*>> value_expression
|
||
%type <Nonnull<Expression*>> comparison_operand
|
||
%type <Nonnull<Expression*>> comparison_expression
|
||
%type <Nonnull<Expression*>> not_expression
|
||
%type <Nonnull<Expression*>> predicate_expression
|
||
%type <Nonnull<Expression*>> and_or_operand
|
||
%type <Nonnull<Expression*>> and_lhs
|
||
%type <Nonnull<Expression*>> and_expression
|
||
%type <Nonnull<Expression*>> or_lhs
|
||
%type <Nonnull<Expression*>> or_expression
|
||
%type <Nonnull<WhereClause*>> where_clause
|
||
%type <std::vector<Nonnull<WhereClause*>>> where_clause_list
|
||
%type <Nonnull<Expression*>> where_expression
|
||
%type <Nonnull<Expression*>> type_or_where_expression
|
||
%type <Nonnull<Expression*>> statement_expression
|
||
%type <Nonnull<Expression*>> if_expression
|
||
%type <Nonnull<Expression*>> expression
|
||
%type <Nonnull<Expression*>> mixin_import
|
||
%type <Nonnull<GenericBinding*>> generic_binding
|
||
%type <Nonnull<Pattern*>> deduced_param
|
||
%type <std::vector<Nonnull<AstNode*>>> deduced_params
|
||
%type <std::vector<Nonnull<AstNode*>>> impl_deduced_params
|
||
%type <std::vector<Nonnull<AstNode*>>> deduced_param_list
|
||
%type <Nonnull<Pattern*>> pattern
|
||
%type <Nonnull<Pattern*>> non_expression_pattern
|
||
%type <BisonWrap<ReturnTerm>> return_term
|
||
%type <Nonnull<Expression*>> paren_expression
|
||
%type <Nonnull<StructLiteral*>> struct_literal
|
||
%type <std::vector<FieldInitializer>> struct_literal_contents
|
||
%type <Nonnull<StructTypeLiteral*>> struct_type_literal
|
||
%type <std::vector<FieldInitializer>> struct_type_literal_contents
|
||
%type <Nonnull<TupleLiteral*>> tuple
|
||
%type <std::string> binding_lhs
|
||
%type <Nonnull<BindingPattern*>> variable_declaration
|
||
%type <ParenContents<Expression>> paren_expression_base
|
||
%type <ParenContents<Expression>> paren_expression_contents
|
||
%type <Nonnull<Pattern*>> paren_pattern
|
||
%type <Nonnull<TuplePattern*>> tuple_pattern
|
||
%type <Nonnull<TuplePattern*>> maybe_empty_tuple_pattern
|
||
%type <std::optional<Nonnull<TuplePattern*>>> type_params
|
||
%type <ParenContents<Pattern>> paren_pattern_base
|
||
%type <ParenContents<Pattern>> paren_pattern_contents
|
||
%type <Nonnull<AlternativeSignature*>> alternative
|
||
%type <std::vector<Nonnull<AlternativeSignature*>>> alternative_list
|
||
%type <std::vector<Nonnull<AlternativeSignature*>>> alternative_list_contents
|
||
%type <BisonWrap<Match::Clause>> clause
|
||
%type <std::vector<Match::Clause>> clause_list
|
||
%type <Operator> comparison_operator;
|
||
|
||
%token
|
||
// Most tokens have their spelling defined in lexer.lpp.
|
||
// table-begin
|
||
ABSTRACT
|
||
ADDR
|
||
ALIAS
|
||
AMPERSAND
|
||
AND
|
||
API
|
||
ARROW
|
||
AS
|
||
AUTO
|
||
AWAIT
|
||
BASE
|
||
BOOL
|
||
BREAK
|
||
CARET
|
||
CASE
|
||
CHOICE
|
||
CLASS
|
||
COLON
|
||
COLON_BANG
|
||
COMMA
|
||
CONTINUATION
|
||
CONTINUATION_TYPE
|
||
CONTINUE
|
||
DEFAULT
|
||
DESTRUCTOR
|
||
DOUBLE_ARROW
|
||
ELSE
|
||
EQUAL
|
||
EQUAL_EQUAL
|
||
EXTENDS
|
||
EXTERNAL
|
||
FALSE
|
||
FN
|
||
FN_TYPE
|
||
FOR
|
||
FORALL
|
||
GREATER
|
||
GREATER_EQUAL
|
||
GREATER_GREATER
|
||
IF
|
||
IMPL
|
||
IMPORT
|
||
IN
|
||
INTERFACE
|
||
IS
|
||
LEFT_CURLY_BRACE
|
||
LEFT_PARENTHESIS
|
||
LEFT_SQUARE_BRACKET
|
||
LESS
|
||
LESS_EQUAL
|
||
LESS_LESS
|
||
LET
|
||
LIBRARY
|
||
MATCH
|
||
MINUS
|
||
MIX
|
||
MIXIN
|
||
NOT
|
||
NOT_EQUAL
|
||
OR
|
||
PACKAGE
|
||
PERCENT
|
||
PERIOD
|
||
PIPE
|
||
PLUS
|
||
RETURN
|
||
RETURNED
|
||
RIGHT_CURLY_BRACE
|
||
RIGHT_PARENTHESIS
|
||
RIGHT_SQUARE_BRACKET
|
||
RUN
|
||
SELF
|
||
SEMICOLON
|
||
SLASH
|
||
STRING
|
||
THEN
|
||
TRUE
|
||
TYPE
|
||
UNDERSCORE
|
||
UNIMPL_EXAMPLE
|
||
VAR
|
||
WHERE
|
||
WHILE
|
||
// table-end
|
||
// Used to track EOF.
|
||
END_OF_FILE 0
|
||
// Only used for precedence.
|
||
FNARROW "-> in return type"
|
||
// The lexer determines the arity and fixity of each `*` based on whitespace
|
||
// and adjacent tokens. UNARY_STAR indicates that the operator is unary but
|
||
// could be either prefix or postfix.
|
||
UNARY_STAR "unary *"
|
||
PREFIX_STAR "prefix *"
|
||
POSTFIX_STAR "postfix *"
|
||
BINARY_STAR "binary *"
|
||
;
|
||
|
||
%start input
|
||
%%
|
||
input: package_directive import_directives declaration_list
|
||
{
|
||
*ast = AST({.package = $1.first,
|
||
.is_api = $1.second,
|
||
.imports = std::move($2),
|
||
.declarations = std::move($3)});
|
||
}
|
||
;
|
||
package_directive:
|
||
PACKAGE identifier optional_library_path api_or_impl SEMICOLON
|
||
{ $$ = {LibraryName({.package = $2, .path = $3}), $4}; }
|
||
;
|
||
import_directive:
|
||
IMPORT identifier optional_library_path SEMICOLON
|
||
{ $$ = LibraryName({.package = $2, .path = $3}); }
|
||
;
|
||
import_directives:
|
||
// Empty
|
||
{ $$ = std::vector<LibraryName>(); }
|
||
| import_directives import_directive
|
||
{
|
||
$$ = std::move($1);
|
||
$$.push_back($2);
|
||
}
|
||
;
|
||
optional_library_path:
|
||
// Empty
|
||
{ $$ = ""; }
|
||
| LIBRARY string_literal
|
||
{ $$ = $2; }
|
||
;
|
||
api_or_impl:
|
||
API
|
||
{ $$ = true; }
|
||
| IMPL
|
||
{ $$ = false; }
|
||
;
|
||
primary_expression:
|
||
identifier
|
||
{ $$ = arena->New<IdentifierExpression>(context.source_loc(), $1); }
|
||
| designator
|
||
{
|
||
// `.Foo` is rewritten to `.Self.Foo`.
|
||
$$ = arena->New<SimpleMemberAccessExpression>(
|
||
context.source_loc(),
|
||
arena->New<DotSelfExpression>(context.source_loc()), $1);
|
||
}
|
||
| PERIOD SELF
|
||
{ $$ = arena->New<DotSelfExpression>(context.source_loc()); }
|
||
| integer_literal
|
||
{ $$ = arena->New<IntLiteral>(context.source_loc(), $1); }
|
||
| string_literal
|
||
{ $$ = arena->New<StringLiteral>(context.source_loc(), $1); }
|
||
| TRUE
|
||
{ $$ = arena->New<BoolLiteral>(context.source_loc(), true); }
|
||
| FALSE
|
||
{ $$ = arena->New<BoolLiteral>(context.source_loc(), false); }
|
||
| sized_type_literal
|
||
{
|
||
int val = 0;
|
||
if (!llvm::to_integer(llvm::StringRef($1).substr(1), val)) {
|
||
context.RecordSyntaxError(
|
||
llvm::formatv("Invalid type literal: {0}", $1));
|
||
YYERROR;
|
||
} else if ($1[0] != 'i' || val != 32) {
|
||
context.RecordSyntaxError(
|
||
llvm::formatv("Only i32 is supported for now: {0}", $1));
|
||
YYERROR;
|
||
} else {
|
||
$$ = arena->New<IntTypeLiteral>(context.source_loc());
|
||
}
|
||
}
|
||
| SELF
|
||
// TODO: Should we create a new TypeLiteral for `Self`?
|
||
{ $$ = arena->New<IdentifierExpression>(context.source_loc(), "Self"); }
|
||
| STRING
|
||
{ $$ = arena->New<StringTypeLiteral>(context.source_loc()); }
|
||
| BOOL
|
||
{ $$ = arena->New<BoolTypeLiteral>(context.source_loc()); }
|
||
| TYPE
|
||
{ $$ = arena->New<TypeTypeLiteral>(context.source_loc()); }
|
||
| CONTINUATION_TYPE
|
||
{ $$ = arena->New<ContinuationTypeLiteral>(context.source_loc()); }
|
||
| paren_expression { $$ = $1; }
|
||
| struct_literal { $$ = $1; }
|
||
| struct_type_literal { $$ = $1; }
|
||
| LEFT_SQUARE_BRACKET expression SEMICOLON expression RIGHT_SQUARE_BRACKET
|
||
{ $$ = arena->New<ArrayTypeLiteral>(context.source_loc(), $2, $4); }
|
||
;
|
||
postfix_expression:
|
||
primary_expression
|
||
| postfix_expression designator
|
||
{
|
||
$$ = arena->New<SimpleMemberAccessExpression>(context.source_loc(), $1,
|
||
$2);
|
||
}
|
||
| postfix_expression PERIOD LEFT_PARENTHESIS expression RIGHT_PARENTHESIS
|
||
{
|
||
$$ = arena->New<CompoundMemberAccessExpression>(context.source_loc(), $1,
|
||
$4);
|
||
}
|
||
| postfix_expression LEFT_SQUARE_BRACKET expression RIGHT_SQUARE_BRACKET
|
||
{ $$ = arena->New<IndexExpression>(context.source_loc(), $1, $3); }
|
||
| intrinsic_identifier tuple
|
||
{ $$ = arena->New<IntrinsicExpression>($1, $2, context.source_loc()); }
|
||
| postfix_expression tuple
|
||
{ $$ = arena->New<CallExpression>(context.source_loc(), $1, $2); }
|
||
| postfix_expression POSTFIX_STAR
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Ptr,
|
||
std::vector<Nonnull<Expression*>>({$1}));
|
||
}
|
||
| postfix_expression UNARY_STAR
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Ptr,
|
||
std::vector<Nonnull<Expression*>>({$1}));
|
||
}
|
||
;
|
||
ref_deref_expression:
|
||
postfix_expression
|
||
| PREFIX_STAR ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Deref,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
| UNARY_STAR ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Deref,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
| AMPERSAND ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::AddressOf,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
;
|
||
fn_type_expression:
|
||
FN_TYPE tuple ARROW type_expression
|
||
{ $$ = arena->New<FunctionTypeLiteral>(context.source_loc(), $2, $4); }
|
||
;
|
||
type_expression:
|
||
ref_deref_expression
|
||
| bitwise_and_expression
|
||
| fn_type_expression
|
||
;
|
||
minus_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
MINUS ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Neg,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
;
|
||
complement_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
CARET ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Complement,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
;
|
||
unary_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
minus_expression
|
||
| complement_expression
|
||
;
|
||
// A simple_binary_operand is an operand of a binary operator
|
||
// that is not itself a binary operator expression.
|
||
simple_binary_operand:
|
||
ref_deref_expression
|
||
| unary_expression
|
||
;
|
||
multiplicative_lhs:
|
||
simple_binary_operand
|
||
| multiplicative_expression
|
||
;
|
||
multiplicative_expression:
|
||
multiplicative_lhs BINARY_STAR simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Mul,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
| multiplicative_lhs SLASH simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Div,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
additive_operand:
|
||
simple_binary_operand
|
||
| multiplicative_expression
|
||
;
|
||
additive_lhs:
|
||
simple_binary_operand
|
||
| additive_expression
|
||
;
|
||
additive_expression:
|
||
multiplicative_expression
|
||
| additive_lhs PLUS additive_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Add,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
| additive_lhs MINUS additive_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Sub,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
modulo_expression:
|
||
simple_binary_operand PERCENT simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Mod,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
bitwise_and_lhs:
|
||
simple_binary_operand
|
||
| bitwise_and_expression
|
||
;
|
||
bitwise_and_expression:
|
||
bitwise_and_lhs AMPERSAND simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::BitwiseAnd,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
bitwise_or_lhs:
|
||
simple_binary_operand
|
||
| bitwise_or_expression
|
||
;
|
||
bitwise_or_expression:
|
||
bitwise_or_lhs PIPE simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::BitwiseOr,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
bitwise_xor_lhs:
|
||
simple_binary_operand
|
||
| bitwise_xor_expression
|
||
;
|
||
bitwise_xor_expression:
|
||
bitwise_xor_lhs CARET simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::BitwiseXor,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
bitwise_expression:
|
||
bitwise_and_expression
|
||
| bitwise_or_expression
|
||
| bitwise_xor_expression
|
||
;
|
||
bit_shift_expression:
|
||
simple_binary_operand LESS_LESS simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::BitShiftLeft,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
| simple_binary_operand GREATER_GREATER simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::BitShiftRight,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
as_expression:
|
||
simple_binary_operand AS simple_binary_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::As,
|
||
std::vector<Nonnull<Expression*>>{$1, $3});
|
||
}
|
||
;
|
||
unimpl_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
ref_deref_expression UNIMPL_EXAMPLE ref_deref_expression
|
||
{
|
||
$$ = arena->New<UnimplementedExpression>(context.source_loc(),
|
||
"ExampleInfix", $1, $3);
|
||
}
|
||
;
|
||
value_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
additive_expression
|
||
| as_expression
|
||
| bitwise_expression
|
||
| bit_shift_expression
|
||
| fn_type_expression
|
||
| modulo_expression
|
||
| unary_expression
|
||
| unimpl_expression
|
||
;
|
||
comparison_operand:
|
||
ref_deref_expression
|
||
| value_expression
|
||
;
|
||
comparison_operator:
|
||
EQUAL_EQUAL
|
||
{ $$ = Operator::Eq; }
|
||
| LESS
|
||
{ $$ = Operator::Less; }
|
||
| LESS_EQUAL
|
||
{ $$ = Operator::LessEq; }
|
||
| GREATER
|
||
{ $$ = Operator::Greater; }
|
||
| GREATER_EQUAL
|
||
{ $$ = Operator::GreaterEq; }
|
||
| NOT_EQUAL
|
||
{ $$ = Operator::NotEq; }
|
||
;
|
||
comparison_expression:
|
||
value_expression
|
||
| comparison_operand comparison_operator comparison_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), $2,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
not_expression:
|
||
NOT ref_deref_expression
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Not,
|
||
std::vector<Nonnull<Expression*>>({$2}));
|
||
}
|
||
;
|
||
predicate_expression:
|
||
// ref_deref_expression excluded due to precedence diamond.
|
||
not_expression
|
||
| comparison_expression
|
||
;
|
||
and_or_operand:
|
||
ref_deref_expression
|
||
| predicate_expression
|
||
;
|
||
and_lhs:
|
||
and_or_operand
|
||
| and_expression
|
||
;
|
||
and_expression:
|
||
// predicate_expression excluded due to precedence diamond.
|
||
and_lhs AND and_or_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::And,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
or_lhs:
|
||
and_or_operand
|
||
| or_expression
|
||
;
|
||
or_expression:
|
||
// predicate_expression excluded due to precedence diamond.
|
||
or_lhs OR and_or_operand
|
||
{
|
||
$$ = arena->New<OperatorExpression>(
|
||
context.source_loc(), Operator::Or,
|
||
std::vector<Nonnull<Expression*>>({$1, $3}));
|
||
}
|
||
;
|
||
where_clause:
|
||
comparison_operand IS comparison_operand
|
||
{ $$ = arena->New<IsWhereClause>(context.source_loc(), $1, $3); }
|
||
| comparison_operand EQUAL_EQUAL comparison_operand
|
||
{ $$ = arena->New<EqualsWhereClause>(context.source_loc(), $1, $3); }
|
||
;
|
||
where_clause_list:
|
||
where_clause
|
||
{ $$ = {$1}; }
|
||
| where_clause_list AND where_clause
|
||
{
|
||
$$ = std::move($1);
|
||
$$.push_back($3);
|
||
}
|
||
;
|
||
where_expression:
|
||
type_expression WHERE where_clause_list
|
||
{
|
||
auto* self =
|
||
arena->New<GenericBinding>(context.source_loc(), ".Self", $1);
|
||
$$ = arena->New<WhereExpression>(context.source_loc(), self, $3);
|
||
}
|
||
;
|
||
type_or_where_expression:
|
||
type_expression
|
||
| where_expression
|
||
;
|
||
statement_expression:
|
||
ref_deref_expression
|
||
| predicate_expression
|
||
| and_expression
|
||
| or_expression
|
||
| where_expression
|
||
;
|
||
if_expression:
|
||
statement_expression
|
||
| IF expression THEN if_expression ELSE if_expression
|
||
{ $$ = arena->New<IfExpression>(context.source_loc(), $2, $4, $6); }
|
||
;
|
||
expression:
|
||
if_expression
|
||
;
|
||
designator: PERIOD identifier { $$ = $2; }
|
||
;
|
||
paren_expression: paren_expression_base
|
||
{ $$ = ExpressionFromParenContents(arena, context.source_loc(), $1); }
|
||
;
|
||
tuple: paren_expression_base
|
||
{ $$ = TupleExpressionFromParenContents(arena, context.source_loc(), $1); }
|
||
;
|
||
paren_expression_base:
|
||
LEFT_PARENTHESIS RIGHT_PARENTHESIS
|
||
{ $$ = {.elements = {}, .has_trailing_comma = false}; }
|
||
| LEFT_PARENTHESIS paren_expression_contents RIGHT_PARENTHESIS
|
||
{ $$ = $2; }
|
||
| LEFT_PARENTHESIS paren_expression_contents COMMA RIGHT_PARENTHESIS
|
||
{
|
||
$$ = $2;
|
||
$$.has_trailing_comma = true;
|
||
}
|
||
;
|
||
paren_expression_contents:
|
||
expression
|
||
{ $$ = {.elements = {$1}, .has_trailing_comma = false}; }
|
||
| paren_expression_contents COMMA expression
|
||
{
|
||
$$ = $1;
|
||
$$.elements.push_back($3);
|
||
}
|
||
;
|
||
|
||
struct_literal:
|
||
LEFT_CURLY_BRACE struct_literal_contents RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<StructLiteral>(context.source_loc(), $2); }
|
||
| LEFT_CURLY_BRACE struct_literal_contents COMMA RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<StructLiteral>(context.source_loc(), $2); }
|
||
;
|
||
struct_literal_contents:
|
||
designator EQUAL expression
|
||
{ $$ = {FieldInitializer($1, $3)}; }
|
||
| struct_literal_contents COMMA designator EQUAL expression
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(FieldInitializer($3, $5));
|
||
}
|
||
;
|
||
|
||
struct_type_literal:
|
||
LEFT_CURLY_BRACE RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<StructTypeLiteral>(context.source_loc()); }
|
||
| LEFT_CURLY_BRACE struct_type_literal_contents RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<StructTypeLiteral>(context.source_loc(), $2); }
|
||
| LEFT_CURLY_BRACE struct_type_literal_contents COMMA RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<StructTypeLiteral>(context.source_loc(), $2); }
|
||
;
|
||
struct_type_literal_contents:
|
||
designator COLON expression
|
||
{ $$ = {FieldInitializer($1, $3)}; }
|
||
| struct_type_literal_contents COMMA designator COLON expression
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(FieldInitializer($3, $5));
|
||
}
|
||
;
|
||
|
||
// In many cases, using `pattern` recursively will result in ambiguities.
|
||
// When that happens, it's necessary to factor out two separate productions,
|
||
// one for when the sub-pattern is an expression, and one for when it is not.
|
||
// To facilitate this, non-terminals besides `pattern` whose names contain
|
||
// `pattern` are structured to be disjoint from `expression`, unless otherwise
|
||
// specified.
|
||
pattern:
|
||
non_expression_pattern
|
||
{ $$ = $1; }
|
||
| expression
|
||
{ $$ = arena->New<ExpressionPattern>($1); }
|
||
;
|
||
non_expression_pattern:
|
||
AUTO
|
||
{ $$ = arena->New<AutoPattern>(context.source_loc()); }
|
||
| binding_lhs COLON pattern
|
||
{
|
||
$$ = arena->New<BindingPattern>(context.source_loc(), $1, $3,
|
||
std::nullopt);
|
||
}
|
||
| binding_lhs COLON_BANG expression
|
||
{ $$ = arena->New<GenericBinding>(context.source_loc(), $1, $3); }
|
||
| paren_pattern
|
||
{ $$ = $1; }
|
||
| postfix_expression tuple_pattern
|
||
{
|
||
ErrorOr<Nonnull<AlternativePattern*>> alternative_pattern =
|
||
AlternativePattern::Create(arena, context.source_loc(), $1, $2);
|
||
if (alternative_pattern.ok()) {
|
||
$$ = *alternative_pattern;
|
||
} else {
|
||
context.RecordSyntaxError(std::move(alternative_pattern).error());
|
||
YYERROR;
|
||
}
|
||
}
|
||
| VAR non_expression_pattern
|
||
{ $$ = arena->New<VarPattern>(context.source_loc(), $2); }
|
||
;
|
||
binding_lhs:
|
||
identifier { $$ = $1; }
|
||
| UNDERSCORE { $$ = AnonymousName; }
|
||
;
|
||
paren_pattern: paren_pattern_base
|
||
{ $$ = PatternFromParenContents(arena, context.source_loc(), $1); }
|
||
;
|
||
paren_pattern_base:
|
||
LEFT_PARENTHESIS paren_pattern_contents RIGHT_PARENTHESIS
|
||
{ $$ = $2; }
|
||
| LEFT_PARENTHESIS paren_pattern_contents COMMA RIGHT_PARENTHESIS
|
||
{
|
||
$$ = $2;
|
||
$$.has_trailing_comma = true;
|
||
}
|
||
;
|
||
// paren_pattern is analogous to paren_expression, but in order to avoid
|
||
// ambiguities, it must be disjoint from paren_expression, meaning it must
|
||
// contain at least one non_expression_pattern. The structure of this rule
|
||
// is very different from the corresponding expression rule because is has to
|
||
// enforce that requirement.
|
||
paren_pattern_contents:
|
||
non_expression_pattern
|
||
{ $$ = {.elements = {$1}, .has_trailing_comma = false}; }
|
||
| paren_expression_contents COMMA non_expression_pattern
|
||
{
|
||
$$ = ParenExpressionToParenPattern(arena, $1);
|
||
$$.elements.push_back($3);
|
||
}
|
||
| paren_pattern_contents COMMA expression
|
||
{
|
||
$$ = $1;
|
||
$$.elements.push_back(arena->New<ExpressionPattern>($3));
|
||
}
|
||
| paren_pattern_contents COMMA non_expression_pattern
|
||
{
|
||
$$ = $1;
|
||
$$.elements.push_back($3);
|
||
}
|
||
;
|
||
tuple_pattern: paren_pattern_base
|
||
{ $$ = TuplePatternFromParenContents(arena, context.source_loc(), $1); }
|
||
;
|
||
// Unlike most `pattern` nonterminals, this one overlaps with `expression`,
|
||
// so it should be used only when prior context (such as an introducer)
|
||
// rules out the possibility of an `expression` at this point.
|
||
maybe_empty_tuple_pattern:
|
||
LEFT_PARENTHESIS RIGHT_PARENTHESIS
|
||
{
|
||
$$ = arena->New<TuplePattern>(context.source_loc(),
|
||
std::vector<Nonnull<Pattern*>>());
|
||
}
|
||
| tuple_pattern
|
||
{ $$ = $1; }
|
||
;
|
||
|
||
clause:
|
||
CASE pattern DOUBLE_ARROW block
|
||
{ $$ = Match::Clause($2, $4); }
|
||
| DEFAULT DOUBLE_ARROW block
|
||
{
|
||
$$ = Match::Clause(arena->New<BindingPattern>(
|
||
context.source_loc(), std::string(AnonymousName),
|
||
arena->New<AutoPattern>(context.source_loc()),
|
||
ValueCategory::Let),
|
||
$3);
|
||
}
|
||
;
|
||
clause_list:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| clause_list clause
|
||
{
|
||
$$ = $1;
|
||
$$.push_back($2);
|
||
}
|
||
;
|
||
statement:
|
||
statement_expression EQUAL expression SEMICOLON
|
||
{ $$ = arena->New<Assign>(context.source_loc(), $1, $3); }
|
||
| VAR pattern SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDefinition>(
|
||
context.source_loc(), $2, std::nullopt, ValueCategory::Var,
|
||
VariableDefinition::DefinitionType::Var);
|
||
}
|
||
| VAR pattern EQUAL expression SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDefinition>(
|
||
context.source_loc(), $2, $4, ValueCategory::Var,
|
||
VariableDefinition::DefinitionType::Var);
|
||
}
|
||
| RETURNED VAR variable_declaration SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDefinition>(
|
||
context.source_loc(), $3, std::nullopt, ValueCategory::Var,
|
||
VariableDefinition::DefinitionType::Returned);
|
||
}
|
||
| RETURNED VAR variable_declaration EQUAL expression SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDefinition>(
|
||
context.source_loc(), $3, $5, ValueCategory::Var,
|
||
VariableDefinition::DefinitionType::Returned);
|
||
}
|
||
| LET pattern EQUAL expression SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDefinition>(
|
||
context.source_loc(), $2, $4, ValueCategory::Let,
|
||
VariableDefinition::DefinitionType::Var);
|
||
}
|
||
| statement_expression SEMICOLON
|
||
{ $$ = arena->New<ExpressionStatement>(context.source_loc(), $1); }
|
||
| if_statement
|
||
{ $$ = $1; }
|
||
| WHILE LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block
|
||
{ $$ = arena->New<While>(context.source_loc(), $3, $5); }
|
||
| BREAK SEMICOLON
|
||
{ $$ = arena->New<Break>(context.source_loc()); }
|
||
| CONTINUE SEMICOLON
|
||
{ $$ = arena->New<Continue>(context.source_loc()); }
|
||
| RETURN return_expression SEMICOLON
|
||
{
|
||
auto [return_exp, is_omitted_exp] = $2;
|
||
$$ = arena->New<ReturnExpression>(context.source_loc(), return_exp,
|
||
is_omitted_exp);
|
||
}
|
||
| RETURN VAR SEMICOLON
|
||
{ $$ = arena->New<ReturnVar>(context.source_loc()); }
|
||
| MATCH LEFT_PARENTHESIS expression RIGHT_PARENTHESIS LEFT_CURLY_BRACE
|
||
clause_list RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<Match>(context.source_loc(), $3, $6); }
|
||
| CONTINUATION identifier block
|
||
{ $$ = arena->New<Continuation>(context.source_loc(), $2, $3); }
|
||
| RUN expression SEMICOLON
|
||
{ $$ = arena->New<Run>(context.source_loc(), $2); }
|
||
| AWAIT SEMICOLON
|
||
{ $$ = arena->New<Await>(context.source_loc()); }
|
||
| FOR LEFT_PARENTHESIS variable_declaration IN type_expression RIGHT_PARENTHESIS block
|
||
{ $$ = arena->New<For>(context.source_loc(), $3, $5, $7); }
|
||
;
|
||
if_statement:
|
||
IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS block optional_else
|
||
{ $$ = arena->New<If>(context.source_loc(), $3, $5, $6); }
|
||
;
|
||
optional_else:
|
||
// Empty
|
||
{ $$ = std::nullopt; }
|
||
| ELSE if_statement
|
||
{
|
||
$$ = arena->New<Block>(context.source_loc(),
|
||
std::vector<Nonnull<Statement*>>({$2}));
|
||
}
|
||
| ELSE block
|
||
{ $$ = $2; }
|
||
;
|
||
return_expression:
|
||
// Empty
|
||
{ $$ = {arena->New<TupleLiteral>(context.source_loc()), true}; }
|
||
| expression
|
||
{ $$ = {$1, false}; }
|
||
;
|
||
statement_list:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| statement_list statement
|
||
{
|
||
$$ = std::move($1);
|
||
$$.push_back($2);
|
||
}
|
||
;
|
||
block:
|
||
LEFT_CURLY_BRACE statement_list RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<Block>(context.source_loc(), std::move($2)); }
|
||
;
|
||
return_term:
|
||
// Empty
|
||
{ $$ = ReturnTerm::Omitted(context.source_loc()); }
|
||
| ARROW AUTO
|
||
{ $$ = ReturnTerm::Auto(context.source_loc()); }
|
||
| ARROW expression
|
||
{ $$ = ReturnTerm::Explicit($2); }
|
||
;
|
||
generic_binding:
|
||
identifier COLON_BANG expression
|
||
{
|
||
$$ = arena->New<GenericBinding>(context.source_loc(), std::move($1), $3);
|
||
}
|
||
;
|
||
deduced_param:
|
||
generic_binding
|
||
{ $$ = $1; }
|
||
| variable_declaration
|
||
{ $$ = $1; }
|
||
| ADDR variable_declaration
|
||
{ $$ = arena->New<AddrPattern>(context.source_loc(), $2); }
|
||
;
|
||
deduced_param_list:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| deduced_param
|
||
{ $$ = {$1}; }
|
||
| deduced_param_list COMMA deduced_param
|
||
{
|
||
$$ = $1; // TODO: can we std::move here?
|
||
$$.push_back($3);
|
||
}
|
||
;
|
||
deduced_params:
|
||
// Empty
|
||
{ $$ = std::vector<Nonnull<AstNode*>>(); }
|
||
| LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET
|
||
{ $$ = $2; }
|
||
;
|
||
impl_deduced_params:
|
||
// Empty
|
||
{ $$ = std::vector<Nonnull<AstNode*>>(); }
|
||
| FORALL LEFT_SQUARE_BRACKET deduced_param_list RIGHT_SQUARE_BRACKET
|
||
{ $$ = $3; }
|
||
;
|
||
function_declaration:
|
||
FN identifier deduced_params maybe_empty_tuple_pattern return_term block
|
||
{
|
||
ErrorOr<FunctionDeclaration*> fn = FunctionDeclaration::Create(
|
||
arena, context.source_loc(), $2, $3, $4, $5, $6);
|
||
if (fn.ok()) {
|
||
$$ = *fn;
|
||
} else {
|
||
context.RecordSyntaxError(std::move(fn).error());
|
||
YYERROR;
|
||
}
|
||
}
|
||
| FN identifier deduced_params maybe_empty_tuple_pattern return_term SEMICOLON
|
||
{
|
||
ErrorOr<FunctionDeclaration*> fn = FunctionDeclaration::Create(
|
||
arena, context.source_loc(), $2, $3, $4, $5, std::nullopt);
|
||
if (fn.ok()) {
|
||
$$ = *fn;
|
||
} else {
|
||
context.RecordSyntaxError(std::move(fn).error());
|
||
YYERROR;
|
||
}
|
||
}
|
||
;
|
||
variable_declaration: identifier COLON pattern
|
||
{
|
||
$$ = arena->New<BindingPattern>(context.source_loc(), $1, $3,
|
||
std::nullopt);
|
||
}
|
||
;
|
||
alias_declaration: ALIAS identifier EQUAL expression SEMICOLON
|
||
{ $$ = arena->New<AliasDeclaration>(context.source_loc(), $2, $4); }
|
||
;
|
||
// EXPERIMENTAL MIXIN FEATURE
|
||
mix_declaration: MIX expression SEMICOLON
|
||
{ $$ = arena->New<MixDeclaration>(context.source_loc(), $2); }
|
||
;
|
||
alternative:
|
||
identifier tuple
|
||
{ $$ = arena->New<AlternativeSignature>(context.source_loc(), $1, $2); }
|
||
| identifier
|
||
{
|
||
$$ = arena->New<AlternativeSignature>(
|
||
context.source_loc(), $1,
|
||
arena->New<TupleLiteral>(context.source_loc()));
|
||
}
|
||
;
|
||
alternative_list:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| alternative_list_contents
|
||
{ $$ = $1; }
|
||
| alternative_list_contents COMMA
|
||
{ $$ = $1; }
|
||
;
|
||
alternative_list_contents:
|
||
alternative
|
||
{ $$ = {std::move($1)}; }
|
||
| alternative_list_contents COMMA alternative
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(std::move($3));
|
||
}
|
||
;
|
||
type_params:
|
||
// Empty
|
||
{ $$ = std::nullopt; }
|
||
| tuple_pattern
|
||
{ $$ = $1; }
|
||
;
|
||
// EXPERIMENTAL MIXIN FEATURE
|
||
mixin_import:
|
||
// Empty
|
||
{ $$ = arena->New<TypeTypeLiteral>(context.source_loc()); }
|
||
| FOR expression
|
||
{
|
||
context.RecordSyntaxError("'for' not supported currently");
|
||
YYERROR;
|
||
// $$ = $2;
|
||
}
|
||
;
|
||
class_declaration_extensibility:
|
||
// Empty
|
||
{ $$ = Carbon::ClassExtensibility::None; }
|
||
| ABSTRACT
|
||
{ $$ = Carbon::ClassExtensibility::Abstract; }
|
||
| BASE
|
||
{ $$ = Carbon::ClassExtensibility::Base; }
|
||
;
|
||
class_declaration_extends:
|
||
// Empty
|
||
{ $$ = std::nullopt; }
|
||
| EXTENDS expression
|
||
{ $$ = $2; }
|
||
;
|
||
declaration:
|
||
function_declaration
|
||
{ $$ = $1; }
|
||
| destructor_declaration
|
||
{ $$ = $1; }
|
||
| class_declaration_extensibility CLASS identifier type_params class_declaration_extends LEFT_CURLY_BRACE class_body RIGHT_CURLY_BRACE
|
||
{
|
||
$$ = arena->New<ClassDeclaration>(
|
||
context.source_loc(), $3,
|
||
arena->New<SelfDeclaration>(context.source_loc()), $1, $4, $5, $7);
|
||
}
|
||
| MIXIN identifier type_params mixin_import LEFT_CURLY_BRACE mixin_body RIGHT_CURLY_BRACE
|
||
{
|
||
// EXPERIMENTAL MIXN FEATURE
|
||
auto self = arena->New<GenericBinding>(context.source_loc(), "Self", $4);
|
||
$$ = arena->New<MixinDeclaration>(context.source_loc(), $2, $3, self, $6);
|
||
}
|
||
| CHOICE identifier type_params LEFT_CURLY_BRACE alternative_list RIGHT_CURLY_BRACE
|
||
{ $$ = arena->New<ChoiceDeclaration>(context.source_loc(), $2, $3, $5); }
|
||
| VAR variable_declaration SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDeclaration>(context.source_loc(), $2,
|
||
std::nullopt, ValueCategory::Var);
|
||
}
|
||
| VAR variable_declaration EQUAL expression SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDeclaration>(context.source_loc(), $2, $4,
|
||
ValueCategory::Var);
|
||
}
|
||
| LET variable_declaration EQUAL expression SEMICOLON
|
||
{
|
||
$$ = arena->New<VariableDeclaration>(context.source_loc(), $2, $4,
|
||
ValueCategory::Let);
|
||
}
|
||
| INTERFACE identifier type_params LEFT_CURLY_BRACE interface_body RIGHT_CURLY_BRACE
|
||
{
|
||
$$ = arena->New<InterfaceDeclaration>(arena, context.source_loc(), $2, $3,
|
||
$5);
|
||
}
|
||
| impl_kind IMPL impl_deduced_params impl_type AS type_or_where_expression LEFT_CURLY_BRACE impl_body RIGHT_CURLY_BRACE
|
||
{
|
||
ErrorOr<ImplDeclaration*> impl = ImplDeclaration::Create(
|
||
arena, context.source_loc(), $1, $4, $6, $3, $8);
|
||
if (impl.ok()) {
|
||
$$ = *impl;
|
||
} else {
|
||
context.RecordSyntaxError(std::move(impl).error());
|
||
YYERROR;
|
||
}
|
||
}
|
||
| alias_declaration
|
||
{ $$ = $1; }
|
||
;
|
||
impl_kind:
|
||
// Internal
|
||
{ $$ = Carbon::ImplKind::InternalImpl; }
|
||
| EXTERNAL
|
||
{ $$ = Carbon::ImplKind::ExternalImpl; }
|
||
;
|
||
impl_type:
|
||
// Self
|
||
{ $$ = arena->New<IdentifierExpression>(context.source_loc(), "Self"); }
|
||
| type_expression
|
||
;
|
||
destructor_declaration:
|
||
DESTRUCTOR deduced_params block
|
||
{
|
||
ErrorOr<DestructorDeclaration*> fn =
|
||
DestructorDeclaration::CreateDestructor(
|
||
arena, context.source_loc(), $2,
|
||
arena->New<TuplePattern>(context.source_loc(),
|
||
std::vector<Nonnull<Pattern*>>()),
|
||
ReturnTerm::Omitted(context.source_loc()), $3);
|
||
if (fn.ok()) {
|
||
$$ = *fn;
|
||
} else {
|
||
context.RecordSyntaxError(std::move(fn).error());
|
||
YYERROR;
|
||
}
|
||
}
|
||
;
|
||
declaration_list:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| declaration_list declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(Nonnull<Declaration*>($2));
|
||
}
|
||
;
|
||
class_body:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| class_body declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(Nonnull<Declaration*>($2));
|
||
}
|
||
| class_body mix_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(Nonnull<Declaration*>($2));
|
||
}
|
||
;
|
||
// EXPERIMENTAL MIXIN FEATURE
|
||
mixin_body:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| mixin_body function_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(Nonnull<Declaration*>($2));
|
||
}
|
||
| mixin_body mix_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(Nonnull<Declaration*>($2));
|
||
}
|
||
;
|
||
interface_body:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| interface_body function_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back($2);
|
||
}
|
||
| interface_body LET generic_binding SEMICOLON
|
||
{
|
||
$$ = $1;
|
||
$$.push_back(
|
||
arena->New<AssociatedConstantDeclaration>(context.source_loc(), $3));
|
||
}
|
||
;
|
||
impl_body:
|
||
// Empty
|
||
{ $$ = {}; }
|
||
| impl_body function_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back($2);
|
||
}
|
||
| impl_body alias_declaration
|
||
{
|
||
$$ = $1;
|
||
$$.push_back($2);
|
||
}
|
||
;
|
||
%%
|