Пример #1
0
        private static IStatement ParseStatement(Context context, ParserState state)
        {
            IStatement statement;

            if (_parseRules.TryGetValue(state.Current().Kind, out var parseRule))
            {
                state.Advance();
                statement = parseRule.ParserFunction.Invoke(context, state);
                if (parseRule.EndsWithSemicolon)
                {
                    state.ConsumeOrError(TokenKind.Semicolon);
                }
                ConsumeUnnecessarySemicolons(context, state);
                return(statement);
            }

            var nodeId     = state.NodeIdGenerator.GetNextId();
            var expression = ExpressionParser.ParseExpression(state);

            if (state.Consume(TokenKind.ColonEqual))
            {
                var value = ExpressionParser.ParseExpression(state);
                var span  = SourceSpan.Merge(expression.Span, value.Span);
                statement = new AssignmentStatement(nodeId, span, expression, value);
            }
            else
            {
                statement = new ExpressionStatement(nodeId, expression.Span, expression);
            }

            state.ConsumeOrError(TokenKind.Semicolon);
            ConsumeUnnecessarySemicolons(context, state);
            return(statement);
        }
Пример #2
0
        private static List <Spanned <FunctionParameter> > ParseFunctionParameters(
            Context context,
            ParserState state)
        {
            var parameters = new List <Spanned <FunctionParameter> >();

            state.ConsumeOrError(TokenKind.LeftParenthesis);
            if (state.Consume(TokenKind.RightParenthesis))
            {
                return(parameters);
            }

            do
            {
                var identifier = state.ConsumeOrError(TokenKind.Identifier);
                state.ConsumeOrError(TokenKind.Colon);
                var typeSignature = TypeSignatureParser.ParseTypeSignature(state);
                var span          = SourceSpan.Merge(identifier.Span, typeSignature.Span);
                parameters.Add(
                    new Spanned <FunctionParameter>(
                        new FunctionParameter(
                            state.NodeIdGenerator.GetNextId(),
                            identifier,
                            typeSignature),
                        span));
            } while (!state.IsAtEnd() && state.Consume(TokenKind.Comma));

            state.ConsumeOrError(TokenKind.RightParenthesis);

            return(parameters);
        }
Пример #3
0
        private static IExpression ParseArrayLiteral(ParserState state)
        {
            var        nodeId = state.NodeIdGenerator.GetNextId();
            SourceSpan span;

            var spanStart = state.Previous().Span;
            var elements  = new List <IExpression>();

            if (state.Consume(TokenKind.RightBracket))
            {
                throw new ParseException(
                          state.Previous().Span,
                          "empty array literals are not allowed");
            }

            do
            {
                elements.Add(ParseExpression(state));
            } while (state.Consume(TokenKind.Comma));

            state.ConsumeOrError(TokenKind.RightBracket);

            var spanEnd = state.Previous().Span;

            span = SourceSpan.Merge(spanStart, spanEnd);
            return(new ArrayLiteral(nodeId, span, elements));
        }
