public NamedFunctionDeclarationSyntax ParseNamedFunction( FixedList <AttributeSyntax> attributes, FixedList <IModiferToken> modifiers) { Tokens.Expect <IFunctionKeywordToken>(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); var genericParameters = AcceptGenericParameters(); var name = nameContext.Qualify(identifier.Value); var bodyParser = NestedParser(name); var parameters = bodyParser.ParseParameters(); var lifetimeBounds = bodyParser.ParseLifetimeBounds(); ExpressionSyntax returnType = null; if (Tokens.Accept <IRightArrowToken>()) { returnType = ParseExpression(); } var genericConstraints = ParseGenericConstraints(); var mayEffects = ParseMayEffects(); var noEffects = ParseNoEffects(); var(requires, ensures) = ParseFunctionContracts(); var body = bodyParser.ParseFunctionBody(); return(new NamedFunctionDeclarationSyntax(File, modifiers, name, identifier.Span, genericParameters, parameters, lifetimeBounds, returnType, genericConstraints, mayEffects, noEffects, requires, ensures, body)); }
private FieldDeclarationSyntax ParseField( FixedList <AttributeSyntax> attributes, FixedList <IModiferToken> modifiers) { // TODO include these in the syntax tree var binding = Tokens.Expect <IBindingToken>(); var getterAccess = AcceptFieldGetter(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); var name = nameContext.Qualify(identifier.Value); ExpressionSyntax typeExpression = null; if (Tokens.Accept <IColonToken>()) { // Need to not consume the assignment that separates the type from the initializer, // hence the min operator precedence. typeExpression = ParseExpression(OperatorPrecedence.AboveAssignment); } ExpressionSyntax initializer = null; if (Tokens.Accept <IEqualsToken>()) { initializer = ParseExpression(); } Tokens.Expect <ISemicolonToken>(); return(new FieldDeclarationSyntax(File, attributes, modifiers, getterAccess, name, identifier.Span, typeExpression, initializer)); }
private ThrowEffectEntrySyntax ParseThrowEffectEntry() { var isParams = Tokens.Accept <IParamsKeywordToken>(); var exceptionType = ParseExpression(); return(new ThrowEffectEntrySyntax(isParams, exceptionType)); }
private ConstDeclarationSyntax ParseConst( FixedList <AttributeSyntax> attributes, FixedList <IModiferToken> modifiers) { try { Tokens.Expect <IConstKeywordToken>(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); var name = nameContext.Qualify(identifier.Value); ExpressionSyntax type = null; if (Tokens.Accept <IColonToken>()) { // Need to not consume the assignment that separates the type from the initializer, // hence the min operator precedence. type = ParseExpression(OperatorPrecedence.AboveAssignment); } ExpressionSyntax initializer = null; if (Tokens.Accept <IEqualsToken>()) { initializer = ParseExpression(); } Tokens.Expect <ISemicolonToken>(); return(new ConstDeclarationSyntax(File, attributes, modifiers, name, identifier.Span, type, initializer)); } catch (ParseFailedException) { SkipToEndOfStatement(); throw; } }
internal FieldDeclarationSyntax ParseField( IClassDeclarationSyntax declaringType, bool mutableBinding, ModifierParser modifiers) { var accessModifer = modifiers.ParseAccessModifier(); modifiers.ParseEndOfModifiers(); // We should only be called when there is a binding keyword var binding = Tokens.Required <IBindingToken>(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); Name name = identifier.Value; Tokens.Expect <IColonToken>(); var type = ParseType(); IExpressionSyntax?initializer = null; if (Tokens.Accept <IEqualsToken>()) { initializer = ParseExpression(); } var semicolon = Tokens.Expect <ISemicolonToken>(); var span = TextSpan.Covering(binding, semicolon); return(new FieldDeclarationSyntax(declaringType, span, File, accessModifer, mutableBinding, identifier.Span, name, type, initializer)); }
// Requires the binding has already been consumed private IStatementSyntax ParseRestOfVariableDeclaration( TextSpan binding, bool mutableBinding) { var identifier = Tokens.RequiredToken <IIdentifierToken>(); var name = identifier.Value; ITypeSyntax?type = null; bool inferMutableType = false; if (Tokens.Accept <IColonToken>()) { (type, inferMutableType) = ParseVariableDeclarationType(); } IExpressionSyntax?initializer = null; if (Tokens.Accept <IEqualsToken>()) { initializer = ParseExpression(); } var semicolon = Tokens.Expect <ISemicolonToken>(); var span = TextSpan.Covering(binding, semicolon); return(new VariableDeclarationStatementSyntax(span, mutableBinding, name, identifier.Span, type, inferMutableType, initializer)); }
private ExpressionSyntax AcceptBaseClass() { if (!Tokens.Accept <IColonToken>()) { return(null); } return(ParseExpression()); }
private FixedList <ExpressionSyntax> AcceptBaseTypes() { if (!Tokens.Accept <ILessThanColonToken>()) { return(null); } return(AcceptOneOrMore <ExpressionSyntax, ICommaToken>(ParseExpression)); }
private ExpressionSyntax AcceptInvariant() { if (!Tokens.Accept <IInvariantKeywordToken>()) { return(null); } return(ParseExpression()); }
private FixedList <EffectSyntax> ParseNoEffects() { if (!Tokens.Accept <INoKeywordToken>()) { return(FixedList <EffectSyntax> .Empty); } return(AcceptOneOrMore <EffectSyntax, ICommaToken>(ParseEffect)); }
private (ITypeSyntax?, IReachabilityAnnotationsSyntax) ParseReturn() { if (Tokens.Accept <IRightArrowToken>()) { return(ParseType(), ParseReachabilityAnnotations()); } return(null, new ReachabilityAnnotationsSyntax(Tokens.Current.Span.AtStart(), null, null)); }
public BlockSyntax AcceptBlock() { var openBrace = Tokens.Current.Span; if (!Tokens.Accept <IOpenBraceToken>()) { return(null); } return(ParseRestOfBlock(openBrace)); }
public GenericConstraintSyntax AcceptGenericConstraint() { if (!Tokens.Accept <IWhereKeywordToken>()) { return(null); } var expression = ParseExpression(); return(new GenericConstraintSyntax(expression)); }
/// <summary> /// Skip tokens until we reach what we assume to be the end of a statement /// </summary> // TODO does this belong on a statement parser or something private void SkipToEndOfStatement() { while (!Tokens.AtEnd <ISemicolonToken>()) { Tokens.Next(); } // Consume the semicolon is we aren't at the end of the file. var _ = Tokens.Accept <ISemicolonToken>(); }
public FixedList <GenericParameterSyntax> AcceptGenericParameters() { if (!Tokens.Accept <IOpenBracketToken>()) { return(null); } var parameters = ParseMany <GenericParameterSyntax, ICommaToken, ICloseBracketToken>(ParseGenericParameter); Tokens.Expect <ICloseBracketToken>(); return(parameters); }
public ExpressionSyntax ParseName() { ExpressionSyntax name = ParseSimpleName(); while (Tokens.Accept <IDotToken>()) { var simpleName = ParseSimpleName(); var span = TextSpan.Covering(name.Span, simpleName.Span); name = new MemberAccessExpressionSyntax(span, name, AccessOperator.Standard, simpleName); } return(name); }
public ParameterSyntax ParseParameter() { switch (Tokens.Current) { case IRefKeywordToken _: case IMutableKeywordToken _: case ISelfKeywordToken _: { var span = Tokens.Current.Span; var refSelf = Tokens.Accept <IRefKeywordToken>(); var mutableSelf = Tokens.Accept <IMutableKeywordToken>(); var selfSpan = Tokens.Expect <ISelfKeywordToken>(); span = TextSpan.Covering(span, selfSpan); var name = nameContext.Qualify(SpecialName.Self); return(new SelfParameterSyntax(span, name, refSelf, mutableSelf)); } case IDotToken _: { var dot = Tokens.Expect <IDotToken>(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); var equals = Tokens.AcceptToken <IEqualsToken>(); ExpressionSyntax defaultValue = null; if (equals != null) { defaultValue = ParseExpression(); } var span = TextSpan.Covering(dot, identifier.Span, defaultValue?.Span); var name = nameContext.Qualify(SimpleName.Special("field_" + identifier.Value)); return(new FieldParameterSyntax(span, name, defaultValue)); } default: { var span = Tokens.Current.Span; var isParams = Tokens.Accept <IParamsKeywordToken>(); var mutableBinding = Tokens.Accept <IVarKeywordToken>(); var identifier = Tokens.RequiredToken <IIdentifierOrUnderscoreToken>(); var name = nameContext.Qualify(variableNumbers.VariableName(identifier.Value)); Tokens.Expect <IColonToken>(); // Need to not consume the assignment that separates the type from the default value, // hence the min operator precedence. var type = ParseExpression(OperatorPrecedence.AboveAssignment); ExpressionSyntax defaultValue = null; if (Tokens.Accept <IEqualsToken>()) { defaultValue = ParseExpression(); } span = TextSpan.Covering(span, type.Span, defaultValue?.Span); return(new NamedParameterSyntax(span, isParams, mutableBinding, name, type, defaultValue)); } } }
private AttributeSyntax AcceptAttribute() { if (!Tokens.Accept <IHashHashToken>()) { return(null); } var name = ParseName(); FixedList <ArgumentSyntax> arguments = null; if (Tokens.Accept <IOpenParenToken>()) { arguments = ParseArguments(); Tokens.Expect <ICloseParenToken>(); } return(new AttributeSyntax(name, arguments)); }
public UsingDirectiveSyntax AcceptUsingDirective() { if (!Tokens.Accept <IUsingKeywordToken>()) { return(null); } var identifiers = AcceptOneOrMore <IIdentifierToken, IDotToken>( () => Tokens.AcceptToken <IIdentifierToken>()); RootName name = GlobalNamespaceName.Instance; foreach (var identifier in identifiers) { name = name.Qualify(identifier.Value); } Tokens.Expect <ISemicolonToken>(); return(new UsingDirectiveSyntax((Name)name)); }
public GenericParameterSyntax ParseGenericParameter() { Name name; var dollar = Tokens.AcceptToken <IDollarToken>(); if (dollar != null) { var lifetime = Tokens.RequiredToken <ILifetimeNameToken>(); var span = TextSpan.Covering(dollar.Span, lifetime.Span); switch (lifetime) { case IIdentifierToken lifetimeIdentifier: name = nameContext.Qualify(lifetimeIdentifier.Value); break; case IRefKeywordToken _: name = nameContext.Qualify(SpecialName.Ref); break; case IOwnedKeywordToken _: Add(ParseError.OwnedNotValidAsGenericLifetimeParameter(File, span)); // We just treat it as if they had written `$\owned` name = nameContext.Qualify("owned"); break; default: throw NonExhaustiveMatchException.For(lifetime); } return(new GenericParameterSyntax(true, false, name, null)); } var isParams = Tokens.Accept <IParamsKeywordToken>(); var identifier = Tokens.RequiredToken <IIdentifierToken>(); name = nameContext.Qualify(identifier.Value); ExpressionSyntax typeExpression = null; if (Tokens.Accept <IColonToken>()) { typeExpression = ParseExpression(); } return(new GenericParameterSyntax(false, isParams, name, typeExpression)); }
public INamedParameterSyntax ParseFunctionParameter() { var span = Tokens.Current.Span; var mutableBinding = Tokens.Accept <IVarKeywordToken>(); var identifier = Tokens.RequiredToken <IIdentifierOrUnderscoreToken>(); var name = identifier.Value; Tokens.Expect <IColonToken>(); var type = ParseType(); IExpressionSyntax?defaultValue = null; if (Tokens.Accept <IEqualsToken>()) { defaultValue = ParseExpression(); } span = TextSpan.Covering(span, type.Span, defaultValue?.Span); return(new NamedParameterSyntax(span, mutableBinding, name, type, defaultValue)); }
public IParameterSyntax ParseMethodParameter() { switch (Tokens.Current) { case IMutableKeywordToken _: case ISelfKeywordToken _: { var span = Tokens.Current.Span; var mutableSelf = Tokens.Accept <IMutableKeywordToken>(); var selfSpan = Tokens.Expect <ISelfKeywordToken>(); span = TextSpan.Covering(span, selfSpan); return(new SelfParameterSyntax(span, mutableSelf)); } default: return(ParseFunctionParameter()); } }
public FixedList <T> ParseMany <T, TSeparator, TTerminator>(Func <T> parseItem) where T : class where TSeparator : class, IToken where TTerminator : IToken { var items = new List <T>(); while (!Tokens.AtEnd <TTerminator>()) { items.Add(parseItem()); if (!Tokens.Accept <TSeparator>()) { break; } } return(items.ToFixedList()); }
public FixedList <T> AcceptSeparatedList <T, TSeparator>(Func <T> acceptItem) where T : class where TSeparator : class, IToken { var items = new List <T>(); var item = acceptItem(); while (item != null) { items.Add(item); if (!Tokens.Accept <TSeparator>()) { break; } item = acceptItem(); } return(items.ToFixedList()); }
private NameSyntax ParseSimpleName() { var identifier = Tokens.RequiredToken <IIdentifierToken>(); var name = new SimpleName(identifier.Value); NameSyntax syntax; if (Tokens.Accept <IOpenBracketToken>()) { var arguments = ParseArguments(); var closeBracket = Tokens.Expect <ICloseBracketToken>(); var span = TextSpan.Covering(identifier.Span, closeBracket); syntax = new GenericNameSyntax(span, identifier.Value, arguments); } else { syntax = new IdentifierNameSyntax(identifier.Span, name); } return(syntax); }
private (NamespaceName, TextSpan) ParseNamespaceName() { var firstSegment = Tokens.RequiredToken <IIdentifierToken>(); var span = firstSegment.Span; NamespaceName name = firstSegment.Value; while (Tokens.Accept <IDotToken>()) { var(nameSegment, segmentSpan) = Tokens.ExpectToken <IIdentifierToken>(); // We need the span to cover a trailing dot span = TextSpan.Covering(span, segmentSpan); if (nameSegment is null) { break; } name = name.Qualify(nameSegment.Value); } return(name, span); }
/// <summary> /// Parse an expected item and then parse additional items as long as there is /// a separator. /// </summary> public FixedList <T> ParseManySeparated <T, TSeparator>(Func <T> parseItem) //where T : class where TSeparator : class, IToken { var item = parseItem(); if (item is null) { throw new ParseFailedException(); } var items = new List <T>() { item }; while (Tokens.Accept <TSeparator>()) { items.Add(parseItem()); } return(items.ToFixedList()); }
// Requires the binding has already been consumed private StatementSyntax ParseRestOfVariableDeclaration(bool mutableBinding) { var identifier = Tokens.RequiredToken <IIdentifierToken>(); var name = this.nameContext.Qualify(variableNumbers.VariableName(identifier.Value)); ExpressionSyntax type = null; if (Tokens.Accept <IColonToken>()) { // Need to not consume the assignment that separates the type from the initializer, // hence the min operator precedence. type = ParseExpression(OperatorPrecedence.LogicalOr); } ExpressionSyntax initializer = null; if (Tokens.Accept <IEqualsToken>()) { initializer = ParseExpression(); } Tokens.Expect <ISemicolonToken>(); return(new VariableDeclarationStatementSyntax(mutableBinding, name, identifier.Span, type, initializer)); }
public FixedList <T> AcceptOneOrMore <T, TSeparator>(Func <T> acceptItem) where T : class where TSeparator : class, IToken { var item = acceptItem(); if (item == null) { throw new ParseFailedException(); } var items = new List <T>(); while (item != null) { items.Add(item); if (!Tokens.Accept <TSeparator>()) { break; } item = acceptItem(); } return(items.ToFixedList()); }
public OperatorDeclarationSyntax ParseOperator( FixedList <AttributeSyntax> attributes, FixedList <IModiferToken> modifiers) { var operatorKeyword = Tokens.Expect <IOperatorKeywordToken>(); var genericParameters = AcceptGenericParameters(); // TODO correctly store these in the syntax class OverloadableOperator oper; TextSpan endOperatorSpan; switch (Tokens.Current) { case IHashToken _: Tokens.Expect <IHashToken>(); switch (Tokens.Current) { case IOpenParenToken _: Tokens.Next(); endOperatorSpan = Tokens.Expect <ICloseParenToken>(); oper = OverloadableOperator.TupleInitializer; break; case IOpenBracketToken _: Tokens.Next(); endOperatorSpan = Tokens.Expect <ICloseBracketToken>(); oper = OverloadableOperator.ListInitializer; break; case IOpenBraceToken _: Tokens.Next(); endOperatorSpan = Tokens.Expect <ICloseBraceToken>(); oper = OverloadableOperator.SetInitializer; break; default: throw NonExhaustiveMatchException.For(Tokens.Current); } break; case IStringLiteralToken _: endOperatorSpan = Tokens.Expect <IStringLiteralToken>(); // TODO need to check it is empty string oper = OverloadableOperator.StringLiteral; break; // TODO case for user defined literals '' default: Tokens.UnexpectedToken(); throw new ParseFailedException(); } var nameSpan = TextSpan.Covering(operatorKeyword, endOperatorSpan); var name = nameContext.Qualify(SimpleName.Special("op_" + oper)); var bodyParser = NestedParser(name); var parameters = bodyParser.ParseParameters(); var lifetimeBounds = bodyParser.ParseLifetimeBounds(); ExpressionSyntax returnType = null; if (Tokens.Accept <IRightArrowToken>()) { returnType = bodyParser.ParseExpression(); } var genericConstraints = ParseGenericConstraints(); var mayEffects = ParseMayEffects(); var noEffects = ParseNoEffects(); var(requires, ensures) = ParseFunctionContracts(); var body = bodyParser.ParseBlock(); return(new OperatorDeclarationSyntax(File, modifiers, name, nameSpan, genericParameters, parameters, lifetimeBounds, returnType, genericConstraints, mayEffects, noEffects, requires, ensures, body)); }