Esempio n. 1
0
        private void ApplyGrammar(List <ASTNode> nodes, int from = 0, bool allowNoSemicolon = false, params GrammarRule[] additionalPatterns)
        {
            int i = from;

            while (i < nodes.Count)
            {
                if (nodes[i] is NopNode)
                {
                    nodes.RemoveAt(i); // Remove the nopnode -> Should never pass through this method
                    continue;
                }

                if (additionalPatterns != null)
                {
                    bool skipStandard = false;
                    for (int j = 0; j < additionalPatterns.Length; j++)
                    {
                        if (additionalPatterns[j](nodes, ref i))
                        {
                            skipStandard = true;
                            break;
                        }
                    }
                    if (skipStandard)
                    {
                        i++;
                        continue;
                    }
                }

                if (nodes[i].LexicalType == LexTokenType.Keyword)
                {
                    switch (nodes[i].Content)
                    {
                    case "class":
                        this.ApplyClassGrammar(nodes, ref i);
                        break;

                    case "return":
                        this.ApplyReturnStatementGrammar(nodes, i);
                        break;

                    case "if":
                        this.ApplyIfStatementGrammar(nodes, i);
                        break;

                    case "while":
                        this.ApplyWhileStatementGrammar(nodes, i);
                        break;

                    case "for":
                        this.ApplyForStatementGrammar(nodes, i);
                        break;

                    case "do":
                        this.ApplyDoStatementGrammar(nodes, i);
                        break;

                    case "public":
                    case "private":
                    case "protected":
                    case "external":
                    case "internal":
                        nodes[i] = new AccessModifierNode(nodes[i].Content, nodes[i].Pos);
                        break;

                    case "namespace":
                        this.ApplyNamespaceGrammar(nodes, i);
                        break;

                    default:
                        throw new NotImplementedException(nodes[i].Content);
                    }
                }
                else if (TypeSequence <ASTNode, IdentifierNode, IdentifierNode, SeperatorNode> .Match(nodes, i))   // int x;

                {
                    this.ApplyModifierGrammar(nodes, ref i, out AccessModifierNode accessModifier, out HashSet <StorageModifierNode> storageModifiers);

                    nodes[i] = new VarDeclNode(nodes[i].Pos, nodes[i].ToTypeIdentifier(), nodes[i + 1].Content);
                    this.ApplyModifiers(nodes[i] as VarDeclNode, accessModifier, storageModifiers);
                    this.RemoveNode(nodes, i + 1, 2);
                }
                else if (TypeSequence <ASTNode, IdentifierNode, AssignmentNode, SeperatorNode> .Match(nodes, i) || TypeSequence <ASTNode, TypeArrayIdentifierNode, AssignmentNode, SeperatorNode> .Match(nodes, i))  // int x = <expr>; OR int[] x = <expr>;

                {
                    this.ApplyModifierGrammar(nodes, ref i, out AccessModifierNode accessModifier, out HashSet <StorageModifierNode> storageModifiers);

                    AssignmentNode assignOp    = nodes[i + 1] as AssignmentNode;
                    bool           doRecursive = true;

                    if (assignOp.Right is ScopeNode initializer)
                    {
                        if (this.ApplyInitializerGrammar(initializer, out IInitializer init))
                        {
                            assignOp.Update(LeftRight.LHS, assignOp.Left);
                            assignOp.Update(LeftRight.RHS, init as ASTNode);
                            doRecursive = false;
                        }
                    }
                    if (doRecursive)
                    {
                        this.ApplySingleNodeGrammar(assignOp.Right, true);
                    }
                    nodes[i] = new VarDeclNode(nodes[i].Pos, nodes[i].ToTypeIdentifier(), assignOp);
                    this.ApplyModifiers(nodes[i] as VarDeclNode, accessModifier, storageModifiers);
                    this.RemoveNode(nodes, i + 1, 2);
                }
                else if (TypeSequence <ASTNode, IdentifierNode, ExpressionNode, ASTNode, IdentifierNode, ScopeNode> .Match(nodes, i))
                {
                    if (nodes[i + 2].Content.CompareTo(":") == 0)
                    {
                        this.ApplyFunctionGrammar(nodes, ref i);
                    }
                }
                else if (TypeSequence <ASTNode, IExpr, ExpressionNode> .Match(nodes, i))
                {
                    ExpressionNode groupNode = nodes[i + 1] as ExpressionNode;
                    this.ApplyGrammar(groupNode.Nodes, 0, true); // apply grammar on arguments ==> should lead to a nice arg1,arg2,arg3 setup (otherwise error)
                    CallNode callNode = new CallNode(nodes[i], nodes[i].Pos)
                    {
                        Arguments = new ArgumentsNode(groupNode) // Note: This constructor will apply the grammar rule on its own
                    };
                    if (!callNode.Arguments.IsValid)
                    {
                        throw new Exception();
                    }
                    this.RemoveNode(nodes, i + 1);
                    nodes[i] = callNode;
                }
                else if (nodes[i] is IGroupedASTNode groupNode)
                {
                    this.ApplyGrammar(groupNode.Nodes);
                }
                else
                {
                    ApplySingleNodeGrammar(nodes[i]);
                }

                if (nodes[i] is IExpr && i + 1 < nodes.Count && nodes[i + 1] is SeperatorNode sepNode && sepNode.Content.CompareTo(";") == 0)
                {
                    this.RemoveNode(nodes, i + 1);
                }