/// <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); } }
/// <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))); }