mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
Parsing for pointer types and pointer operators. (#3026)
This provides parsing support for the functionality added in #2006.
This commit is contained in:
@@ -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
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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* {
|
||||
}
|
||||
@@ -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*;
|
||||
}
|
||||
@@ -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*;
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user