Пример #4
0
 public InfixOperation(
     int nodeId,
     Token @operator,
     IExpression leftOperand,
     IExpression rightOperand)
 {
     NodeId   = nodeId;
     Span     = SourceSpan.Merge(leftOperand.Span, rightOperand.Span);
     Operator = new Spanned <InfixOperator>(
         @operator.Kind switch
     {
         TokenKind.Ampersand => InfixOperator.BinaryAnd,
         TokenKind.AmpersandAmpersand => InfixOperator.LogicalAnd,
         TokenKind.Asterisk => InfixOperator.Multiply,
         TokenKind.Caret => InfixOperator.BinaryXor,
         TokenKind.Equal => InfixOperator.Equal,
         TokenKind.EqualEqual => InfixOperator.Equal,
         TokenKind.Greater => InfixOperator.Greater,
         TokenKind.GreaterEqual => InfixOperator.GreaterOrEqual,
         TokenKind.GreaterGreater => InfixOperator.ShiftRight,
         TokenKind.Less => InfixOperator.Less,
         TokenKind.LessEqual => InfixOperator.LessOrEqual,
         TokenKind.LessGreater => InfixOperator.NotEqual,
         TokenKind.LessLess => InfixOperator.ShiftLeft,
         TokenKind.Minus => InfixOperator.Subtract,
         TokenKind.Percent => InfixOperator.Modulo,
         TokenKind.Pipe => InfixOperator.BinaryOr,
         TokenKind.PipePipe => InfixOperator.LogicalOr,
         TokenKind.Plus => InfixOperator.Add,
         TokenKind.Slash => InfixOperator.Divide,
         _ => throw new ArgumentException(
             $"Cannot create an infix operator from a token {@operator.Kind}"),
     },
Пример #5
0
 public Block(Token openingBrace, Token closingBrace, List <IStatement> statements)
 {
     Span         = SourceSpan.Merge(openingBrace.Span, closingBrace.Span);
     OpeningBrace = openingBrace;
     ClosingBrace = closingBrace;
     Statements   = statements;
 }
Пример #6
0
        private static ITypeSignature ParsePointerSignature(ParserState state)
        {
            var spanStart      = state.Previous().Span;
            var underlyingType = ParseTypeSignature(state);
            var span           = SourceSpan.Merge(spanStart, underlyingType.Span);

            return(new PointerSignature(span, underlyingType));
        }
Пример #7
0
        private static IExpression ParseDereferenceExpression(ParserState state)
        {
            var startSpan  = state.Previous().Span;
            var expression = ParsePrefixOperation(state);
            var nodeId     = state.NodeIdGenerator.GetNextId();
            var span       = SourceSpan.Merge(startSpan, expression.Span);

            return(new Dereference(nodeId, span, expression));
        }
Пример #8
0
        private static IStatement ParseWhileStatement(Context context, ParserState state)
        {
            var startSpan = state.Previous().Span;
            var condition = ExpressionParser.ParseExpression(state);
            var body      = ParseBlock(context, state);
            var nodeId    = state.NodeIdGenerator.GetNextId();
            var span      = SourceSpan.Merge(startSpan, body.Span);

            return(new WhileStatement(nodeId, span, condition, body));
        }
Пример #9
0
        private static IExpression ParseSubscriptOperator(ParserState state, IExpression operand)
        {
            var index = ParseExpression(state);

            state.ConsumeOrError(TokenKind.RightBracket);
            var nodeId = state.NodeIdGenerator.GetNextId();
            var span   = SourceSpan.Merge(operand.Span, state.Previous().Span);

            return(new SubscriptExpression(nodeId, span, operand, index));
        }
Пример #10
0
        private static IExpression ParseParenthesizedExpression(ParserState state)
        {
            var startSpan  = state.Previous().Span;
            var expression = ParseExpression(state);

            state.ConsumeOrError(TokenKind.RightParenthesis);
            var endSpan = state.Previous().Span;

            return(new ParenthesizedExpression(
                       state.NodeIdGenerator.GetNextId(),
                       SourceSpan.Merge(startSpan, endSpan),
                       expression));
        }
Пример #11
0
 public PrefixOperation(int nodeId, Token @operator, IExpression operand)
 {
     NodeId   = nodeId;
     Span     = SourceSpan.Merge(@operator.Span, operand.Span);
     Operator = new Spanned <PrefixOperator>(
         @operator.Kind switch
     {
         TokenKind.Bang => PrefixOperator.Not,
         TokenKind.Plus => PrefixOperator.Identity,
         TokenKind.Minus => PrefixOperator.Negate,
         TokenKind.Tilde => PrefixOperator.BinaryNot,
         _ => throw new ArgumentException(nameof(@operator)),
     },
Пример #12
0
        private static IStatement ParseReturnStatement(Context context, ParserState state)
        {
            var startSpan = state.Previous().Span;

            if (state.Current().Kind == TokenKind.Semicolon)
            {
                return(new ReturnStatement(state.NodeIdGenerator.GetNextId(), startSpan, null));
            }
            var expression = ExpressionParser.ParseExpression(state);
            var endSpan    = state.Previous().Span;
            var span       = SourceSpan.Merge(startSpan, endSpan);

            return(new ReturnStatement(state.NodeIdGenerator.GetNextId(), span, expression));
        }
Пример #13
0
        private static IStatement ParseAssertStatement(Context context, ParserState state)
        {
            var startSpan = state.Previous().Span;

            state.ConsumeOrError(TokenKind.LeftParenthesis);
            var condition = ExpressionParser.ParseExpression(state);

            state.ConsumeOrError(TokenKind.RightParenthesis);
            var endSpan = state.Previous().Span;

            return(new AssertStatement(
                       state.NodeIdGenerator.GetNextId(),
                       SourceSpan.Merge(startSpan, endSpan),
                       condition));
        }
Пример #14
0
        private static IStatement ParseIfStatement(Context context, ParserState state)
        {
            var startSpan = state.Previous().Span;
            var condition = ExpressionParser.ParseExpression(state);
            var thenBlock = ParseBlock(context, state);
            var elifs     = ParseElifs(context, state);
            var elseBlock = state.Consume(TokenKind.Else) ? ParseBlock(context, state) : null;

            return(new IfStatement(
                       state.NodeIdGenerator.GetNextId(),
                       SourceSpan.Merge(startSpan, elseBlock != null ? elseBlock.Span : thenBlock.Span),
                       condition,
                       thenBlock,
                       elifs,
                       elseBlock));
        }
Пример #15
0
 private static void ConsumeUnnecessarySemicolons(Context context, ParserState state)
 {
     while (!state.IsAtEnd() && state.Consume(TokenKind.Semicolon))
     {
         var firstSemicolon = state.Previous();
         var lastSemicolon  = firstSemicolon;
         while (state.Consume(TokenKind.Semicolon))
         {
             lastSemicolon = state.Previous();
         }
         var semicolonsSpan = SourceSpan.Merge(firstSemicolon.Span, lastSemicolon.Span);
         var message        = firstSemicolon.Span.Start == lastSemicolon.Span.Start
             ? "unnecessary trailing semicolon"
             : "unnecessary trailing semicolons";
         context.Warning(semicolonsSpan, message);
     }
 }
Пример #16
0
        private static IStatement ParseFunctionDefinition(Context context, ParserState state)
        {
            var startSpan           = state.Previous().Span;
            var identifier          = state.ConsumeOrError(TokenKind.Identifier);
            var parameters          = ParseFunctionParameters(context, state);
            var returnTypeSignature = state.Consume(TokenKind.Colon)
                ? TypeSignatureParser.ParseTypeSignature(state)
                : null;
            var body    = ParseBlock(context, state);
            var endSpan = state.Previous().Span;
            var span    = SourceSpan.Merge(startSpan, endSpan);

            return(new FunctionDefinition(
                       state.NodeIdGenerator.GetNextId(),
                       span,
                       identifier,
                       parameters,
                       body,
                       returnTypeSignature));
        }
Пример #17
0
        private static ITypeSignature ParseArraySignature(ParserState state)
        {
            var spanStart      = state.Previous().Span;
            var underlyingType = ParseTypeSignature(state);

            state.ConsumeOrError(TokenKind.Semicolon);
            var length = int.Parse(state.ConsumeOrError(TokenKind.Integer).Lexeme);

            if (length <= 0)
            {
                throw new ParseException(
                          state.Previous().Span,
                          "array length must be a positive integer");
            }

            state.ConsumeOrError(TokenKind.RightBracket);
            var spanEnd = state.Previous().Span;
            var span    = SourceSpan.Merge(spanStart, spanEnd);

            return(new ArraySignature(span, underlyingType, length));
        }
Пример #18
0
        private static IStatement ParseVariableDefinition(Context context, ParserState state)
        {
            var startSpan     = state.Previous().Span;
            var identifier    = state.ConsumeOrError(TokenKind.Identifier);
            var typeSignature = state.Consume(TokenKind.Colon)
                ? TypeSignatureParser.ParseTypeSignature(state)
                : null;

            SourceSpan endSpan;
            SourceSpan span;

            if (state.Consume(TokenKind.Equal))
            {
                var initializer = ExpressionParser.ParseExpression(state);
                endSpan = state.Previous().Span;
                span    = SourceSpan.Merge(startSpan, endSpan);
                return(new VariableDefinition(
                           state.NodeIdGenerator.GetNextId(),
                           span,
                           identifier,
                           typeSignature,
                           initializer));
            }

            if (typeSignature == null)
            {
                throw new ParseException(identifier.Span, "type signature needed");
            }

            endSpan = state.Previous().Span;
            span    = SourceSpan.Merge(startSpan, endSpan);
            return(new VariableDefinition(
                       state.NodeIdGenerator.GetNextId(),
                       span,
                       identifier,
                       typeSignature,
                       null));
        }
Пример #19
0
        private static IExpression ParseFunctionCall(ParserState state, IExpression callee)
        {
            var arguments = new List <IExpression>();

            if (state.Consume(TokenKind.RightParenthesis))
            {
                return(new FunctionCall(
                           state.NodeIdGenerator.GetNextId(),
                           SourceSpan.Merge(callee.Span, state.Previous().Span),
                           callee,
                           arguments));
            }

            do
            {
                arguments.Add(ParseExpression(state));
            } while (!state.IsAtEnd() && state.Consume(TokenKind.Comma));

            state.ConsumeOrError(TokenKind.RightParenthesis);
            var span = SourceSpan.Merge(callee.Span, state.Previous().Span);

            return(new FunctionCall(state.NodeIdGenerator.GetNextId(), span, callee, arguments));
        }