Exemple #1
0
        private IEnumerable <string> AddOrUpdateStat(Node node, ParsingContext context, string sectionId, bool isUpdate)
        {
            var errors = ParseStat(node, context, sectionId, out var stat);

            if (!errors.Any())
            {
                if (isUpdate)
                {
                    errors = errors.Concat(_statService.AddOrUpdate(stat).FormatErrors(node));
                }
                else
                {
                    errors = errors.Concat(_statService.Add(stat).FormatErrors(node));
                }
            }
            if (!errors.Any())
            {
                if (!isUpdate || !_sections[sectionId].Stats.Contains(stat))
                {
                    _sections[sectionId].Stats.Add(stat !);
                }
                else
                {
                    _sections[sectionId].Stats[_sections[sectionId].Stats.IndexOf(stat)] = stat !;
                }
            }

            return(errors);
        }
Exemple #2
0
        private IEnumerable <string> AddOrUpdateSection(Node node, ParsingContext context, string?parentSectionId, bool isAnUpdate)
        {
            var errors = new List <string>();

            if (!isAnUpdate && _sections.ContainsKey(node.Value))
            {
                //TODO continue after error
                errors.Add(node, $"section already exists: {node.Value}");

                return(errors);
            }

            if (!isAnUpdate || !_sections.ContainsKey(node.Value))
            {
                if (parentSectionId == null)
                {
                    _sections[node.Value] = new Section(node.Value);
                }
                else
                {
                    _sections[node.Value] = new Section(node.Value, _sections[parentSectionId].Default);
                }
            }

            foreach (var child in node.Children)
            {
                if (child.IsFunction())
                {
                    errors = errors.Concat(AddOrUpdateFunction(child, context, isAnUpdate)).ToList();
                }
                else if (child.IsSection())
                {
                    errors = errors.Concat(AddOrUpdateSection(child, context, node.Value, isAnUpdate)).ToList();
                }
                else if (child.Value.IsEquivalentTo("_default"))
                {
                    errors = errors.Concat(SetDefault(child, context, node.Value)).ToList();
                }
                else if (child.IsStat())
                {
                    errors = errors.Concat(AddOrUpdateStat(child, context, node.Value, isAnUpdate)).ToList();
                }
                else if (child.IsVariable())
                {
                    errors = errors.Concat(SetVariable(child, context)).ToList();
                }
                else
                {
                    errors.Add(child, $"expected a valid function, stat or section id but found '{child.Value}'");
                    return(errors);
                }

                if (errors.Any())
                {
                    return(errors);
                }
            }

            return(errors);
        }
Exemple #3
0
        private IEnumerable <string> SetDefault(Node node, ParsingContext context, string sectionId)
        {
            var errors = ParseStat(node, context, sectionId, out var stat).ToList();

            if (errors.Any())
            {
                return(errors);
            }

            _sections[sectionId].Default = stat !;            //TODO gerer par path => sect1#A != sect2#A

            return(errors);
        }
Exemple #4
0
        //TODO static? / DI
        public IEnumerable <string> Populate(Node node, bool isAnUpdate)
        {
            var errors  = new List <string>();
            var context = new ParsingContext(_statService, _functionService);

            if (!node.Children.Any())
            {
                return new[] { "empty book" }
            }
            ;

            errors = errors.Concat(AddOrUpdateSection(node, context, null, isAnUpdate)).ToList();

            return(errors);
        }
Exemple #5
0
        private IEnumerable <string> SetVariable(Node node, ParsingContext context)
        {
            if (node.Value[0] == '.')
            {
                return new[] { $"Can not use shorthand variable name ({node.Value})" }
            }
            ;                                                                                           //TODO better msg

            var variableId             = new VariableId(node.Value);
            var variableExpressionNode = node.Children.First();

            var errors = _parser.Parse(out var expression, variableExpressionNode.Value, context).FormatErrors(variableExpressionNode).ToList();

            if (errors.Any())
            {
                return(errors);
            }

            _statService.Get(variableId.StatId).AddOrUpdateVariable(variableId, expression !);

            return(Enumerable.Empty <string>());
        }
