예제 #1
0
파일: BaZicParser.cs 프로젝트: veler/BaZic
        /// <summary>
        /// Parse the program's root context.
        /// </summary>
        /// <param name="xamlCode">The XAML code to analyze that represents the user interface.</param>
        /// <param name="resourceFilePaths">Paths to the resources files (like PNG or JPG) required for the XAML code.</param>
        /// <returns>A <see cref="BaZicProgram"/> that represents the syntax tree that corresponds to the input code.</returns>
        private BaZicProgram ParseProgram(string xamlCode, IEnumerable <string> resourceFilePaths)
        {
            var variables        = new List <VariableDeclaration>();
            var methods          = new List <MethodDeclaration>();
            var entryPointExists = false;

            var statements = ParseStatements(true, TokenType.EndCode);

            DiscardToken(TokenType.EndCode);

            foreach (var statement in statements)
            {
                switch (statement)
                {
                case VariableDeclaration variable:
                    ValidateGlobalVariableDeclarationDefaultValue(variable.DefaultValue);
                    variables.Add(variable);
                    break;

                case EntryPointMethod entryPointMethod:
                    entryPointExists = true;
                    methods.Add(entryPointMethod);
                    break;

                case MethodDeclaration method:
                    methods.Add(method);
                    break;

                default:
                    AddIssue(new BaZicParserException(L.BaZic.Parser.ForbiddenMember));
                    break;
                }
            }

            if (!entryPointExists)
            {
                methods.Add(new EntryPointMethod());
            }

            foreach (var methodInvocation in _methodInvocations)
            {
                ValidateMethodInvocation(methodInvocation);
            }

            if (_parsedXamlRoot != null || _controlAccessors.Count > 0 || _declaredEvents.Count > 0)
            {
                ValidateResources(resourceFilePaths);

                var uiProgram = new BaZicUiProgram();
                uiProgram.Xaml = xamlCode;
                uiProgram.WithControlAccessors(_controlAccessors.ToArray());
                uiProgram.WithUiEvents(_declaredEvents.ToArray());
                uiProgram.WithVariables(variables.ToArray());
                uiProgram.WithMethods(methods.ToArray());
                if (resourceFilePaths != null)
                {
                    uiProgram.WithResourceFilePaths(resourceFilePaths.ToArray());
                }

                return(uiProgram);
            }
            else
            {
                var program = new BaZicProgram();
                program.WithVariables(variables.ToArray());
                program.WithMethods(methods.ToArray());
                return(program);
            }
        }
예제 #2
0
파일: BaZicParser.cs 프로젝트: veler/BaZic
        /// <summary>
        /// Parse a BaZic code and returns a syntax tree representation of the algorithm.
        /// </summary>
        /// <param name="tokens">The BaZic code represented by tokens to analyze.</param>
        /// <param name="xamlCode">The XAML code to analyze that represents the user interface.</param>
        /// <param name="resourceFilePaths">Paths to the resources files (like PNG or JPG) required for the XAML code.</param>
        /// <param name="optimize">(optional) Defines whether the generated syntax tree must be optimized for the interpreter or not.</param>
        /// <returns>A <see cref="BaZicProgram"/> that represents the syntax tree that corresponds to the input code.</returns>
        public ParserResult Parse(List <Token> tokens, string xamlCode, IEnumerable <string> resourceFilePaths = null, bool optimize = false)
        {
            Requires.NotNull(tokens, nameof(tokens));

            _issues.Clear();
            BaZicProgram program = null;

            if (tokens.Count == 0)
            {
                return(new ParserResult(program, new AggregateException(_issues)));
            }

            ThreadHelper.RunOnStaThread(() =>
            {
                try
                {
                    _reflectionHelper = new FastReflection();

                    // Parse BaZic user interface code (XAML).
                    _parsedXamlRoot = ParseXaml(xamlCode);

                    // Parse BaZic code.
                    _catchIndicator  = 0;
                    _doLoopIndicator = 0;
                    _tokenStack.Clear();

                    for (var i = tokens.Count - 1; i >= 0; i--)
                    {
                        _tokenStack.Push(tokens[i]);
                    }

                    if (_tokenStack.Peek().TokenType != TokenType.StartCode)
                    {
                        AddIssue(new BaZicParserException(L.BaZic.Parser.FormattedBadFirstToken(TokenType.StartCode)));
                    }

                    if (_tokenStack.Count <= 2)
                    {
                        if (_parsedXamlRoot == null)
                        {
                            program = new BaZicProgram();
                        }
                        else
                        {
                            ValidateResources(resourceFilePaths);

                            var uiProgram  = new BaZicUiProgram();
                            uiProgram.Xaml = xamlCode;
                            if (resourceFilePaths != null)
                            {
                                uiProgram.WithResourceFilePaths(resourceFilePaths.ToArray());
                            }
                            program = uiProgram;
                        }
                    }
                    else
                    {
                        PreviousToken = _tokenStack.Pop();
                        CurrentToken  = _tokenStack.Pop();
                        NextToken     = _tokenStack.Pop();

                        program = ParseProgram(xamlCode, resourceFilePaths);
                    }

                    if (optimize && _issues.OfType <BaZicParserException>().Count(issue => issue.Level == BaZicParserExceptionLevel.Error) == 0)
                    {
                        var optimizer = new BaZicOptimizer();
                        program       = optimizer.Optimize(program);
                    }

                    tokens.Clear();
                }
                catch (Exception exception)
                {
                    CoreHelper.ReportException(exception);
                    _issues.Add(exception);
                }
                finally
                {
                    _expectedExpressionGroupSeparator.Clear();
                    _declaredVariables.Clear();
                    _declaredParameterDeclaration.Clear();
                    _declaredMethods.Clear();
                    _declaredEvents.Clear();
                    _controlAccessors.Clear();
                    _methodInvocations.Clear();
                    _catchIndicator  = 0;
                    _doLoopIndicator = 0;
                    if (_parsedXamlRoot != null)
                    {
                        if (_parsedXamlRoot is Window window)
                        {
                            window.Close();
                        }
                        _parsedXamlRoot = null;
                    }
                    _reflectionHelper.Dispose();
                    _reflectionHelper = null;
                }
            }, true);

            return(new ParserResult(program, new AggregateException(_issues)));
        }