Parsing for pointer types and pointer operators. (#3026)

This provides parsing support for the functionality added in #2006.
This commit is contained in:
Richard Smith
2023-07-26 21:24:54 +00:00
committed by GitHub
parent b783197ec6
commit c4b880c6ef
18 changed files with 450 additions and 75 deletions
+2 -1
View File
@@ -53,7 +53,7 @@ CARBON_DIAGNOSTIC_KIND(BinaryOperatorRequiresWhitespace)
CARBON_DIAGNOSTIC_KIND(ExpectedCloseParen)
CARBON_DIAGNOSTIC_KIND(ExpectedCodeBlock)
CARBON_DIAGNOSTIC_KIND(ExpectedExpression)
CARBON_DIAGNOSTIC_KIND(ExpectedIdentifierAfterDot)
CARBON_DIAGNOSTIC_KIND(ExpectedIdentifierAfterDotOrArrow)
CARBON_DIAGNOSTIC_KIND(ExpectedParameterName)
CARBON_DIAGNOSTIC_KIND(ExpectedParenAfter)
CARBON_DIAGNOSTIC_KIND(ExpectedExpressionSemi)
@@ -62,6 +62,7 @@ CARBON_DIAGNOSTIC_KIND(ExpectedStructLiteralField)
CARBON_DIAGNOSTIC_KIND(ExpectedVariableDeclaration)
CARBON_DIAGNOSTIC_KIND(ExpectedVariableName)
CARBON_DIAGNOSTIC_KIND(OperatorRequiresParentheses)
CARBON_DIAGNOSTIC_KIND(UnaryOperatorRequiresParentheses)
CARBON_DIAGNOSTIC_KIND(UnaryOperatorHasWhitespace)
CARBON_DIAGNOSTIC_KIND(UnaryOperatorRequiresWhitespace)
CARBON_DIAGNOSTIC_KIND(UnexpectedTokenAfterListElement)
+50 -48
View File
@@ -34,100 +34,102 @@ case
choice
// CHECK:STDOUT: { index: 13, kind: 'Class', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'class', has_trailing_space: true },
class
// CHECK:STDOUT: { index: 14, kind: 'Constraint', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'constraint', has_trailing_space: true },
// CHECK:STDOUT: { index: 14, kind: 'Const', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'const', has_trailing_space: true },
const
// CHECK:STDOUT: { index: 15, kind: 'Constraint', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'constraint', has_trailing_space: true },
constraint
// CHECK:STDOUT: { index: 15, kind: 'Continue', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'continue', has_trailing_space: true },
// CHECK:STDOUT: { index: 16, kind: 'Continue', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'continue', has_trailing_space: true },
continue
// CHECK:STDOUT: { index: 16, kind: 'Default', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'default', has_trailing_space: true },
// CHECK:STDOUT: { index: 17, kind: 'Default', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'default', has_trailing_space: true },
default
// CHECK:STDOUT: { index: 17, kind: 'Destructor', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'destructor', has_trailing_space: true },
// CHECK:STDOUT: { index: 18, kind: 'Destructor', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'destructor', has_trailing_space: true },
destructor
// CHECK:STDOUT: { index: 18, kind: 'Else', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'else', has_trailing_space: true },
// CHECK:STDOUT: { index: 19, kind: 'Else', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'else', has_trailing_space: true },
else
// CHECK:STDOUT: { index: 19, kind: 'Extend', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'extend', has_trailing_space: true },
// CHECK:STDOUT: { index: 20, kind: 'Extend', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'extend', has_trailing_space: true },
extend
// CHECK:STDOUT: { index: 20, kind: 'False', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'false', has_trailing_space: true },
// CHECK:STDOUT: { index: 21, kind: 'False', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'false', has_trailing_space: true },
false
// CHECK:STDOUT: { index: 21, kind: 'Final', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'final', has_trailing_space: true },
// CHECK:STDOUT: { index: 22, kind: 'Final', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'final', has_trailing_space: true },
final
// CHECK:STDOUT: { index: 22, kind: 'Fn', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true },
// CHECK:STDOUT: { index: 23, kind: 'Fn', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'fn', has_trailing_space: true },
fn
// CHECK:STDOUT: { index: 23, kind: 'For', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'for', has_trailing_space: true },
// CHECK:STDOUT: { index: 24, kind: 'For', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'for', has_trailing_space: true },
for
// CHECK:STDOUT: { index: 24, kind: 'Forall', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'forall', has_trailing_space: true },
// CHECK:STDOUT: { index: 25, kind: 'Forall', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'forall', has_trailing_space: true },
forall
// CHECK:STDOUT: { index: 25, kind: 'Friend', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'friend', has_trailing_space: true },
// CHECK:STDOUT: { index: 26, kind: 'Friend', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'friend', has_trailing_space: true },
friend
// CHECK:STDOUT: { index: 26, kind: 'If', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'if', has_trailing_space: true },
// CHECK:STDOUT: { index: 27, kind: 'If', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'if', has_trailing_space: true },
if
// CHECK:STDOUT: { index: 27, kind: 'Impl', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'impl', has_trailing_space: true },
// CHECK:STDOUT: { index: 28, kind: 'Impl', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'impl', has_trailing_space: true },
impl
// CHECK:STDOUT: { index: 28, kind: 'Impls', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'impls', has_trailing_space: true },
// CHECK:STDOUT: { index: 29, kind: 'Impls', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'impls', has_trailing_space: true },
impls
// CHECK:STDOUT: { index: 29, kind: 'Import', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'import', has_trailing_space: true },
// CHECK:STDOUT: { index: 30, kind: 'Import', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'import', has_trailing_space: true },
import
// CHECK:STDOUT: { index: 30, kind: 'In', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'in', has_trailing_space: true },
// CHECK:STDOUT: { index: 31, kind: 'In', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'in', has_trailing_space: true },
in
// CHECK:STDOUT: { index: 31, kind: 'Interface', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'interface', has_trailing_space: true },
// CHECK:STDOUT: { index: 32, kind: 'Interface', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'interface', has_trailing_space: true },
interface
// CHECK:STDOUT: { index: 32, kind: 'Let', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'let', has_trailing_space: true },
// CHECK:STDOUT: { index: 33, kind: 'Let', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'let', has_trailing_space: true },
let
// CHECK:STDOUT: { index: 33, kind: 'Library', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'library', has_trailing_space: true },
// CHECK:STDOUT: { index: 34, kind: 'Library', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'library', has_trailing_space: true },
library
// CHECK:STDOUT: { index: 34, kind: 'Like', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'like', has_trailing_space: true },
// CHECK:STDOUT: { index: 35, kind: 'Like', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'like', has_trailing_space: true },
like
// CHECK:STDOUT: { index: 35, kind: 'Match', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'match', has_trailing_space: true },
// CHECK:STDOUT: { index: 36, kind: 'Match', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'match', has_trailing_space: true },
match
// CHECK:STDOUT: { index: 36, kind: 'Namespace', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'namespace', has_trailing_space: true },
// CHECK:STDOUT: { index: 37, kind: 'Namespace', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'namespace', has_trailing_space: true },
namespace
// CHECK:STDOUT: { index: 37, kind: 'Not', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'not', has_trailing_space: true },
// CHECK:STDOUT: { index: 38, kind: 'Not', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'not', has_trailing_space: true },
not
// CHECK:STDOUT: { index: 38, kind: 'Observe', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'observe', has_trailing_space: true },
// CHECK:STDOUT: { index: 39, kind: 'Observe', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'observe', has_trailing_space: true },
observe
// CHECK:STDOUT: { index: 39, kind: 'Or', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'or', has_trailing_space: true },
// CHECK:STDOUT: { index: 40, kind: 'Or', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'or', has_trailing_space: true },
or
// CHECK:STDOUT: { index: 40, kind: 'Override', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'override', has_trailing_space: true },
// CHECK:STDOUT: { index: 41, kind: 'Override', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'override', has_trailing_space: true },
override
// CHECK:STDOUT: { index: 41, kind: 'Package', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'package', has_trailing_space: true },
// CHECK:STDOUT: { index: 42, kind: 'Package', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'package', has_trailing_space: true },
package
// CHECK:STDOUT: { index: 42, kind: 'Partial', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'partial', has_trailing_space: true },
// CHECK:STDOUT: { index: 43, kind: 'Partial', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'partial', has_trailing_space: true },
partial
// CHECK:STDOUT: { index: 43, kind: 'Private', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'private', has_trailing_space: true },
// CHECK:STDOUT: { index: 44, kind: 'Private', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'private', has_trailing_space: true },
private
// CHECK:STDOUT: { index: 44, kind: 'Protected', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'protected', has_trailing_space: true },
// CHECK:STDOUT: { index: 45, kind: 'Protected', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'protected', has_trailing_space: true },
protected
// CHECK:STDOUT: { index: 45, kind: 'Require', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'require', has_trailing_space: true },
// CHECK:STDOUT: { index: 46, kind: 'Require', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'require', has_trailing_space: true },
require
// CHECK:STDOUT: { index: 46, kind: 'Return', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'return', has_trailing_space: true },
// CHECK:STDOUT: { index: 47, kind: 'Return', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'return', has_trailing_space: true },
return
// CHECK:STDOUT: { index: 47, kind: 'Returned', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'returned', has_trailing_space: true },
// CHECK:STDOUT: { index: 48, kind: 'Returned', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'returned', has_trailing_space: true },
returned
// CHECK:STDOUT: { index: 48, kind: 'SelfTypeIdentifier', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'Self', has_trailing_space: true },
// CHECK:STDOUT: { index: 49, kind: 'SelfTypeIdentifier', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'Self', has_trailing_space: true },
Self
// CHECK:STDOUT: { index: 49, kind: 'SelfValueIdentifier', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'self', has_trailing_space: true },
// CHECK:STDOUT: { index: 50, kind: 'SelfValueIdentifier', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'self', has_trailing_space: true },
self
// CHECK:STDOUT: { index: 50, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'String', has_trailing_space: true },
// CHECK:STDOUT: { index: 51, kind: 'StringTypeLiteral', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'String', has_trailing_space: true },
String
// CHECK:STDOUT: { index: 51, kind: 'Template', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'template', has_trailing_space: true },
// CHECK:STDOUT: { index: 52, kind: 'Template', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'template', has_trailing_space: true },
template
// CHECK:STDOUT: { index: 52, kind: 'Then', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'then', has_trailing_space: true },
// CHECK:STDOUT: { index: 53, kind: 'Then', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'then', has_trailing_space: true },
then
// CHECK:STDOUT: { index: 53, kind: 'True', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'true', has_trailing_space: true },
// CHECK:STDOUT: { index: 54, kind: 'True', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'true', has_trailing_space: true },
true
// CHECK:STDOUT: { index: 54, kind: 'Type', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'type', has_trailing_space: true },
// CHECK:STDOUT: { index: 55, kind: 'Type', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'type', has_trailing_space: true },
type
// CHECK:STDOUT: { index: 55, kind: 'Underscore', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: '_', has_trailing_space: true },
// CHECK:STDOUT: { index: 56, kind: 'Underscore', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: '_', has_trailing_space: true },
_
// CHECK:STDOUT: { index: 56, kind: 'Var', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true },
// CHECK:STDOUT: { index: 57, kind: 'Var', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'var', has_trailing_space: true },
var
// CHECK:STDOUT: { index: 57, kind: 'Virtual', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'virtual', has_trailing_space: true },
// CHECK:STDOUT: { index: 58, kind: 'Virtual', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'virtual', has_trailing_space: true },
virtual
// CHECK:STDOUT: { index: 58, kind: 'Where', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'where', has_trailing_space: true },
// CHECK:STDOUT: { index: 59, kind: 'Where', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'where', has_trailing_space: true },
where
// CHECK:STDOUT: { index: 59, kind: 'While', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'while', has_trailing_space: true },
// CHECK:STDOUT: { index: 60, kind: 'While', line: {{ *}}[[@LINE+1]], column: 1, indent: 1, spelling: 'while', has_trailing_space: true },
while
// CHECK:STDOUT: { index: 60, kind: 'Identifier', line: {{ *}}[[@LINE+3]], column: 1, indent: 1, spelling: 'notakeyword', identifier: 0, has_trailing_space: true },
// CHECK:STDOUT: { index: 61, kind: 'EndOfFile', line: {{ *}}[[@LINE+2]], column: {{[0-9]+}}, indent: 1, spelling: '' },
// CHECK:STDOUT: { index: 61, kind: 'Identifier', line: {{ *}}[[@LINE+3]], column: 1, indent: 1, spelling: 'notakeyword', identifier: 0, has_trailing_space: true },
// CHECK:STDOUT: { index: 62, kind: 'EndOfFile', line: {{ *}}[[@LINE+2]], column: {{[0-9]+}}, indent: 1, spelling: '' },
// CHECK:STDOUT: ]
notakeyword
+1
View File
@@ -135,6 +135,7 @@ CARBON_KEYWORD_TOKEN(Break, "break")
CARBON_KEYWORD_TOKEN(Case, "case")
CARBON_KEYWORD_TOKEN(Choice, "choice")
CARBON_KEYWORD_TOKEN(Class, "class")
CARBON_KEYWORD_TOKEN(Const, "const")
CARBON_KEYWORD_TOKEN(Constraint, "constraint")
CARBON_KEYWORD_TOKEN(Continue, "continue")
CARBON_KEYWORD_TOKEN(Default, "default")
+7
View File
@@ -256,6 +256,13 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(QualifiedDeclaration, 2)
// QualifiedExpression
CARBON_PARSE_NODE_KIND_CHILD_COUNT(MemberAccessExpression, 2)
// A pointer member access expression, such as `a->b` or
// `GetObject()->(Interface.member)`:
// _external_: lhs expression
// _external_: rhs expression
// QualifiedExpression
CARBON_PARSE_NODE_KIND_CHILD_COUNT(PointerMemberAccessExpression, 2)
// A literal.
CARBON_PARSE_NODE_KIND_CHILD_COUNT(Literal, 0)
+16 -5
View File
@@ -6,10 +6,6 @@
namespace Carbon {
CARBON_DIAGNOSTIC(
OperatorRequiresParentheses, Error,
"Parentheses are required to disambiguate operator precedence.");
auto ParserHandleExpression(ParserContext& context) -> void {
auto state = context.PopState();
@@ -21,7 +17,13 @@ auto ParserHandleExpression(ParserContext& context) -> void {
OperatorPriority::RightFirst) {
// The precedence rules don't permit this prefix operator in this
// context. Diagnose this, but carry on and parse it anyway.
context.emitter().Emit(*context.position(), OperatorRequiresParentheses);
CARBON_DIAGNOSTIC(
UnaryOperatorRequiresParentheses, Error,
"Parentheses are required around this unary `{0}` operator.",
TokenKind);
context.emitter().Emit(*context.position(),
UnaryOperatorRequiresParentheses,
context.PositionKind());
} else {
// Check that this operator follows the proper whitespace rules.
context.DiagnoseOperatorFixity(ParserContext::OperatorFixity::Prefix);
@@ -123,6 +125,12 @@ auto ParserHandleExpressionInPostfixLoop(ParserContext& context) -> void {
context.PushState(state);
break;
}
case TokenKind::MinusGreater: {
context.PushState(state);
state.state = ParserState::ArrowExpression;
context.PushState(state);
break;
}
case TokenKind::OpenParen: {
context.PushState(state);
state.state = ParserState::CallExpression;
@@ -171,6 +179,9 @@ auto ParserHandleExpressionLoop(ParserContext& context) -> void {
// Either the LHS operator and this operator are ambiguous, or the
// LHS operator is a unary operator that can't be nested within
// this operator. Either way, parentheses are required.
CARBON_DIAGNOSTIC(
OperatorRequiresParentheses, Error,
"Parentheses are required to disambiguate operator precedence.");
context.emitter().Emit(*context.position(), OperatorRequiresParentheses);
state.has_error = true;
} else {
+21 -9
View File
@@ -6,21 +6,25 @@
namespace Carbon {
// Handles PeriodAs variants.
// Handles PeriodAs variants and ArrowExpression.
// TODO: This currently only supports identifiers on the rhs, but will in the
// future need to handle things like `object.(Interface.member)` for qualifiers.
auto ParserHandlePeriod(ParserContext& context, ParseNodeKind node_kind)
static auto ParserHandlePeriodOrArrow(ParserContext& context,
ParseNodeKind node_kind, bool is_arrow)
-> void {
auto state = context.PopState();
// `.` identifier
auto dot = context.ConsumeChecked(TokenKind::Period);
auto dot = context.ConsumeChecked(is_arrow ? TokenKind::MinusGreater
: TokenKind::Period);
if (!context.ConsumeAndAddLeafNodeIf(TokenKind::Identifier,
ParseNodeKind::Name)) {
CARBON_DIAGNOSTIC(ExpectedIdentifierAfterDot, Error,
"Expected identifier after `.`.");
context.emitter().Emit(*context.position(), ExpectedIdentifierAfterDot);
CARBON_DIAGNOSTIC(ExpectedIdentifierAfterDotOrArrow, Error,
"Expected identifier after `{0}`.", llvm::StringRef);
context.emitter().Emit(*context.position(),
ExpectedIdentifierAfterDotOrArrow,
is_arrow ? "->" : ".");
// If we see a keyword, assume it was intended to be a name.
// TODO: Should keywords be valid here?
if (context.PositionKind().is_keyword()) {
@@ -39,15 +43,23 @@ auto ParserHandlePeriod(ParserContext& context, ParseNodeKind node_kind)
}
auto ParserHandlePeriodAsDeclaration(ParserContext& context) -> void {
ParserHandlePeriod(context, ParseNodeKind::QualifiedDeclaration);
ParserHandlePeriodOrArrow(context, ParseNodeKind::QualifiedDeclaration,
/*is_arrow=*/false);
}
auto ParserHandlePeriodAsExpression(ParserContext& context) -> void {
ParserHandlePeriod(context, ParseNodeKind::MemberAccessExpression);
ParserHandlePeriodOrArrow(context, ParseNodeKind::MemberAccessExpression,
/*is_arrow=*/false);
}
auto ParserHandlePeriodAsStruct(ParserContext& context) -> void {
ParserHandlePeriod(context, ParseNodeKind::StructFieldDesignator);
ParserHandlePeriodOrArrow(context, ParseNodeKind::StructFieldDesignator,
/*is_arrow=*/false);
}
auto ParserHandleArrowExpression(ParserContext& context) -> void {
ParserHandlePeriodOrArrow(
context, ParseNodeKind::PointerMemberAccessExpression, /*is_arrow=*/true);
}
} // namespace Carbon
+10
View File
@@ -215,6 +215,13 @@ CARBON_PARSER_STATE(DeclarationScopeLoop)
// (state done)
CARBON_PARSER_STATE_VARIANTS3(Period, Declaration, Expression, Struct)
// Handles `->name` expressions. Identical to PeriodAsExpression except for the
// leading token.
//
// Always:
// (state done)
CARBON_PARSER_STATE(ArrowExpression)
// Handles processing of an expression.
//
// If `If`:
@@ -250,6 +257,9 @@ CARBON_PARSER_STATE(ExpressionInPostfix)
// If `Period`:
// 1. PeriodAsExpression
// 2. ExpressionInPostfixLoop
// If `MinusGreater`:
// 1. ArrowExpression
// 2. ExpressionInPostfixLoop
// If `OpenParen`:
// 1. CallExpression
// 2. ExpressionInPostfixLoop
+17 -4
View File
@@ -29,6 +29,7 @@ enum PrecedenceLevel : int8_t {
BitwiseXor,
BitShift,
// Type formation.
TypePrefix,
TypePostfix,
// Sentinel representing a type context.
Type,
@@ -55,21 +56,26 @@ struct OperatorPriorityTable {
// relationships.
MarkHigherThan({Highest}, {TermPrefix});
MarkHigherThan({TermPrefix}, {NumericPrefix, BitwisePrefix, LogicalPrefix,
NumericPostfix, TypePostfix});
NumericPostfix});
MarkHigherThan({NumericPrefix, NumericPostfix},
{Modulo, Multiplicative, BitShift});
MarkHigherThan({Multiplicative}, {Additive});
MarkHigherThan({BitwisePrefix},
{BitwiseAnd, BitwiseOr, BitwiseXor, BitShift});
MarkHigherThan({TypePostfix}, {Type});
MarkHigherThan(
{Modulo, Additive, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift, Type},
{Modulo, Additive, BitwiseAnd, BitwiseOr, BitwiseXor, BitShift},
{Relational});
MarkHigherThan({Relational, LogicalPrefix}, {LogicalAnd, LogicalOr});
MarkHigherThan({LogicalAnd, LogicalOr}, {If});
MarkHigherThan({If}, {SimpleAssignment, CompoundAssignment});
MarkHigherThan({SimpleAssignment, CompoundAssignment}, {Lowest});
// Types are mostly a separate precedence graph.
MarkHigherThan({Highest}, {TypePrefix});
MarkHigherThan({TypePrefix}, {TypePostfix});
MarkHigherThan({TypePostfix}, {Type});
MarkHigherThan({Type}, {If});
// Compute the transitive closure of the above relationships: if we parse
// `a $ b @ c` as `(a $ b) @ c` and parse `b @ c % d` as `(b @ c) % d`,
// then we will parse `a $ b @ c % d` as `((a $ b) @ c) % d` and should
@@ -137,7 +143,9 @@ struct OperatorPriorityTable {
// For prefix operators, RightFirst would mean `@@x` is `@(@x)` and
// Ambiguous would mean it's an error. LeftFirst is meaningless. For now we
// allow all prefix operators to be repeated.
// allow all prefix operators other than `const` to be repeated.
//
// TODO: The design does not permit repeating most unary operators.
for (PrecedenceLevel prefix :
{TermPrefix, NumericPrefix, BitwisePrefix, LogicalPrefix, If}) {
table[prefix][prefix] = OperatorPriority::RightFirst;
@@ -199,6 +207,7 @@ auto PrecedenceGroup::ForLeading(TokenKind kind)
-> std::optional<PrecedenceGroup> {
switch (kind) {
case TokenKind::Star:
case TokenKind::Amp:
return PrecedenceGroup(TermPrefix);
case TokenKind::Not:
@@ -215,6 +224,9 @@ auto PrecedenceGroup::ForLeading(TokenKind kind)
case TokenKind::If:
return PrecedenceGroup(If);
case TokenKind::Const:
return PrecedenceGroup(TypePrefix);
default:
return std::nullopt;
}
@@ -288,6 +300,7 @@ auto PrecedenceGroup::ForTrailing(TokenKind kind, bool infix)
// Prefix-only operators.
case TokenKind::Not:
case TokenKind::Const:
break;
// Symbolic tokens that might be operators eventually.
+22 -1
View File
@@ -41,7 +41,26 @@
// CHECK:STDOUT: {kind: 'MemberAccessExpression', text: '.', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 38},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'Modify'},
// CHECK:STDOUT: {kind: 'DeducedParameterListStart', text: '['},
// CHECK:STDOUT: {kind: 'SelfValueName', text: 'self'},
// CHECK:STDOUT: {kind: 'SelfTypeNameExpression', text: 'Self'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 4},
// CHECK:STDOUT: {kind: 'Address', text: 'addr', subtree_size: 5},
// CHECK:STDOUT: {kind: 'DeducedParameterList', text: ']', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 12},
// CHECK:STDOUT: {kind: 'SelfValueName', text: 'self'},
// CHECK:STDOUT: {kind: 'Name', text: 'x'},
// CHECK:STDOUT: {kind: 'PointerMemberAccessExpression', text: '->', subtree_size: 3},
// CHECK:STDOUT: {kind: 'Literal', text: '1'},
// CHECK:STDOUT: {kind: 'InfixOperator', text: '=', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 19},
// CHECK:STDOUT: {kind: 'ClassDefinition', text: '}', subtree_size: 57},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
@@ -49,4 +68,6 @@ class Foo {
fn Make() -> Self { return {.x = 0}; }
fn Baz[self: Self]() -> i32 { return self.x; }
fn Modify[addr self: Self*]() { self->x = 1; }
}
+26
View File
@@ -0,0 +1,26 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'NamespaceStart', text: 'namespace'},
// CHECK:STDOUT: {kind: 'Name', text: 'Foo'},
// CHECK:STDOUT: {kind: 'Namespace', text: ';', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'Foo'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'Bar'},
// CHECK:STDOUT: {kind: 'CallExpressionStart', text: '(', subtree_size: 2},
// CHECK:STDOUT: {kind: 'CallExpression', text: ')', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 4},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', has_error: yes, subtree_size: 7},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 8},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
namespace Foo;
// CHECK:STDERR: fail_arrow.carbon:[[@LINE+3]]:7: `fn` requires a `(` for parameters.
// CHECK:STDERR: fn Foo->Bar() {}
// CHECK:STDERR: ^
fn Foo->Bar() {}
+1 -1
View File
@@ -44,7 +44,7 @@ fn F() {
// CHECK:STDERR: fail_variety.carbon:[[@LINE+6]]:38: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: n = a * b + c * d = d * d << e & f - not g;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_variety.carbon:[[@LINE+3]]:40: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: fail_variety.carbon:[[@LINE+3]]:40: Parentheses are required around this unary `not` operator.
// CHECK:STDERR: n = a * b + c * d = d * d << e & f - not g;
// CHECK:STDERR: ^
n = a * b + c * d = d * d << e & f - not g;
+8 -6
View File
@@ -9,14 +9,16 @@
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'n'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '++', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '++', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ExpressionStatement', text: ';', subtree_size: 4},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 10},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'n'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '&', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 4},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ExpressionStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 12},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
fn F() {
++++n;
***&n;
}
@@ -0,0 +1,25 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'F'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: 'const', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: 'const', subtree_size: 3},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 10},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 11},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
// CHECK:STDERR: recover_prefix_repeat.carbon:[[@LINE+3]]:17: Parentheses are required around this unary `const` operator.
// CHECK:STDERR: fn F() -> const const i32* {
// CHECK:STDERR: ^
fn F() -> const const i32* {
}
+61
View File
@@ -0,0 +1,61 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'A'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: 'const', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 4},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 9},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'A'},
// CHECK:STDOUT: {kind: 'CallExpressionStart', text: '(', subtree_size: 2},
// CHECK:STDOUT: {kind: 'CallExpression', text: ')', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 15},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'B'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParenExpressionOrTupleLiteralStart', text: '('},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: 'const', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParenExpression', text: ')', subtree_size: 4},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 11},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'B'},
// CHECK:STDOUT: {kind: 'CallExpressionStart', text: '(', subtree_size: 2},
// CHECK:STDOUT: {kind: 'CallExpression', text: ')', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'C'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParenExpressionOrTupleLiteralStart', text: '('},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ParenExpression', text: ')', subtree_size: 4},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: 'const', subtree_size: 5},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 11},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'C'},
// CHECK:STDOUT: {kind: 'CallExpressionStart', text: '(', subtree_size: 2},
// CHECK:STDOUT: {kind: 'CallExpression', text: ')', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
fn A() -> const i32* { return A(); }
fn B() -> (const i32)* { return B(); }
fn C() -> const (i32*) { return C(); }
@@ -0,0 +1,79 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'F'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'Literal', text: '3'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'InfixOperator', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'Literal', text: '4'},
// CHECK:STDOUT: {kind: 'InfixOperator', text: '*', has_error: yes, subtree_size: 6},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 8},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'G'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: '4'},
// CHECK:STDOUT: {kind: 'InfixOperator', text: '+', has_error: yes, subtree_size: 4},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 6},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 14},
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'H'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', has_error: yes, subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 13},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
fn F() -> i32 {
// TODO: Indicate the locations of both operators involved in the precedence
// error, so that it's clear what ambiguity we're referring to.
// TODO: Improve error recovery so that we recover as `3 * (i32*) * 4`, not
// as `(3 * i32)* * 4`, to suppress the second error here.
// CHECK:STDERR: fail_pointer_type_in_expression.carbon:[[@LINE+6]]:17: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return 3 * i32* * 4;
// CHECK:STDERR: ^
// CHECK:STDERR: fail_pointer_type_in_expression.carbon:[[@LINE+3]]:19: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return 3 * i32* * 4;
// CHECK:STDERR: ^
return 3 * i32* * 4;
}
fn G() -> i32 {
// CHECK:STDERR: fail_pointer_type_in_expression.carbon:[[@LINE+3]]:15: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return i32* + 4;
// CHECK:STDERR: ^
return i32* + 4;
}
fn H() -> i32 {
// CHECK:STDERR: fail_pointer_type_in_expression.carbon:[[@LINE+3]]:14: Parentheses are required to disambiguate operator precedence.
// CHECK:STDERR: return *i32*;
// CHECK:STDERR: ^
return *i32*;
}
+44
View File
@@ -0,0 +1,44 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'F'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'Name', text: 'p'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 4},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 6},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 12},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'p'},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 3},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 16},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
// CHECK:STDOUT: {kind: 'Name', text: 'T'},
// CHECK:STDOUT: {kind: 'Literal', text: 'type'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
// CHECK:STDOUT: {kind: 'Literal', text: 'true'},
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', subtree_size: 3},
// CHECK:STDOUT: {kind: 'Literal', text: 'f64'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else', subtree_size: 8},
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 14},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
fn F(p: i32*) -> i32* {
return p;
}
var T: type = if true then i32* else f64*;
+54
View File
@@ -0,0 +1,54 @@
// 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
//
// AUTOUPDATE
// CHECK:STDOUT: [
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
// CHECK:STDOUT: {kind: 'Name', text: 'F'},
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
// CHECK:STDOUT: {kind: 'Name', text: 'n'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
// CHECK:STDOUT: {kind: 'Literal', text: '0'},
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 7},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
// CHECK:STDOUT: {kind: 'Name', text: 'p'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 4},
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'n'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '&', subtree_size: 2},
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 9},
// CHECK:STDOUT: {kind: 'VariableIntroducer', text: 'var'},
// CHECK:STDOUT: {kind: 'Name', text: 'q'},
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PostfixOperator', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 5},
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'p'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '&', subtree_size: 2},
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 10},
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
// CHECK:STDOUT: {kind: 'NameExpression', text: 'q'},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 2},
// CHECK:STDOUT: {kind: 'PrefixOperator', text: '*', subtree_size: 3},
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 5},
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 39},
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
// CHECK:STDOUT: ]
fn F() -> i32 {
var n: i32 = 0;
var p: i32* = &n;
var q: i32** = &p;
return **q;
}
@@ -65,6 +65,12 @@ auto SemanticsHandleMemberAccessExpression(SemanticsContext& context,
return true;
}
auto SemanticsHandlePointerMemberAccessExpression(SemanticsContext& context,
ParseTree::Node parse_node)
-> bool {
return context.TODO(parse_node, "HandlePointerMemberAccessExpression");
}
auto SemanticsHandleName(SemanticsContext& context, ParseTree::Node parse_node)
-> bool {
auto name_str = context.parse_tree().GetNodeText(parse_node);