Exemple #6
0
        private IEnumerable <string> AddOrUpdateFunction(Node node, ParsingContext context, bool isUpdate)
        {
            var errors = new List <string>();

            context.FunctionId = new FunctionId(node.Value);

            if (node.Type == NodeType.PropertyIdentifier)
            {
                var expressionNode = node.Children.First();
                errors = _parser.Parse(out var expression, expressionNode.Value, context).FormatErrors(expressionNode).ToList();
                if (errors.Any())
                {
                    return(errors);
                }

                if (!isUpdate)
                {
                    errors = errors.Concat(_functionService.Add(new UserFunction(context.FunctionId, expression !)).FormatErrors(node))
                             .FormatErrors(expressionNode)
                             .ToList();
                }
                else
                {
                    errors = errors.Concat(_functionService.AddOrUpdate(new UserFunction(context.FunctionId, expression !)).FormatErrors(node))
                             .FormatErrors(expressionNode)
                             .ToList();
                }
            }
            else
            {
                errors.Add(node, "no");                 //TODO
            }

            context.FunctionId = null;

            return(errors);
        }
Exemple #7
0
 public static bool IsValue(this Node node)
 => node.IsNumber() ||
 node.Type == NodeType.String;
Exemple #8
0
 public static bool IsNumber(this Node node)
 => node.Type == NodeType.Integer ||
 node.Type == NodeType.Float;
Exemple #9
0
 public static bool IsSection(this Node node)
 => node.Type == NodeType.ObjectIdentifier &&
 node.Value.IsValidSectionId();
Exemple #10
0
 public static bool IsFunction(this Node node)
 => node.Value.IsValidFunctionId();
Exemple #11
0
 public static bool IsVariable(this Node node)
 => node.Value.IsValidVariableId() &&
 node.Type == NodeType.PropertyIdentifier;
Exemple #12
0
 public static bool IsStat(this Node node)
 => node.Value.IsValidStatId() &&
 (node.Type == NodeType.PropertyIdentifier ||
  node.Type == NodeType.ObjectIdentifier);
Exemple #13
0
 public static IEnumerable <string> FormatErrors(this IEnumerable <string> errors, Node node)
 {
     //TODO file name
     //TODO more precise line number / position
     return(errors.Select(e => $"error: {node.LineNumber}:{node.LinePosition} {e}"));
 }
Exemple #14
0
 public static void Add(this IList <string> errors, Node node, string error)
 {
     //TODO file name
     errors.Add($"error: {node.LineNumber}:{node.LinePosition} {error}");
 }
