Ejemplo n.º 1
0
        /// <summary>
        /// Возвращает токены между ';' и 'завершить'.
        /// </summary>
        public static TokenList GetCaseBody(TokenList tokens, out int counter, int index)
        {
            int       firstIndex = tokens.IndexOf(":") + 1;
            int       lastIndex  = tokens.IndexOf(KeywordType.Break);
            TokenList list       = tokens.GetRange(firstIndex, lastIndex);

            if (list.Count == 0)
            {
                throw new EmptyBodyException("Конструкция 'случай' с пустым телом", lineIndex);
            }

            counter = index + lastIndex - 1;
            return(list);
        }
Ejemplo n.º 2
0
        public void TokenList_Simple()
        {
            TokenList tokens = new TokenList();

            Assert.AreEqual(0, tokens.Count);

            CssToken[] expect = new CssToken[]
            {
                new CssToken(CssTokenType.Asterisk, 10, 1),
                new CssToken(CssTokenType.Asterisk, 20, 1),
                new CssToken(CssTokenType.Asterisk, 30, 1),
                new CssToken(CssTokenType.Asterisk, 40, 1),
                new CssToken(CssTokenType.Asterisk, 50, 1),
                new CssToken(CssTokenType.Asterisk, 60, 1),
            };

            // The token collection is supposed to automatically sort its contents,
            // so add the tokens in a weird order.

            tokens.Add(expect[3]);
            tokens.Add(expect[0]);
            tokens.Add(expect[1]);
            tokens.Add(expect[4]);
            tokens.Add(expect[2]);
            tokens.Insert(tokens.Count, expect[5]);

            Assert.AreEqual(expect.Length, tokens.Count);

            for (int i = 0; i < expect.Length; i++)
            {
                Assert.AreEqual(expect[i], tokens[i]);
                Assert.IsTrue(tokens.Contains(expect[i]));
                Assert.AreEqual(i, tokens.IndexOf(expect[i]));
            }

            // Test the binary search for the token collection

            Assert.AreEqual(0, tokens.FindInsertIndex(0, beforeExisting: true));
            Assert.AreEqual(0, tokens.FindInsertIndex(10, beforeExisting: true));
            Assert.AreEqual(1, tokens.FindInsertIndex(10, beforeExisting: false));
            Assert.AreEqual(3, tokens.FindInsertIndex(35, beforeExisting: true));
            Assert.AreEqual(3, tokens.FindInsertIndex(35, beforeExisting: false));
            Assert.AreEqual(4, tokens.FindInsertIndex(50, beforeExisting: true));
            Assert.AreEqual(5, tokens.FindInsertIndex(50, beforeExisting: false));
            Assert.AreEqual(6, tokens.FindInsertIndex(61, beforeExisting: true));
            Assert.AreEqual(6, tokens.FindInsertIndex(61, beforeExisting: false));
            Assert.AreEqual(6, tokens.FindInsertIndex(100, beforeExisting: true));
            Assert.AreEqual(6, tokens.FindInsertIndex(100, beforeExisting: false));

            Assert.IsTrue(tokens.Remove(expect[2]));
            Assert.AreEqual(expect.Length - 1, tokens.Count);
            Assert.AreEqual(expect[3], tokens[2]);

            tokens.Clear();
            Assert.AreEqual(0, tokens.Count);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Парсит тела конструкций, в том числе и новой функции.
        /// </summary>
        public static void Parse(TokenList tokens, out int counter, bool isRoot = false)
        {
            counter = 0;
            while (counter < tokens.Count)
            {
                BaseGenerator generator    = CodeManager.GetGenerator(parseMode);
                TokenList     nextTokens   = tokens.GetRange(counter);
                Token         currentToken = tokens[counter];
                Token         nextToken    = tokens.Get(counter + 1);

                if (currentToken.TypeIs(TokenType.NextLine))
                {
                    lineIndex++;
                    counter++;
                    continue;
                }

                if (currentToken.TypeIs(TokenType.Id))
                {
                    // <variableName> = <expression>;
                    if (nextToken.TypeIs(TokenType.AssignOperator))
                    {
                        string    variableName = currentToken.value;
                        TokenList expression   = nextTokens.GetRange(nextTokens.IndexOf("=") + 1, nextTokens.IndexOf(";"));

                        generator.AddVariableAssignment(variableName, expression, isRoot);
                        counter += nextTokens.IndexOf(";") + 1;
                    }
                    // <id>(<expression>);
                    else if (nextToken.TypeIs(TokenType.BeginParenthesis))
                    {
                        Token     name       = currentToken;
                        TokenList attributes = GetExpressionInParenthesis(nextTokens, errors: false);

                        if (attributes.Count == 0 && !nextTokens.Get(2).TypeIs(TokenType.EndParenthesis))
                        {
                            throw new ParseException($"После '(' при вызове функции без параметров ожидалось ')', а не '{nextToken}'", lineIndex);
                        }

                        generator.AddFunctionCall(name, attributes);
                        counter += nextTokens.IndexOf(";") + 1;
                    }
                    else
                    {
                        throw new ParseException($"После '{currentToken}' ожидалось '=' либо '(', а не '{nextToken}'", lineIndex);
                    }
                }
                else if (currentToken.TypeIs(TokenType.Keyword))
                {
                    // функция <functionName>(<parameters>) { <functionBody> }
                    if (currentToken.TypeIs(KeywordType.Function))
                    {
                        NewFunction newFunction = CodeManager.NewFunction;
                        string      name        = nextToken.value;
                        TokenList   parameters  = GetExpressionInParenthesis(nextTokens, errors: false);
                        TokenList   body        = GetBody(nextTokens, out counter, counter);

                        if (!nextToken.TypeIs(TokenType.Id))
                        {
                            throw new ParseException($"После ключевого слова 'функция' ожидалось название объявляемой функции, а не '{nextToken}'", lineIndex);
                        }

                        if (!nextTokens.Get(2).TypeIs(TokenType.BeginParenthesis))
                        {
                            throw new ParseException($"После названия функции ожидалось '(', а не '{nextToken}'", lineIndex);
                        }

                        if (parameters.Count == 0 && !nextTokens.Get(3).TypeIs(TokenType.EndParenthesis))
                        {
                            throw new ParseException($"После '(' при объявлении функции без параметров ожидалось ')', а не '{nextToken}'", lineIndex);
                        }

                        parameters.DeleteAll(",");
                        newFunction.AddFunctionHeader(name, parameters);
                        parseMode = ParseMode.FunctionCreation;
                        Parse(body, out _);
                        newFunction.Create();
                        parseMode = ParseMode.Default;
                    }
                    // если (<expresion>) { <body> }
                    else if (currentToken.TypeIs(KeywordType.If))
                    {
                        TokenList expression = GetExpressionInParenthesis(nextTokens);
                        TokenList body       = GetBody(nextTokens, out counter, counter);

                        if (!nextToken.TypeIs(TokenType.BeginParenthesis))
                        {
                            throw new ParseException($"После ')' ожидалось '{{', а не {nextToken}", lineIndex);
                        }

                        generator.AddIfConstruction(expression);
                        Parse(body, out _);
                        generator.AddConstructionEnd();
                    }
                    // иначе { <body> }
                    else if (currentToken.TypeIs(KeywordType.Else))
                    {
                        TokenList body = GetBody(nextTokens, out counter, counter);

                        generator.AddElseConstruction();
                        Parse(body, out _);
                        generator.AddConstructionEnd();
                    }
                    // делать { <body> } пока (<expression>)
                    else if (currentToken.TypeIs(KeywordType.Do))
                    {
                        TokenList body = GetBody(nextTokens, out counter, counter);

                        generator.AddDoConstruction();
                        Parse(body, out _);
                        generator.AddConstructionEnd();
                        nextTokens   = tokens.GetRange(counter);
                        currentToken = tokens[counter];

                        if (currentToken.TypeIs(KeywordType.While))
                        {
                            TokenList expression = GetExpressionInParenthesis(nextTokens);

                            if (expression.Count == 0)
                            {
                                throw new ParseException($"Конструкция 'пока' без выражения", lineIndex);
                            }

                            generator.AddEndingWhileConstruction(expression);
                            counter += nextTokens.IndexOf(";") + 1;
                        }
                        else
                        {
                            throw new ParseException($"После окончания конструкции 'делать' ожидалось ключевое слово 'пока'", lineIndex);
                        }
                    }
                    // пока (<expression>) { <body> }
                    else if (currentToken.TypeIs(KeywordType.While))
                    {
                        TokenList expression = GetExpressionInParenthesis(nextTokens);
                        TokenList body       = GetBody(nextTokens, out counter, counter);

                        generator.AddWhileConstruction(expression);
                        Parse(body, out _);
                        generator.AddConstructionEnd();
                    }
                    // пробовать { <tryBody> } отловить [(<errorValue>)] { <catchBody> }
                    else if (currentToken.TypeIs(KeywordType.Try))
                    {
                        TokenList tryBody = GetBody(nextTokens, out counter, counter);

                        generator.AddTryConstruction();
                        Parse(tryBody, out _);
                        generator.AddConstructionEnd();

                        nextTokens   = tokens.GetRange(counter);
                        currentToken = tokens[counter];

                        if (currentToken.TypeIs(KeywordType.Catch))
                        {
                            TokenList expression = GetExpressionInParenthesis(nextTokens, errors: false);
                            TokenList catchBody  = GetBody(nextTokens, out counter, counter);

                            if (expression.Count == 1 && expression[0].TypeIs(TokenType.Id))
                            {
                                generator.AddCatchConstruction(expression[0]);
                            }
                            else
                            {
                                generator.AddCatchConstruction();
                            }

                            Parse(catchBody, out _);
                            generator.AddConstructionEnd();
                        }
                    }
                    // определить (<value>) { <body> }
                    else if (currentToken.TypeIs(KeywordType.Switch))
                    {
                        TokenList expression = GetExpressionInParenthesis(nextTokens);
                        TokenList body       = GetBody(nextTokens, out counter, counter);

                        if (expression.Count == 1 && expression[0].TypeIs(TokenType.Id))
                        {
                            generator.AddSwitchConstruction(expression[0]);
                            ParseSwitch(body);
                            generator.AddConstructionEnd();
                        }
                    }
                    // использовать ...
                    else if (currentToken.TypeIs(KeywordType.Use))
                    {
                        // ссылки "<path>"
                        if (nextToken.TypeIs(KeywordType.Links) && nextTokens.Get(2).TypeIs(TokenType.String) &&
                            Path.GetExtension(nextTokens[2].value) == GlobalParams.linksExtention)
                        {
                            CodeManager.UpdateNamesMap(nextTokens[2].value);
                        }
                        // <id>
                        else if (nextToken.TypeIs(TokenType.Id))
                        {
                            Compilator.AddUsing(nextToken.ToString());
                            Compilator.AddClassRef(nextToken.ToString());
                        }

                        counter += nextTokens.IndexOf(";") + 1;
                    }
                    // импорт ...
                    else if (currentToken.TypeIs(KeywordType.Import))
                    {
                        if (nextToken.TypeIs(TokenType.String))
                        {
                            string path = nextToken.value;
                            if (File.Exists(path))
                            {
                                string extention = Path.GetExtension(path);
                                if (extention == GlobalParams.codeExtention)
                                {
                                    // ......
                                }
                                else
                                {
                                    Compilator.AddRef(path);
                                }
                            }
                        }
                        counter += nextTokens.IndexOf(";") + 1;
                    }
                    else
                    {
                        throw new ParseException($"На первой позиции не ожидалось ключевое слово {currentToken}", lineIndex);
                    }
                }
                else
                {
                    throw new ParseException($"Не удалось распознать слово '{currentToken}'", lineIndex);
                }
            }
        }