예제 #1
0
        /// <summary>
        /// Generates a BaZic code with UI from a syntax tree.
        /// </summary>
        /// <param name="syntaxTree">The syntax tree that represents the algorithm</param>
        /// <returns>A BaZic code</returns>
        public string Generate(BaZicUiProgram syntaxTree)
        {
            _indentSpaceCount = 0;

            var globalVariables = new List <string>();

            foreach (var variable in syntaxTree.GlobalVariables)
            {
                globalVariables.Add(GenerateVariableDeclaration(variable));
            }

            var globalVariablesString = string.Join(Environment.NewLine, globalVariables);

            if (!string.IsNullOrWhiteSpace(globalVariablesString))
            {
                globalVariablesString += Environment.NewLine + Environment.NewLine;
            }

            var methods = new List <string>();

            foreach (var method in syntaxTree.Methods)
            {
                methods.Add(GenerateMethodDeclaration(method, syntaxTree.UiEvents.SingleOrDefault(e => e.MethodId == method.Id)));
            }

            var methodsString = string.Join(Environment.NewLine + Environment.NewLine, methods);

            return($"# BaZic code generated automatically" + Environment.NewLine + Environment.NewLine +
                   $"{globalVariablesString}" +
                   $"{methodsString}");
        }
예제 #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ProgramInterpreter"/> class.
 /// </summary>
 /// <param name="baZicInterpreter">The main interpreter.</param>
 /// <param name="program">The <see cref="BaZicProgram"/> to interpret.</param>
 /// <param name="executionFlowId">A GUID that defines in which callstack is linked.</param>
 internal ProgramInterpreter(BaZicInterpreterCore baZicInterpreter, BaZicProgram program, Guid executionFlowId)
     : base(baZicInterpreter, null, executionFlowId)
 {
     Requires.NotNull(program, nameof(program));
     _program   = program;
     _uiProgram = program as BaZicUiProgram;
 }
예제 #3
0
        public void BaZicCodeGeneratorUi()
        {
            var program = new BaZicUiProgram()
                          .WithControlAccessors(new ControlAccessorDeclaration("Button1"))
                          .WithVariables(
                new VariableDeclaration("Foo")
                ).WithMethods(
                new EntryPointMethod()
                .WithBody(
                    new VariableDeclaration("Bar", true),
                    new IterationStatement(new BinaryOperatorExpression(new VariableReferenceExpression("Foo"), BinaryOperatorType.Equality, new VariableReferenceExpression("Bar")))
                    .WithBody(
                        new ConditionStatement(new PrimitiveExpression(true))
                        .WithThenBody(
                            new CommentStatement("If true")
                            ).WithElseBody(
                            new CommentStatement("If not true")
                            )
                        )
                    )
                );

            var code = new BaZicCodeGenerator().Generate(program);

            var expected =
                @"# BaZic code generated automatically

VARIABLE Foo

EXTERN FUNCTION Main(args[])
    VARIABLE Bar[]
    DO WHILE Foo = Bar
        IF TRUE THEN
            # If true
        ELSE
            # If not true
        END IF
    LOOP
END FUNCTION";

            Assert.AreEqual(expected, code);
        }
예제 #4
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);
            }
        }
예제 #5
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)));
        }