Exemple #15
0
        private IEnumerable <string> ParseStat(Node statNode, ParsingContext context, string sectionId, out Stat stat)
        {
            var errors = new List <string>();

            context.StatId = new StatId(statNode.Value);
            stat           = new Stat(_sections[sectionId].Default, context.StatId);

            if (statNode.Type == NodeType.PropertyIdentifier)
            {
                var statExpressionNode = statNode.Children.First();
                errors = _parser.Parse(out var expression, statExpressionNode.Value, context).FormatErrors(statExpressionNode).ToList();
                if (errors.Any())
                {
                    return(errors);
                }

                //TODO AddOrUpdate
                return(errors.Concat(stat.AddOrUpdateExpression(expression !, sectionId + '_' + stat.Id)).FormatErrors(statExpressionNode));
            }
            else if (statNode.Type == NodeType.ObjectIdentifier)
            {
                foreach (var expressionId in statNode.Children)
                {
                    if (expressionId.Value.StartsWith('.'))
                    {
                        if (!expressionId.Value.IsValidVariableId())
                        {
                            errors.Add(expressionId, $"{expressionId.Value} looks like a variable declaration (starts with '.') but is not a valid variable id");
                            continue;
                        }

                        if (expressionId.Type != NodeType.PropertyIdentifier)
                        {
                            errors.Add(expressionId, $"{expressionId.Value} looks like a variable declaration (starts with '.') but is followed by '{{'");
                            continue;
                        }

                        var expressionNode = expressionId.Children.First();
                        var parseErrors    = _parser.Parse(out var expression, expressionNode.Value, context).FormatErrors(expressionNode).ToList();
                        if (parseErrors.Any())
                        {
                            return(errors.Concat(parseErrors));
                        }

                        stat.AddOrUpdateVariable(new VariableId(expressionId.Value, stat.Id), expression !);
                    }
                    else if (expressionId.Type == NodeType.PropertyIdentifier)
                    {
                        //TODO check name validity

                        var expressionValueNode = expressionId.Children.First();

                        var exprErrors = _parser.Parse(out var expression, expressionValueNode.Value, context).FormatErrors(expressionValueNode);
                        errors = errors.Concat(exprErrors).ToList();
                        if (exprErrors.Any())
                        {
                            continue;
                        }
                        exprErrors = stat.AddOrUpdateExpression(expression !, expressionId.Value).FormatErrors(expressionValueNode);
                        //TODO AddOrUpdate
                        errors = errors.Concat(exprErrors).ToList();
                    }
                    else if (expressionId.Type == NodeType.ObjectIdentifier)
                    {
                        //TODO handle duplicates

                        var position     = -1;
                        var positionNode = expressionId.Children.FirstOrDefault(c => c.Value.IsEquivalentTo("position"));
                        if (positionNode != null)
                        {
                            var positionValueNode = positionNode.Children.First();
                            if (positionValueNode.Type != NodeType.Integer)
                            {
                                //TODO stat path
                                errors.Add(positionNode.Children.First(), $"expected position to be an integer but found {positionNode.Value}");
                            }

                            position = int.Parse(positionValueNode.Value);
                        }

                        var extraNodes = expressionId.Children.Where(c => !c.Value.IsEquivalentTo("expression") &&
                                                                     !c.Value.IsEquivalentTo("position"));
                        if (extraNodes.Any())
                        {
                            // TODO add stat.expression path to error
                            errors.Add(expressionId, $"unknown properties ({string.Join(',', $"'{string.Join("", extraNodes.Select(n => n.Value))}'")}) will be ignored. Allowed properties are 'expression' and 'position'. Did you forget an '#' at the start of a parent section name?");
                        }

                        // TODO rename to 'value'
                        var valueIdNode = expressionId.Children.FirstOrDefault(c => c.Value.IsEquivalentTo("expression"));
                        if (valueIdNode == null)
                        {
                            errors.Add(expressionId, $"expression {expressionId} of stat {statNode.Value} should have an \"expression\" property");
                            continue;
                        }
                        if (valueIdNode.Type != NodeType.PropertyIdentifier)
                        {
                            errors.Add(valueIdNode, $"TODO value type error");                             //TODO
                            continue;
                        }

                        var valueNode = valueIdNode.Children.First();
                        if (!valueNode.IsValue())
                        {
                            errors.Add(valueIdNode.Children.First(), $"TODO value error");
                            continue;
                        }

                        var valueErrors = _parser.Parse(out var expression, valueNode.Value, context).FormatErrors(valueNode);
                        errors = errors.Concat(valueErrors).ToList();
                        if (valueErrors.Any())
                        {
                            continue;
                        }
                        valueErrors = stat.AddOrUpdateExpression(expression !, expressionId.Value, position).FormatErrors(valueNode);
                        errors      = errors.Concat(valueErrors).ToList();
                    }
                    else
                    {
                        //TODO this should never happen??
                        errors.Add(expressionId, "expected expression string or expression object");
                        return(errors);                        // TODO continue on error
                    }
                }
            }
            else
            {
                // TODO this should never happen
                errors.Add(statNode, "expected expression string or expression object");
                return(errors);
            }

            return(errors);
        }