Ejemplo n.º 1
0
        public SyntaxNode Parse(string token, int lineCount, SyntaxNode parent = null)
        {
            string inner = GetInnerString(token);

            if (inner == null)
            {
                return(null);
            }
            if (string.IsNullOrWhiteSpace(inner))
            {
                return(new ListNode(parent, new List <SyntaxNode>()));
            }

            int  currentIndex     = 0;
            int  openParentheses  = 0;
            int  closeParentheses = 0;
            int  startIndex       = 0;
            bool startedString    = false;
            bool startedRange     = false;

            ListNode          currentList = new ListNode(parent, new List <SyntaxNode>(), lineCount);
            List <SyntaxNode> children    = new List <SyntaxNode>();

            while (currentIndex < inner.Length)
            {
                if (inner[currentIndex] == '(')
                {
                    openParentheses++;
                }
                else if (inner[currentIndex] == ')')
                {
                    closeParentheses++;
                }
                else if (inner[currentIndex] == ';')
                {
                    int endIndex = inner.IndexOf('\n', currentIndex);
                    currentIndex = endIndex == -1 ? inner.Length : endIndex + 1;
                    continue;
                }

                if (closeParentheses > openParentheses)
                {
                    throw currentList.CreateParseException(lineCount, currentIndex, $"Mismatched parenthesis:\n\t{inner}");
                }

                currentIndex++;
                if ((currentIndex == inner.Length || char.IsWhiteSpace(inner[currentIndex]) || inner[currentIndex] == ')') && openParentheses == closeParentheses)
                {
                    var nextInner = inner.Substring(startIndex, currentIndex - startIndex);
                    lineCount += nextInner.Count(c => c == '\n');
                    string currentInner     = nextInner.Trim();
                    int    childShouldQuote = 0;
                    if (currentInner.StartsWith('`'))
                    {
                        if (currentInner.StartsWith("``"))
                        {
                            childShouldQuote++;
                        }
                        currentInner = currentInner.Replace("`", "");
                        childShouldQuote++;
                    }
                    if (stringParser.StartsString(currentInner))
                    {
                        startedString = true;
                        continue;
                    }
                    if (rangeParser.StartsRange(currentInner))
                    {
                        startedRange = true;
                        continue;
                    }

                    SyntaxNode item = identifierParser.Parse(currentInner, currentList)
                                      ?? numericParser.Parse(currentInner, currentList)
                                      ?? stringParser.Parse(currentInner, currentList)
                                      ?? rangeParser.Parse(currentInner, currentList);

                    if (item == null)
                    {
                        var innerString = GetInnerString(currentInner);
                        if (innerString == null)
                        {
                            if (StartsComment(currentInner) || currentInner.Trim() == "")
                            {
                                startIndex   = currentIndex;
                                currentInner = null;
                            }
                            else
                            {
                                throw currentList.CreateParseException(lineCount, currentIndex, "garbage in list");
                            }
                        }
                        else
                        {
                            item = string.IsNullOrWhiteSpace(innerString)
                                ? new ListNode(currentList, new List <SyntaxNode>())
                                : Parse(currentInner, lineCount, currentList);
                        }
                    }

                    if (item != null)
                    {
                        if (IsNamedParameter(item))
                        {
                            currentList.NamedParameterList = true;
                        }
                        if (item is StringNode)
                        {
                            startedString = false;
                        }
                        if (item is RangeNode)
                        {
                            startedRange = false;
                        }
                        QuoteChild(childShouldQuote, currentList, item, children);
                    }
                    else if (!string.IsNullOrWhiteSpace(currentInner) && StartsComment(currentInner))
                    {
                        throw currentList.CreateParseException(lineCount, currentIndex, $"trash in list\n\t'{currentInner}'");
                    }

                    startIndex = currentIndex + 1;
                }
            }

            if (startedString)
            {
                throw currentList.CreateParseException(lineCount, currentIndex, "unfinished string in list");
            }
            if (startedRange)
            {
                throw currentList.CreateParseException(lineCount, currentIndex, "unfinished range in list");
            }

            currentList.Children.AddRange(children);

            return(currentList);
        }