Esempio n. 1
0
        private BlockNode ParseNestedControl(YamlToken p)
        {
            if (p.Kind != YamlTokenKind.StartObj)
            {
                _errorContainer.ParseError(p.Span, $"Unexpected token {p}");
                throw new DocumentException();
            }

            var controlDef = ParseControlDef(p);

            var block = new BlockNode
            {
                Name = controlDef
            };

            while (true)
            {
                p = _yaml.ReadNext();
                switch (p.Kind)
                {
                case YamlTokenKind.EndObj:
                    return(block);

                case YamlTokenKind.Property:
                    block.Properties.Add(new PropertyNode
                    {
                        Identifier = CharacterUtils.UnEscapeName(p.Property, _errorContainer),
                        Expression = new ExpressionNode
                        {
                            Expression = p.Value
                        }
                    });
                    break;

                // StartObj can either be a Control or Function def
                case YamlTokenKind.StartObj:
                    if (IsControlStart(p.Property))
                    {
                        var childNode = ParseNestedControl(p);
                        if (_errorContainer.HasErrors)
                        {
                            return(null);
                        }
                        block.Children.Add(childNode);
                    }
                    else
                    {
                        var functionNode = ParseFunctionDef(p);
                        if (_errorContainer.HasErrors)
                        {
                            return(null);
                        }
                        block.Functions.Add(functionNode);
                    }
                    break;

                case YamlTokenKind.Error:
                    _errorContainer.ParseError(p.Span, p.Value);
                    return(null);

                default:
                    _errorContainer.ParseError(p.Span, $"Unexpected yaml token: {p}");
                    throw new DocumentException();
                }
            }
        }
Esempio n. 2
0
        // Name ( Parameter-Name As Data-type [ , Parameter-Name As Data-type ... ] ) :  (ThisProperty or Parameter-Name) :   Metadata-Name : Metadata-Value   ...  ...
        // Currently iterating on what fields are present in the property metadata blocks
        // Right now, only Default is permitted
        private FunctionNode ParseFunctionDef(YamlToken p)
        {
            // Validation here mirrors validation in PA-Client
            var paramRegex    = new Regex(@"^([\p{L}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]+?)\s+As\s+([\p{L}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]+)");
            var funcNameRegex = new Regex(@"^([\p{L}\p{Nd}\p{Mn}\p{Mc}\p{Pc}\p{Cf}]+?)\(");
            var line          = p.Property;
            var m             = funcNameRegex.Match(line);

            if (!m.Success)
            {
                _errorContainer.ParseError(p.Span, $"Can't parse Function definition");
                throw new DocumentException();
            }

            var funcName     = m.Groups[1].Value;
            var functionNode = new FunctionNode()
            {
                Identifier = funcName
            };

            line = line.Substring(m.Length);

            m = paramRegex.Match(line);
            while (m.Success)
            {
                string argName  = CharacterUtils.UnEscapeName(m.Groups[1].Value, _errorContainer);
                string kindName = CharacterUtils.UnEscapeName(m.Groups[2].Value, _errorContainer);

                functionNode.Args.Add(new TypedNameNode
                {
                    Identifier = argName,
                    Kind       = new TypeNode
                    {
                        TypeName = kindName
                    }
                });

                line = line.Substring(m.Length).TrimStart(',', ' ');
                m    = paramRegex.Match(line);
            }

            if (line != ")")
            {
                _errorContainer.ParseError(p.Span, $"Missing closing ')' in function definition");
                throw new DocumentException();
            }

            while (true)
            {
                p = _yaml.ReadNext();
                switch (p.Kind)
                {
                case YamlTokenKind.EndObj:
                    return(functionNode);

                // Expecting N+1 child objs where one is ThisProperty and the others N are the args
                case YamlTokenKind.StartObj:
                    functionNode.Metadata.Add(ParseArgMetadataBlock(p));
                    break;

                case YamlTokenKind.Error:
                    _errorContainer.ParseError(p.Span, p.Value);
                    return(null);

                default:
                    _errorContainer.ParseError(p.Span, $"Unexpected yaml token: {p}");
                    throw new DocumentException();
                }
            }
        }
Esempio n. 3
0
        internal static bool TryParseIdent(string source, out string parsed, out int length)
        {
            length = 0;
            parsed = null;
            if (source.Length == 0)
            {
                return(false);
            }

            var i                 = 0;
            var result            = new StringBuilder();
            var hasDelimiterStart = CharacterUtils.IsIdentDelimiter(source[i]);
            var hasDelimiterEnd   = false;

            if (!hasDelimiterStart)
            {
                // Simple identifier.
                while (i < source.Length && CharacterUtils.IsSimpleIdentCh(source[i]))
                {
                    result.Append(source[i]);
                    ++i;
                }
                parsed = result.ToString();
                length = i;
                return(true);
            }

            // Delimited identifier.
            ++i;

            // Accept any characters up to the next unescaped identifier delimiter.
            for (; ;)
            {
                if (i >= source.Length)
                {
                    break;
                }

                if (CharacterUtils.IsIdentDelimiter(source[i]))
                {
                    if (i + 1 < source.Length && CharacterUtils.IsIdentDelimiter(source[i + 1]))
                    {
                        // Escaped delimiter.
                        result.Append(source[i]);
                        i += 2;
                    }
                    else
                    {
                        // End of the identifier.
                        hasDelimiterEnd = true;
                        ++i;
                        break;
                    }
                }
                else
                {
                    result.Append(source[i]);
                    ++i;
                }
            }

            if (hasDelimiterStart == hasDelimiterEnd && result.Length > 0)
            {
                length = i;
                parsed = result.ToString();
                return(true);
            }
            return(false);
        }