Beispiel #1
0
        /// <summary>
        /// Try to parse a try catch statement.
        ///
        /// Corresponding grammar:
        ///     'TRY'
        ///         Statement_List
        ///     'CATCH'?
        ///         Statement_List
        ///     'END' 'TRY'
        /// </summary>
        /// <returns>If succeed, returns a <see cref="TryCatchStatement"/>.</returns>
        private TryCatchStatement ParseTryCatchStatement()
        {
            var tryCatchToken = CurrentToken;

            DiscardToken(TokenType.Try);
            DiscardToken(TokenType.NewLine);

            var tryStatements = ParseStatements(false, TokenType.Catch, TokenType.End);

            if (CurrentToken.TokenType == TokenType.Catch)
            {
                IncreaseCatchIndicator();
                DiscardToken(TokenType.Catch);
                DiscardToken(TokenType.NewLine);
                var catchStatements = ParseStatements(false, TokenType.End);
                DiscardToken(TokenType.End);
                DiscardToken(TokenType.Try);
                DecreaseCatchIndicator();
                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new TryCatchStatement()
                    {
                        Line = tryCatchToken.Line,
                        Column = tryCatchToken.Column,
                        StartOffset = tryCatchToken.StartOffset,
                        NodeLength = tryCatchToken.ParsedLength
                    }
                           .WithTryBody(tryStatements)
                           .WithCatchBody(catchStatements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
            else
            {
                DiscardToken(TokenType.End);
                DiscardToken(TokenType.Try);
                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new TryCatchStatement()
                    {
                        Line = tryCatchToken.Line,
                        Column = tryCatchToken.Column,
                        StartOffset = tryCatchToken.StartOffset,
                        NodeLength = tryCatchToken.ParsedLength
                    }
                           .WithTryBody(tryStatements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Try to parse a method delcaration statement.
        ///
        /// Corresponding grammar :
        ///     'EXTERN'? ('ASYNC' | 'EVENT')? 'FUNCTION' Identifier '(' Parameter_List ')'
        ///         Statement_List
        ///     'END' 'FUNCTION'
        /// </summary>
        /// <returns>If succeed, returns a <see cref="VariableDeclaration"/>.</returns>
        private MethodDeclaration ParseMethodDeclaration()
        {
            var isAsync  = false;
            var isEvent  = false;
            var isExtern = false;

            if (CurrentToken.TokenType == TokenType.Extern)
            {
                isExtern = true;
                DiscardToken();
            }

            if (CurrentToken.TokenType == TokenType.Async)
            {
                if (NextToken.TokenType == TokenType.Event)
                {
                    AddIssue(new BaZicParserException(NextToken.Line, NextToken.Column, NextToken.StartOffset, NextToken.ParsedLength, L.BaZic.Parser.Statements.AsyncEvent));
                }

                isAsync = true;
                DiscardToken();
            }
            else if (CurrentToken.TokenType == TokenType.Event)
            {
                if (NextToken.TokenType == TokenType.Async)
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.AsyncEvent));
                }

                isEvent = true;
                DiscardToken();
            }

            DiscardToken(TokenType.Function);

            var identifierToken = CurrentToken;
            var methodName      = CurrentToken.Value;

            TokenIdentificationHelper.CheckIdentifier(methodName, CurrentToken, isEvent, _issues);
            DiscardToken();

            DiscardToken(TokenType.LeftParenth);
            var methodParameters = ParseParameterList();

            DiscardToken(TokenType.RightParenth);

            if (!TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
            {
                AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
            }

            if (isEvent && methodParameters.Length != 0)
            {
                AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.EventNoParameter));
            }

            while (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
            {
                DiscardToken();
            }

            var statements = ParseStatements(false, TokenType.End);

            DiscardToken(TokenType.End);
            DiscardToken(TokenType.Function);
            var endToken = PreviousToken;

            if (TokenIdentificationHelper.IsStatementSeparator(CurrentToken))
            {
                DiscardToken();
            }
            else
            {
                AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
            }

            if (string.Compare(methodName, Consts.EntryPointMethodName, StringComparison.Ordinal) == 0) // The name is case sensitive.
            {
                if (!isExtern)
                {
                    AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.ExternEntryPoint));
                }
                if (isAsync)
                {
                    AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.AsyncEntryPoint));
                }
                if (isEvent)
                {
                    AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.EventEntryPoint));
                }

                if (methodParameters.Length != 1)
                {
                    AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.UniqueArgumentEntryPoint));
                }
                else if (!methodParameters.Single().IsArray)
                {
                    AddIssue(new BaZicParserException(identifierToken.Line, identifierToken.Column, identifierToken.StartOffset, identifierToken.ParsedLength, L.BaZic.Parser.Statements.EntryPointArgumentArrayExpected));
                }

                var entryPointDeclaration = new EntryPointMethod()
                {
                    Line        = identifierToken.Line,
                    Column      = identifierToken.Column,
                    StartOffset = identifierToken.StartOffset,
                    NodeLength  = identifierToken.ParsedLength,
                    EndOffset   = endToken.StartOffset + endToken.ParsedLength
                }
                .WithParameters(methodParameters);

                AddMethod(entryPointDeclaration, false);

                return(entryPointDeclaration.WithBody(statements));
            }

            var methodDeclaration = new MethodDeclaration(methodName, isAsync, isExtern)
            {
                Line        = identifierToken.Line,
                Column      = identifierToken.Column,
                StartOffset = identifierToken.StartOffset,
                NodeLength  = identifierToken.ParsedLength,
                EndOffset   = endToken.StartOffset + endToken.ParsedLength
            }
            .WithParameters(methodParameters);

            AddMethod(methodDeclaration, isEvent);

            return(methodDeclaration.WithBody(statements));
        }
Beispiel #3
0
        /// <summary>
        /// Try to parse a condition statement.
        ///
        /// Corresponding grammar:
        ///     'IF' Expression 'THEN'
        ///         Statement_List
        ///     'ELSE'?
        ///         Statement_List
        ///     'END' 'IF'
        /// </summary>
        /// <returns>If succeed, returns a <see cref="ConditionStatement"/>.</returns>
        private ConditionStatement ParseConditionStatement()
        {
            var ifToken = CurrentToken;

            DiscardToken(TokenType.If);
            var conditionExpression = ParseExpression(true, TokenType.Then);

            DiscardToken(TokenType.Then);
            DiscardToken(TokenType.NewLine);

            var trueStatements = ParseStatements(false, TokenType.Else, TokenType.End);

            if (CurrentToken.TokenType == TokenType.Else)
            {
                DiscardToken(TokenType.Else);
                DiscardToken(TokenType.NewLine);
                var falseStatements = ParseStatements(false, TokenType.End);
                DiscardToken(TokenType.End);
                DiscardToken(TokenType.If);
                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new ConditionStatement(conditionExpression)
                    {
                        Line = ifToken.Line,
                        Column = ifToken.Column,
                        StartOffset = ifToken.StartOffset,
                        NodeLength = ifToken.ParsedLength
                    }
                           .WithThenBody(trueStatements)
                           .WithElseBody(falseStatements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
            else
            {
                DiscardToken(TokenType.End);
                DiscardToken(TokenType.If);
                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new ConditionStatement(conditionExpression)
                    {
                        Line = ifToken.Line,
                        Column = ifToken.Column,
                        StartOffset = ifToken.StartOffset,
                        NodeLength = ifToken.ParsedLength
                    }
                           .WithThenBody(trueStatements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Try to parse a loop iteration statement.
        ///
        /// Corresponding grammar:
        ///     'DO' ('WHILE' Expression)?
        ///         Statement_List
        ///     'LOOP' ('WHILE' Expression)?
        /// </summary>
        /// <returns>If succeed, returns a <see cref="IterationStatement"/>.</returns>
        private IterationStatement ParseLoopStatement()
        {
            var doToken = CurrentToken;

            DiscardToken(TokenType.Do);

            if (CurrentToken.TokenType == TokenType.While)
            {
                // DO WHILE () ... LOOP
                DiscardToken(TokenType.While);

                var conditionExpression = ParseExpression(true, TokenIdentificationHelper.GetStatementSeparatorsTokens());

                DiscardToken(TokenType.NewLine);
                IncreaseDoLoopIndicator();
                var statements = ParseStatements(false, TokenType.Loop);
                DecreaseDoLoopIndicator();

                DiscardToken(TokenType.Loop);

                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new IterationStatement(conditionExpression, false)
                    {
                        Line = doToken.Line,
                        Column = doToken.Column,
                        StartOffset = doToken.StartOffset,
                        NodeLength = doToken.ParsedLength
                    }
                           .WithBody(statements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
            else
            {
                // DO ... LOOP WHILE
                DiscardToken(TokenType.NewLine);
                IncreaseDoLoopIndicator();
                var statements = ParseStatements(false, TokenType.Loop);
                DecreaseDoLoopIndicator();

                DiscardToken(TokenType.Loop);
                DiscardToken(TokenType.While);

                var conditionExpression = ParseExpression(true, TokenIdentificationHelper.GetStatementSeparatorsTokens());

                if (TokenIdentificationHelper.IsStatementSeparatorButNotEndCode(CurrentToken))
                {
                    DiscardToken();
                    return(new IterationStatement(conditionExpression, true)
                    {
                        Line = doToken.Line,
                        Column = doToken.Column,
                        StartOffset = doToken.StartOffset,
                        NodeLength = doToken.ParsedLength
                    }
                           .WithBody(statements));
                }
                else
                {
                    AddIssue(new BaZicParserException(CurrentToken.Line, CurrentToken.Column, CurrentToken.StartOffset, CurrentToken.ParsedLength, L.BaZic.Parser.Statements.LineExpected));
                    return(null);
                }
            }
        }